aboutsummaryrefslogtreecommitdiff
path: root/src/or/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/config.c')
-rw-r--r--src/or/config.c1325
1 files changed, 800 insertions, 525 deletions
diff --git a/src/or/config.c b/src/or/config.c
index 810f1e9a7a..8f4b5ab5a1 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -1,16 +1,66 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file config.c
- * \brief Code to parse and interpret configuration files.
+ * \brief Code to interpret the user's configuration of Tor.
+ *
+ * This module handles torrc configuration file, including parsing it,
+ * combining it with torrc.defaults and the command line, allowing
+ * user changes to it (via editing and SIGHUP or via the control port),
+ * writing it back to disk (because of SAVECONF from the control port),
+ * and -- most importantly, acting on it.
+ *
+ * The module additionally has some tools for manipulating and
+ * inspecting values that are calculated as a result of the
+ * configured options.
+ *
+ * <h3>How to add new options</h3>
+ *
+ * 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 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.
+ * <li>The manual in doc/tor.1.txt, to document what the new option
+ * is, and how it works.
+ * </ul>
+ *
+ * Additionally, you might need to edit these places too:
+ * <ul>
+ * <li>options_validate() 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.
+ * <li>options_transition_affects_descriptor(), in case changes in the
+ * option might require a Tor relay to build and publish a new server
+ * descriptor.
+ * <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.
+ * </ul>
+ *
+ * <h3>Changing the value of an option</h3>
+ *
+ * Because of the SAVECONF command from the control port, it's a bad
+ * idea to change the value of any user-configured option in the
+ * or_options_t. If you want to sometimes do this anyway, we recommend
+ * that you create a secondary field in or_options_t; that you have the
+ * user option linked only to the secondary field; that you use the
+ * secondary field to initialize the one that Tor actually looks at; and that
+ * you use the one Tor looks as the one that you modify.
**/
#define CONFIG_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "compat.h"
#include "addressmap.h"
#include "channel.h"
@@ -19,10 +69,12 @@
#include "circuitmux.h"
#include "circuitmux_ewma.h"
#include "circuitstats.h"
+#include "compress.h"
#include "config.h"
#include "connection.h"
#include "connection_edge.h"
#include "connection_or.h"
+#include "consdiffmgr.h"
#include "control.h"
#include "confparse.h"
#include "cpuworker.h"
@@ -40,6 +92,7 @@
#include "relay.h"
#include "rendclient.h"
#include "rendservice.h"
+#include "hs_config.h"
#include "rephist.h"
#include "router.h"
#include "sandbox.h"
@@ -50,7 +103,6 @@
#include "statefile.h"
#include "transports.h"
#include "ext_orport.h"
-#include "torgzip.h"
#ifdef _WIN32
#include <shlobj.h>
#endif
@@ -63,9 +115,9 @@
* Coverity. Here's a kludge to unconfuse it.
*/
# define __INCLUDE_LEVEL__ 2
-# endif
+#endif /* defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) */
#include <systemd/sd-daemon.h>
-#endif
+#endif /* defined(HAVE_SYSTEMD) */
/* Prefix used to indicate a Unix socket in a FooPort configuration. */
static const char unix_socket_prefix[] = "unix:";
@@ -121,21 +173,38 @@ static config_abbrev_t option_abbrevs_[] = {
{ NULL, NULL, 0, 0},
};
+/** dummy instance of or_options_t, used for type-checking its
+ * members with CONF_CHECK_VAR_TYPE. */
+DUMMY_TYPECHECK_INSTANCE(or_options_t);
+
/** An entry for config_vars: "The option <b>name</b> has type
* CONFIG_TYPE_<b>conftype</b>, and corresponds to
* or_options_t.<b>member</b>"
*/
#define VAR(name,conftype,member,initvalue) \
- { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member), \
- initvalue }
+ { name, CONFIG_TYPE_ ## conftype, offsetof(or_options_t, member), \
+ initvalue CONF_TEST_MEMBERS(or_options_t, conftype, member) }
/** As VAR, but the option name and member name are the same. */
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
/** An entry for config_vars: "The option <b>name</b> is obsolete." */
+#ifdef TOR_UNIT_TESTS
+#define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL, {.INT=NULL} }
+#else
#define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
+#endif
-#define VPORT(member,conftype,initvalue) \
- VAR(#member, conftype, member ## _lines, initvalue)
+/**
+ * Macro to declare *Port options. Each one comes in three entries.
+ * For example, most users should use "SocksPort" to configure the
+ * socks port, but TorBrowser wants to use __SocksPort so that it
+ * isn't stored by SAVECONF. The SocksPortLines virtual option is
+ * used to query both options from the controller.
+ */
+#define VPORT(member) \
+ VAR(#member "Lines", LINELIST_V, member ## _lines, NULL), \
+ VAR(#member, LINELIST_S, member ## _lines, NULL), \
+ VAR("__" #member, LINELIST_S, member ## _lines, NULL)
/** Array of configuration options. Until we disallow nonstandard
* abbreviations, order is significant, since the first matching option will
@@ -146,11 +215,11 @@ static config_var_t option_vars_[] = {
VAR("AccountingRule", STRING, AccountingRule_option, "max"),
V(AccountingStart, STRING, NULL),
V(Address, STRING, NULL),
- V(AllowDotExit, BOOL, "0"),
- V(AllowInvalidNodes, CSV, "middle,rendezvous"),
+ OBSOLETE("AllowDotExit"),
+ OBSOLETE("AllowInvalidNodes"),
V(AllowNonRFC953Hostnames, BOOL, "0"),
- V(AllowSingleHopCircuits, BOOL, "0"),
- V(AllowSingleHopExits, BOOL, "0"),
+ OBSOLETE("AllowSingleHopCircuits"),
+ OBSOLETE("AllowSingleHopExits"),
V(AlternateBridgeAuthority, LINELIST, NULL),
V(AlternateDirAuthority, LINELIST, NULL),
OBSOLETE("AlternateHSAuthority"),
@@ -163,14 +232,14 @@ static config_var_t option_vars_[] = {
V(AuthDirInvalidCCs, CSV, ""),
V(AuthDirFastGuarantee, MEMUNIT, "100 KB"),
V(AuthDirGuardBWGuarantee, MEMUNIT, "2 MB"),
- V(AuthDirPinKeys, BOOL, "0"),
+ V(AuthDirPinKeys, BOOL, "1"),
V(AuthDirReject, LINELIST, NULL),
V(AuthDirRejectCCs, CSV, ""),
OBSOLETE("AuthDirRejectUnlisted"),
OBSOLETE("AuthDirListBadDirs"),
V(AuthDirListBadExits, BOOL, "0"),
V(AuthDirMaxServersPerAddr, UINT, "2"),
- V(AuthDirMaxServersPerAuthAddr,UINT, "5"),
+ OBSOLETE("AuthDirMaxServersPerAuthAddr"),
V(AuthDirHasIPv6Connectivity, BOOL, "0"),
VAR("AuthoritativeDirectory", BOOL, AuthoritativeDir, "0"),
V(AutomapHostsOnResolve, BOOL, "0"),
@@ -183,10 +252,13 @@ static config_var_t option_vars_[] = {
V(BridgePassword, STRING, NULL),
V(BridgeRecordUsageByCountry, BOOL, "1"),
V(BridgeRelay, BOOL, "0"),
+ V(BridgeDistribution, STRING, NULL),
V(CellStatistics, BOOL, "0"),
+ V(PaddingStatistics, BOOL, "1"),
V(LearnCircuitBuildTimeout, BOOL, "1"),
V(CircuitBuildTimeout, INTERVAL, "0"),
- V(CircuitIdleTimeout, INTERVAL, "1 hour"),
+ OBSOLETE("CircuitIdleTimeout"),
+ V(CircuitsAvailableTimeout, INTERVAL, "0"),
V(CircuitStreamTimeout, INTERVAL, "0"),
V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/
V(ClientDNSRejectInternalAddresses, BOOL,"1"),
@@ -203,8 +275,8 @@ static config_var_t option_vars_[] = {
V(ConstrainedSockets, BOOL, "0"),
V(ConstrainedSockSize, MEMUNIT, "8192"),
V(ContactInfo, STRING, NULL),
- V(ControlListenAddress, LINELIST, NULL),
- VPORT(ControlPort, LINELIST, NULL),
+ OBSOLETE("ControlListenAddress"),
+ VPORT(ControlPort),
V(ControlPortFileGroupReadable,BOOL, "0"),
V(ControlPortWriteToFile, FILENAME, NULL),
V(ControlSocket, LINELIST, NULL),
@@ -220,9 +292,9 @@ static config_var_t option_vars_[] = {
V(DisableNetwork, BOOL, "0"),
V(DirAllowPrivateAddresses, BOOL, "0"),
V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"),
- V(DirListenAddress, LINELIST, NULL),
+ OBSOLETE("DirListenAddress"),
V(DirPolicy, LINELIST, NULL),
- VPORT(DirPort, LINELIST, NULL),
+ VPORT(DirPort),
V(DirPortFrontPage, FILENAME, NULL),
VAR("DirReqStatistics", BOOL, DirReqStatistics_option, "1"),
VAR("DirAuthority", LINELIST, DirAuthorities, NULL),
@@ -240,8 +312,8 @@ static config_var_t option_vars_[] = {
OBSOLETE("DisableIOCP"),
OBSOLETE("DisableV2DirectoryInfo_"),
OBSOLETE("DynamicDHGroups"),
- VPORT(DNSPort, LINELIST, NULL),
- V(DNSListenAddress, LINELIST, NULL),
+ VPORT(DNSPort),
+ OBSOLETE("DNSListenAddress"),
/* DoS circuit creation options. */
V(DoSCircuitCreationEnabled, AUTOBOOL, "auto"),
V(DoSCircuitCreationMinConnections, UINT, "0"),
@@ -265,7 +337,7 @@ static config_var_t option_vars_[] = {
V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "10 minutes"),
V(ExcludeNodes, ROUTERSET, NULL),
V(ExcludeExitNodes, ROUTERSET, NULL),
- V(ExcludeSingleHopRelays, BOOL, "1"),
+ OBSOLETE("ExcludeSingleHopRelays"),
V(ExitNodes, ROUTERSET, NULL),
V(ExitPolicy, LINELIST, NULL),
V(ExitPolicyRejectPrivate, BOOL, "1"),
@@ -273,17 +345,19 @@ static config_var_t option_vars_[] = {
V(ExitPortStatistics, BOOL, "0"),
V(ExtendAllowPrivateAddresses, BOOL, "0"),
V(ExitRelay, AUTOBOOL, "auto"),
- VPORT(ExtORPort, LINELIST, NULL),
+ VPORT(ExtORPort),
V(ExtORPortCookieAuthFile, STRING, NULL),
V(ExtORPortCookieAuthFileGroupReadable, BOOL, "0"),
V(ExtraInfoStatistics, BOOL, "1"),
+ V(ExtendByEd25519ID, AUTOBOOL, "auto"),
V(FallbackDir, LINELIST, NULL),
+
V(UseDefaultFallbackDirs, BOOL, "1"),
OBSOLETE("FallbackNetworkstatusFile"),
V(FascistFirewall, BOOL, "0"),
V(FirewallPorts, CSV, ""),
- V(FastFirstHopPK, AUTOBOOL, "auto"),
+ OBSOLETE("FastFirstHopPK"),
V(FetchDirInfoEarly, BOOL, "0"),
V(FetchDirInfoExtraEarly, BOOL, "0"),
V(FetchServerDescriptors, BOOL, "1"),
@@ -299,7 +373,7 @@ static config_var_t option_vars_[] = {
SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"),
V(GeoIPv6File, FILENAME,
SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"),
-#endif
+#endif /* defined(_WIN32) */
OBSOLETE("Group"),
V(GuardLifetime, INTERVAL, "0 minutes"),
V(HardwareAccel, BOOL, "0"),
@@ -318,16 +392,17 @@ static config_var_t option_vars_[] = {
VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL),
- V(HiddenServiceStatistics, BOOL, "1"),
+ VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"),
V(HidServAuth, LINELIST, NULL),
- V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"),
- V(CloseHSServiceRendCircuitsImmediatelyOnTimeout, BOOL, "0"),
+ OBSOLETE("CloseHSClientCircuitsImmediatelyOnTimeout"),
+ OBSOLETE("CloseHSServiceRendCircuitsImmediatelyOnTimeout"),
V(HiddenServiceSingleHopMode, BOOL, "0"),
V(HiddenServiceNonAnonymousMode,BOOL, "0"),
V(HTTPProxy, STRING, NULL),
V(HTTPProxyAuthenticator, STRING, NULL),
V(HTTPSProxy, STRING, NULL),
V(HTTPSProxyAuthenticator, STRING, NULL),
+ VPORT(HTTPTunnelPort),
V(IPv6Exit, BOOL, "0"),
VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL),
V(ServerTransportListenAddr, LINELIST, NULL),
@@ -350,27 +425,31 @@ static config_var_t option_vars_[] = {
V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"),
V(MaxCircuitDirtiness, INTERVAL, "10 minutes"),
V(MaxClientCircuitsPending, UINT, "32"),
+ V(MaxConsensusAgeForDiffs, INTERVAL, "0 seconds"),
VAR("MaxMemInQueues", MEMUNIT, MaxMemInQueues_raw, "0"),
OBSOLETE("MaxOnionsPending"),
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"),
V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"),
- V(MyFamily, STRING, NULL),
+ VAR("MyFamily", LINELIST, MyFamily_lines, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
OBSOLETE("NamingAuthoritativeDirectory"),
- V(NATDListenAddress, LINELIST, NULL),
- VPORT(NATDPort, LINELIST, NULL),
+ OBSOLETE("NATDListenAddress"),
+ VPORT(NATDPort),
V(Nickname, STRING, NULL),
- V(PredictedPortsRelevanceTime, INTERVAL, "1 hour"),
- V(WarnUnsafeSocks, BOOL, "1"),
+ OBSOLETE("PredictedPortsRelevanceTime"),
+ OBSOLETE("WarnUnsafeSocks"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
+ V(NoExec, BOOL, "0"),
V(NumCPUs, UINT, "0"),
V(NumDirectoryGuards, UINT, "0"),
V(NumEntryGuards, UINT, "0"),
V(OfflineMasterKey, BOOL, "0"),
- V(ORListenAddress, LINELIST, NULL),
- VPORT(ORPort, LINELIST, NULL),
+ OBSOLETE("ORListenAddress"),
+ VPORT(ORPort),
V(OutboundBindAddress, LINELIST, NULL),
+ V(OutboundBindAddressOR, LINELIST, NULL),
+ V(OutboundBindAddressExit, LINELIST, NULL),
OBSOLETE("PathBiasDisableRate"),
V(PathBiasCircThreshold, INT, "-1"),
@@ -416,6 +495,8 @@ static config_var_t option_vars_[] = {
V(RecommendedClientVersions, LINELIST, NULL),
V(RecommendedServerVersions, LINELIST, NULL),
V(RecommendedPackages, LINELIST, NULL),
+ V(ReducedConnectionPadding, BOOL, "0"),
+ V(ConnectionPadding, AUTOBOOL, "auto"),
V(RefuseUnknownExits, AUTOBOOL, "auto"),
V(RejectPlaintextPorts, CSV, ""),
V(RelayBandwidthBurst, MEMUNIT, "0"),
@@ -435,13 +516,16 @@ static config_var_t option_vars_[] = {
V(ServerDNSSearchDomains, BOOL, "0"),
V(ServerDNSTestAddresses, CSV,
"www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"),
- V(SchedulerLowWaterMark__, MEMUNIT, "100 MB"),
- V(SchedulerHighWaterMark__, MEMUNIT, "101 MB"),
- V(SchedulerMaxFlushCells__, UINT, "1000"),
+ OBSOLETE("SchedulerLowWaterMark__"),
+ OBSOLETE("SchedulerHighWaterMark__"),
+ OBSOLETE("SchedulerMaxFlushCells__"),
+ V(KISTSchedRunInterval, MSEC_INTERVAL, "0 msec"),
+ V(KISTSockBufSizeFactor, DOUBLE, "1.0"),
+ V(Schedulers, CSV, "KIST,KISTLite,Vanilla"),
V(ShutdownWaitLength, INTERVAL, "30 seconds"),
- V(SocksListenAddress, LINELIST, NULL),
+ OBSOLETE("SocksListenAddress"),
V(SocksPolicy, LINELIST, NULL),
- VPORT(SocksPort, LINELIST, NULL),
+ VPORT(SocksPort),
V(SocksTimeout, INTERVAL, "2 minutes"),
V(SSLKeyLifetime, INTERVAL, "0"),
OBSOLETE("StrictEntryNodes"),
@@ -452,23 +536,24 @@ static config_var_t option_vars_[] = {
V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"),
V(Tor2webMode, BOOL, "0"),
V(Tor2webRendezvousPoints, ROUTERSET, NULL),
- V(TLSECGroup, STRING, NULL),
+ OBSOLETE("TLSECGroup"),
V(TrackHostExits, CSV, NULL),
V(TrackHostExitsExpire, INTERVAL, "30 minutes"),
- V(TransListenAddress, LINELIST, NULL),
- VPORT(TransPort, LINELIST, NULL),
+ OBSOLETE("TransListenAddress"),
+ VPORT(TransPort),
V(TransProxyType, STRING, "default"),
OBSOLETE("TunnelDirConns"),
V(UpdateBridgesFromAuthority, BOOL, "0"),
V(UseBridges, BOOL, "0"),
VAR("UseEntryGuards", BOOL, UseEntryGuards_option, "1"),
- V(UseEntryGuardsAsDirGuards, BOOL, "1"),
+ OBSOLETE("UseEntryGuardsAsDirGuards"),
V(UseGuardFraction, AUTOBOOL, "auto"),
V(UseMicrodescriptors, AUTOBOOL, "auto"),
OBSOLETE("UseNTorHandshake"),
V(User, STRING, NULL),
OBSOLETE("UserspaceIOCPBuffers"),
V(AuthDirSharedRandomness, BOOL, "1"),
+ V(AuthDirTestEd25519LinkKeys, BOOL, "1"),
OBSOLETE("V1AuthoritativeDirectory"),
OBSOLETE("V2AuthoritativeDirectory"),
VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"),
@@ -510,11 +595,13 @@ static config_var_t option_vars_[] = {
"10800, 21600, 43200"),
/* With the ClientBootstrapConsensus*Download* below:
* Clients with only authorities will try:
- * - 3 authorities over 10 seconds, then wait 60 minutes.
+ * - at least 3 authorities over 10 seconds, then exponentially backoff,
+ * with the next attempt 3-21 seconds later,
* Clients with authorities and fallbacks will try:
- * - 2 authorities and 4 fallbacks over 21 seconds, then wait 60 minutes.
+ * - at least 2 authorities and 4 fallbacks over 21 seconds, then
+ * exponentially backoff, with the next attempts 4-33 seconds later,
* Clients will also retry when an application request arrives.
- * After a number of failed reqests, clients retry every 3 days + 1 hour.
+ * After a number of failed requests, clients retry every 3 days + 1 hour.
*
* Clients used to try 2 authorities over 10 seconds, then wait for
* 60 minutes or an application request.
@@ -533,7 +620,16 @@ static config_var_t option_vars_[] = {
* blackholed. Clients will try 3 directories simultaneously.
* (Relays never use simultaneous connections.) */
V(ClientBootstrapConsensusMaxInProgressTries, UINT, "3"),
- V(TestingBridgeDownloadSchedule, CSV_INTERVAL, "1200, 900, 900, 3600"),
+ /* When a client has any running bridges, check each bridge occasionally,
+ * whether or not that bridge is actually up. */
+ V(TestingBridgeDownloadSchedule, CSV_INTERVAL,
+ "10800, 25200, 54000, 111600, 262800"),
+ /* When a client is just starting, or has no running bridges, check each
+ * bridge a few times quickly, and then try again later. These schedules
+ * are much longer than the other schedules, because we try each and every
+ * configured bridge with this schedule. */
+ V(TestingBridgeBootstrapDownloadSchedule, CSV_INTERVAL,
+ "0, 30, 90, 600, 3600, 10800, 25200, 54000, 111600, 262800"),
V(TestingClientMaxIntervalWithoutRequest, INTERVAL, "10 minutes"),
V(TestingDirConnectionMaxStall, INTERVAL, "5 minutes"),
V(TestingConsensusMaxDownloadTries, UINT, "8"),
@@ -553,18 +649,16 @@ static config_var_t option_vars_[] = {
V(TestingDirAuthVoteHSDirIsStrict, BOOL, "0"),
VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "0"),
- { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
+ END_OF_CONFIG_VARS
};
/** Override default values with these if the user sets the TestingTorNetwork
* option. */
static const config_var_t testing_tor_network_defaults[] = {
- V(ServerDNSAllowBrokenConfig, BOOL, "1"),
V(DirAllowPrivateAddresses, BOOL, "1"),
V(EnforceDistinctSubnets, BOOL, "0"),
V(AssumeReachable, BOOL, "1"),
V(AuthDirMaxServersPerAddr, UINT, "0"),
- V(AuthDirMaxServersPerAuthAddr,UINT, "0"),
V(ClientBootstrapConsensusAuthorityDownloadSchedule, CSV_INTERVAL,
"0, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 16, 32, 60"),
V(ClientBootstrapConsensusFallbackDownloadSchedule, CSV_INTERVAL,
@@ -573,7 +667,7 @@ static const config_var_t testing_tor_network_defaults[] = {
"0, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 16, 32, 60"),
V(ClientBootstrapConsensusMaxDownloadTries, UINT, "80"),
V(ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries, UINT, "80"),
- V(ClientDNSRejectInternalAddresses, BOOL,"0"), // deprecated in 0.2.9.2-alpha
+ V(ClientDNSRejectInternalAddresses, BOOL,"0"),
V(ClientRejectInternalAddresses, BOOL, "0"),
V(CountPrivateBandwidth, BOOL, "1"),
V(ExitPolicyRejectPrivate, BOOL, "0"),
@@ -584,7 +678,6 @@ static const config_var_t testing_tor_network_defaults[] = {
V(TestingV3AuthInitialVotingInterval, INTERVAL, "150 seconds"),
V(TestingV3AuthInitialVoteDelay, INTERVAL, "20 seconds"),
V(TestingV3AuthInitialDistDelay, INTERVAL, "20 seconds"),
- V(TestingV3AuthVotingStartOffset, INTERVAL, "0"),
V(TestingAuthDirTimeToLearnReachability, INTERVAL, "0 minutes"),
V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"),
@@ -596,7 +689,9 @@ static const config_var_t testing_tor_network_defaults[] = {
"15, 20, 30, 60"),
V(TestingClientConsensusDownloadSchedule, CSV_INTERVAL, "0, 0, 5, 10, "
"15, 20, 30, 60"),
- V(TestingBridgeDownloadSchedule, CSV_INTERVAL, "60, 30, 30, 60"),
+ V(TestingBridgeDownloadSchedule, CSV_INTERVAL, "10, 30, 60"),
+ V(TestingBridgeBootstrapDownloadSchedule, CSV_INTERVAL, "0, 0, 5, 10, "
+ "15, 20, 30, 60"),
V(TestingClientMaxIntervalWithoutRequest, INTERVAL, "5 seconds"),
V(TestingDirConnectionMaxStall, INTERVAL, "30 seconds"),
V(TestingConsensusMaxDownloadTries, UINT, "80"),
@@ -609,7 +704,7 @@ static const config_var_t testing_tor_network_defaults[] = {
VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "1"),
V(RendPostPeriod, INTERVAL, "2 minutes"),
- { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
+ END_OF_CONFIG_VARS
};
#undef VAR
@@ -617,39 +712,19 @@ static const config_var_t testing_tor_network_defaults[] = {
#undef OBSOLETE
static const config_deprecation_t option_deprecation_notes_[] = {
- /* Deprecated since 0.2.9.2-alpha... */
- { "AllowDotExit", "Unrestricted use of the .exit notation can be used for "
- "a wide variety of application-level attacks." },
- { "AllowInvalidNodes", "There is no reason to enable this option; at best "
- "it will make you easier to track." },
- { "AllowSingleHopCircuits", "Almost no relays actually allow single-hop "
- "exits, making this option pointless." },
- { "AllowSingleHopExits", "Turning this on will make your relay easier "
- "to abuse." },
- { "ClientDNSRejectInternalAddresses", "Turning this on makes your client "
- "easier to fingerprint, and may open you to esoteric attacks." },
- { "ExcludeSingleHopRelays", "Turning it on makes your client easier to "
- "fingerprint." },
- { "FastFirstHopPK", "Changing this option does not make your client more "
- "secure, but does make it easier to fingerprint." },
- { "CloseHSClientCircuitsImmediatelyOnTimeout", "This option makes your "
- "client easier to fingerprint." },
- { "CloseHSServiceRendCircuitsImmediatelyOnTimeout", "This option makes "
- "your hidden services easier to fingerprint." },
- { "WarnUnsafeSocks", "Changing this option makes it easier for you "
- "to accidentally lose your anonymity by leaking DNS information" },
- { "TLSECGroup", "The default is a nice secure choice; the other option "
- "is less secure." },
- { "ControlListenAddress", "Use ControlPort instead." },
- { "DirListenAddress", "Use DirPort instead, possibly with the "
- "NoAdvertise sub-option" },
- { "DNSListenAddress", "Use DNSPort instead." },
- { "SocksListenAddress", "Use SocksPort instead." },
- { "TransListenAddress", "Use TransPort instead." },
- { "NATDListenAddress", "Use NATDPort instead." },
- { "ORListenAddress", "Use ORPort instead, possibly with the "
- "NoAdvertise sub-option" },
- /* End of options deprecated since 0.2.9.2-alpha. */
+ /* Deprecated since 0.3.2.0-alpha. */
+ { "HTTPProxy", "It only applies to direct unencrypted HTTP connections "
+ "to your directory server, which your Tor probably wasn't using." },
+ { "HTTPProxyAuthenticator", "HTTPProxy is deprecated in favor of HTTPSProxy "
+ "which should be used with HTTPSProxyAuthenticator." },
+ /* End of options deprecated since 0.3.2.1-alpha */
+
+ /* Options deprecated since 0.3.2.2-alpha */
+ { "ReachableDirAddresses", "It has no effect on relays, and has had no "
+ "effect on clients since 0.2.8." },
+ { "ClientPreferIPv6DirPort", "It has no effect on relays, and has had no "
+ "effect on clients since 0.2.8." },
+ /* End of options deprecated since 0.3.2.2-alpha. */
{ NULL, NULL }
};
@@ -665,7 +740,9 @@ 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 check_nickname_list(char **lst, const char *name, char **msg);
+static int normalize_nickname_list(config_line_t **normalized_out,
+ const config_line_t *lst, const char *name,
+ char **msg);
static char *get_bindaddr_from_transport_listen_line(const char *line,
const char *transport);
static int parse_ports(or_options_t *options, int validate_only,
@@ -674,7 +751,6 @@ static int parse_ports(or_options_t *options, int validate_only,
static int check_server_ports(const smartlist_t *ports,
const or_options_t *options,
int *num_low_ports_out);
-
static int validate_data_directory(or_options_t *options);
static int write_configuration_file(const char *fname,
const or_options_t *options);
@@ -700,7 +776,7 @@ static uint64_t compute_real_max_mem_in_queues(const uint64_t val,
STATIC config_format_t options_format = {
sizeof(or_options_t),
OR_OPTIONS_MAGIC,
- STRUCT_OFFSET(or_options_t, magic_),
+ offsetof(or_options_t, magic_),
option_abbrevs_,
option_deprecation_notes_,
option_vars_,
@@ -731,6 +807,9 @@ static int have_parsed_cmdline = 0;
static char *global_dirfrontpagecontents = NULL;
/** List of port_cfg_t for all configured ports. */
static smartlist_t *configured_ports = NULL;
+/** True iff we're currently validating options, and any calls to
+ * get_options() are likely to be bugs. */
+static int in_option_validation = 0;
/** Return the contents of our frontpage string, or NULL if not configured. */
MOCK_IMPL(const char*,
@@ -744,6 +823,7 @@ MOCK_IMPL(or_options_t *,
get_options_mutable, (void))
{
tor_assert(global_options);
+ tor_assert_nonfatal(! in_option_validation);
return global_options;
}
@@ -802,7 +882,7 @@ set_options(or_options_t *new_val, char **msg)
tor_free(line);
}
} else {
- smartlist_add(elements, tor_strdup(options_format.vars[i].name));
+ smartlist_add_strdup(elements, options_format.vars[i].name);
smartlist_add(elements, NULL);
}
}
@@ -870,9 +950,14 @@ or_options_free(or_options_t *options)
rs, routerset_free(rs));
smartlist_free(options->NodeFamilySets);
}
+ if (options->SchedulerTypes_) {
+ SMARTLIST_FOREACH(options->SchedulerTypes_, int *, i, tor_free(i));
+ smartlist_free(options->SchedulerTypes_);
+ }
tor_free(options->BridgePassword_AuthDigest_);
tor_free(options->command_arg);
tor_free(options->master_key_fname);
+ config_free_lines(options->MyFamily);
config_free(&options_format, options);
}
@@ -964,6 +1049,23 @@ escaped_safe_str(const char *address)
return escaped(address);
}
+/**
+ * The severity level that should be used for warnings of severity
+ * LOG_PROTOCOL_WARN.
+ *
+ * We keep this outside the options, in case somebody needs to use
+ * LOG_PROTOCOL_WARN while an option transition is happening.
+ */
+static int protocol_warning_severity_level = LOG_WARN;
+
+/** Return the severity level that should be used for warnings of severity
+ * LOG_PROTOCOL_WARN. */
+int
+get_protocol_warning_severity_level(void)
+{
+ return protocol_warning_severity_level;
+}
+
/** List of default directory authorities */
static const char *default_authorities[] = {
@@ -1170,13 +1272,13 @@ options_act_reversible(const or_options_t *old_options, char **msg)
"on this OS/with this build.");
goto rollback;
}
-#else
+#else /* !(!defined(HAVE_SYS_UN_H)) */
if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
*msg = tor_strdup("Setting ControlSocketGroupWritable without setting"
"a ControlSocket makes no sense.");
goto rollback;
}
-#endif
+#endif /* !defined(HAVE_SYS_UN_H) */
if (running_tor) {
int n_ports=0;
@@ -1253,7 +1355,7 @@ options_act_reversible(const or_options_t *old_options, char **msg)
goto rollback;
}
}
-#endif
+#endif /* defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) */
/* Attempt to lock all current and future memory with mlockall() only once */
if (options->DisableAllSwap) {
@@ -1305,7 +1407,7 @@ options_act_reversible(const or_options_t *old_options, char **msg)
options->DataDirectory, strerror(errno));
}
}
-#endif
+#endif /* !defined(_WIN32) */
/* Bail out at this point if we're not going to be a client or server:
* we don't run Tor itself. */
@@ -1482,21 +1584,32 @@ get_effective_bwburst(const or_options_t *options)
return (uint32_t)bw;
}
-/** Return True if any changes from <b>old_options</b> to
- * <b>new_options</b> needs us to refresh our TLS context. */
+/**
+ * Return true if changing the configuration from <b>old</b> to <b>new</b>
+ * affects the guard susbsystem.
+ */
static int
-options_transition_requires_fresh_tls_context(const or_options_t *old_options,
- const or_options_t *new_options)
+options_transition_affects_guards(const or_options_t *old,
+ const or_options_t *new)
{
- tor_assert(new_options);
-
- if (!old_options)
- return 0;
-
- if (!opt_streq(old_options->TLSECGroup, new_options->TLSECGroup))
- return 1;
-
- return 0;
+ /* NOTE: Make sure this function stays in sync with
+ * entry_guards_set_filtered_flags */
+
+ tor_assert(old);
+ tor_assert(new);
+
+ return
+ (old->UseEntryGuards != new->UseEntryGuards ||
+ old->UseBridges != new->UseBridges ||
+ old->ClientUseIPv4 != new->ClientUseIPv4 ||
+ old->ClientUseIPv6 != new->ClientUseIPv6 ||
+ old->FascistFirewall != new->FascistFirewall ||
+ !routerset_equal(old->ExcludeNodes, new->ExcludeNodes) ||
+ !routerset_equal(old->EntryNodes, new->EntryNodes) ||
+ !smartlist_strings_eq(old->FirewallPorts, new->FirewallPorts) ||
+ !config_lines_eq(old->Bridges, new->Bridges) ||
+ !config_lines_eq(old->ReachableORAddresses, new->ReachableORAddresses) ||
+ !config_lines_eq(old->ReachableDirAddresses, new->ReachableDirAddresses));
}
/** Fetch the active option list, and take actions based on it. All of the
@@ -1518,6 +1631,12 @@ options_act(const or_options_t *old_options)
const int transition_affects_workers =
old_options && options_transition_affects_workers(old_options, options);
int old_ewma_enabled;
+ const int transition_affects_guards =
+ old_options && options_transition_affects_guards(old_options, options);
+
+ if (options->NoExec || options->Sandbox) {
+ tor_disable_spawning_background_processes();
+ }
/* disable ptrace and later, other basic debugging techniques */
{
@@ -1553,6 +1672,11 @@ options_act(const or_options_t *old_options)
return -1;
}
+ if (options->ProtocolWarnings)
+ protocol_warning_severity_level = LOG_WARN;
+ else
+ protocol_warning_severity_level = LOG_INFO;
+
if (consider_adding_dir_servers(options, old_options) < 0)
return -1;
@@ -1570,7 +1694,7 @@ options_act(const or_options_t *old_options)
return -1;
}
/* LCOV_EXCL_STOP */
-#else
+#else /* !(defined(ENABLE_TOR2WEB_MODE)) */
if (options->Tor2webMode) {
log_err(LD_CONFIG, "This copy of Tor was not compiled to run in "
"'tor2web mode'. It cannot be run with the Tor2webMode torrc "
@@ -1578,7 +1702,7 @@ options_act(const or_options_t *old_options)
"--enable-tor2web-mode option.");
return -1;
}
-#endif
+#endif /* defined(ENABLE_TOR2WEB_MODE) */
/* If we are a bridge with a pluggable transport proxy but no
Extended ORPort, inform the user that they are missing out. */
@@ -1607,7 +1731,7 @@ options_act(const or_options_t *old_options)
sweep_bridge_list();
}
- if (running_tor && rend_config_services(options, 0)<0) {
+ if (running_tor && hs_config_service_all(options, 0)<0) {
log_warn(LD_BUG,
"Previously validated hidden services line could not be added!");
return -1;
@@ -1687,19 +1811,16 @@ options_act(const or_options_t *old_options)
log_warn(LD_BUG,"Error initializing keys; exiting");
return -1;
}
- } else if (old_options &&
- options_transition_requires_fresh_tls_context(old_options,
- options)) {
- if (router_initialize_tls_context() < 0) {
- log_warn(LD_BUG,"Error initializing TLS context.");
- return -1;
- }
}
/* Write our PID to the PID file. If we do not have write permissions we
- * will log a warning */
+ * will log a warning and exit. */
if (options->PidFile && !sandbox_is_active()) {
- write_pidfile(options->PidFile);
+ if (write_pidfile(options->PidFile) < 0) {
+ log_err(LD_CONFIG, "Unable to write PIDFile %s",
+ escaped(options->PidFile));
+ return -1;
+ }
}
/* Register addressmap directives */
@@ -1714,6 +1835,15 @@ 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;
@@ -1722,16 +1852,14 @@ options_act(const or_options_t *old_options)
monitor_owning_controller_process(options->OwningControllerProcess);
/* reload keys as needed for rendezvous services. */
- if (rend_service_load_all_keys(NULL)<0) {
+ if (hs_service_load_all_keys() < 0) {
log_warn(LD_GENERAL,"Error loading rendezvous service keys");
return -1;
}
- /* Set up scheduler thresholds */
- scheduler_set_watermarks((uint32_t)options->SchedulerLowWaterMark__,
- (uint32_t)options->SchedulerHighWaterMark__,
- (options->SchedulerMaxFlushCells__ > 0) ?
- options->SchedulerMaxFlushCells__ : 1000);
+ /* Inform the scheduler subsystem that a configuration changed happened. It
+ * might be a change of scheduler or parameter. */
+ scheduler_conf_changed();
/* Set up accounting */
if (accounting_parse_options(options, 0)<0) {
@@ -1794,6 +1922,7 @@ options_act(const or_options_t *old_options)
if (old_options) {
int revise_trackexithosts = 0;
int revise_automap_entries = 0;
+ int abandon_circuits = 0;
if ((options->UseEntryGuards && !old_options->UseEntryGuards) ||
options->UseBridges != old_options->UseBridges ||
(options->UseBridges &&
@@ -1810,6 +1939,16 @@ options_act(const or_options_t *old_options)
"Changed to using entry guards or bridges, or changed "
"preferred or excluded node lists. "
"Abandoning previous circuits.");
+ abandon_circuits = 1;
+ }
+
+ if (transition_affects_guards) {
+ if (guards_update_all()) {
+ abandon_circuits = 1;
+ }
+ }
+
+ if (abandon_circuits) {
circuit_mark_all_unused_circs();
circuit_mark_all_dirty_circs_as_unusable();
revise_trackexithosts = 1;
@@ -1840,7 +1979,7 @@ options_act(const or_options_t *old_options)
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 people who used our bridge thinking it is
+ * 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. */
@@ -1868,9 +2007,16 @@ options_act(const or_options_t *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(options) && !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();
@@ -1891,6 +2037,8 @@ options_act(const or_options_t *old_options)
/* 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 ||
@@ -1905,7 +2053,6 @@ options_act(const or_options_t *old_options)
options->CellStatistics = 0;
options->EntryStatistics = 0;
options->ConnDirectionStatistics = 0;
- options->HiddenServiceStatistics = 0;
options->ExitPortStatistics = 0;
}
@@ -1991,13 +2138,6 @@ options_act(const or_options_t *old_options)
!options->BridgeAuthoritativeDir)
rep_hist_desc_stats_term();
- /* Check if we need to parse and add the EntryNodes config option. */
- if (options->EntryNodes &&
- (!old_options ||
- !routerset_equal(old_options->EntryNodes,options->EntryNodes) ||
- !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes)))
- entry_nodes_should_be_added();
-
/* Since our options changed, we might need to regenerate and upload our
* server descriptor.
*/
@@ -2065,6 +2205,7 @@ static const struct {
{ "--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 },
@@ -2225,24 +2366,36 @@ options_trial_assign(config_line_t *list, unsigned flags, char **msg)
return r;
}
- if (options_validate(get_options_mutable(), trial_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);
- return SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
+ rv = SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
+ goto done;
}
- if (options_transition_allowed(get_options(), trial_options, msg) < 0) {
+ if (options_transition_allowed(cur_options, trial_options, msg) < 0) {
or_options_free(trial_options);
- return SETOPT_ERR_TRANSITION;
+ rv = SETOPT_ERR_TRANSITION;
+ goto done;
}
+ in_option_validation = 0;
if (set_options(trial_options, msg)<0) {
or_options_free(trial_options);
- return SETOPT_ERR_SETTING;
+ rv = SETOPT_ERR_SETTING;
+ goto done;
}
/* we liked it. put it in place. */
- return SETOPT_OK;
+ rv = SETOPT_OK;
+ done:
+ in_option_validation = 0;
+ return rv;
}
/** Print a usage message for tor. */
@@ -2252,7 +2405,7 @@ print_usage(void)
printf(
"Copyright (c) 2001-2004, Roger Dingledine\n"
"Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n"
-"Copyright (c) 2007-2016, The Tor Project, Inc.\n\n"
+"Copyright (c) 2007-2017, The Tor Project, Inc.\n\n"
"tor -f <torrc> [args]\n"
"See man page for options, or https://www.torproject.org/ for "
"documentation.\n");
@@ -2333,8 +2486,8 @@ using_default_dir_authorities(const or_options_t *options)
* Fail if one or more of the following is true:
* - DNS name in <b>options-\>Address</b> cannot be resolved.
* - <b>options-\>Address</b> is a local host address.
- * - Attempt to getting local hostname fails.
- * - Attempt to getting network interface address fails.
+ * - Attempt at getting local hostname fails.
+ * - Attempt at getting network interface address fails.
*
* Return 0 if all is well, or -1 if we can't find a suitable
* public IP address.
@@ -2714,13 +2867,13 @@ compute_publishserverdescriptor(or_options_t *options)
#define MIN_REND_POST_PERIOD (10*60)
#define MIN_REND_POST_PERIOD_TESTING (5)
-/** Higest allowable value for PredictedPortsRelevanceTime; if this is
- * too high, our selection of exits will decrease for an extended
- * period of time to an uncomfortable level .*/
-#define MAX_PREDICTED_CIRCS_RELEVANCE (60*60)
+/** Highest allowable value for CircuitsAvailableTimeout.
+ * If this is too large, client connections will stay open for too long,
+ * incurring extra padding overhead. */
+#define MAX_CIRCS_AVAILABLE_TIME (24*60*60)
/** Highest allowable value for RendPostPeriod. */
-#define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2)
+#define MAX_DIR_PERIOD ((7*24*60*60)/2)
/** Lowest allowable value for MaxCircuitDirtiness; if this is too low, Tor
* will generate too many circuits and potentially overload the network. */
@@ -2734,10 +2887,6 @@ compute_publishserverdescriptor(or_options_t *options)
* will generate too many circuits and potentially overload the network. */
#define MIN_CIRCUIT_STREAM_TIMEOUT 10
-/** Lowest allowable value for HeartbeatPeriod; if this is too low, we might
- * expose more information than we're comfortable with. */
-#define MIN_HEARTBEAT_PERIOD (30*60)
-
/** Lowest recommended value for CircuitBuildTimeout; if it is set too low
* and LearnCircuitBuildTimeout is off, the failure rate for circuit
* construction may be very high. In that case, if it is set below this
@@ -2749,8 +2898,11 @@ static int
options_validate_cb(void *old_options, void *options, void *default_options,
int from_setconf, char **msg)
{
- return options_validate(old_options, options, default_options,
+ in_option_validation = 1;
+ int rv = options_validate(old_options, options, default_options,
from_setconf, msg);
+ in_option_validation = 0;
+ return rv;
}
#define REJECT(arg) \
@@ -2761,15 +2913,17 @@ options_validate_cb(void *old_options, void *options, void *default_options,
#else
#define COMPLAIN(args, ...) \
STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END
-#endif
+#endif /* defined(__GNUC__) && __GNUC__ <= 3 */
/** Log a warning message iff <b>filepath</b> is not absolute.
* Warning message must contain option name <b>option</b> and
* an absolute path that <b>filepath</b> will resolve to.
*
* In case <b>filepath</b> is absolute, do nothing.
+ *
+ * Return 1 if there were relative paths; 0 otherwise.
*/
-static void
+static int
warn_if_option_path_is_relative(const char *option,
char *filepath)
{
@@ -2778,39 +2932,100 @@ warn_if_option_path_is_relative(const char *option,
COMPLAIN("Path for %s (%s) is relative and will resolve to %s."
" Is this what you wanted?", option, filepath, abs_path);
tor_free(abs_path);
+ return 1;
}
+ return 0;
}
/** Scan <b>options</b> for occurances of relative file/directory
* path and log a warning whenever it is found.
+ *
+ * Return 1 if there were relative paths; 0 otherwise.
*/
-static void
+static int
warn_about_relative_paths(or_options_t *options)
{
tor_assert(options);
+ int n = 0;
- warn_if_option_path_is_relative("CookieAuthFile",
- options->CookieAuthFile);
- warn_if_option_path_is_relative("ExtORPortCookieAuthFile",
- options->ExtORPortCookieAuthFile);
- warn_if_option_path_is_relative("DirPortFrontPage",
- options->DirPortFrontPage);
- warn_if_option_path_is_relative("V3BandwidthsFile",
- options->V3BandwidthsFile);
- warn_if_option_path_is_relative("ControlPortWriteToFile",
- options->ControlPortWriteToFile);
- warn_if_option_path_is_relative("GeoIPFile",options->GeoIPFile);
- warn_if_option_path_is_relative("GeoIPv6File",options->GeoIPv6File);
- warn_if_option_path_is_relative("Log",options->DebugLogFile);
- warn_if_option_path_is_relative("AccelDir",options->AccelDir);
- warn_if_option_path_is_relative("DataDirectory",options->DataDirectory);
- warn_if_option_path_is_relative("PidFile",options->PidFile);
+ 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);
for (config_line_t *hs_line = options->RendConfigLines; hs_line;
hs_line = hs_line->next) {
if (!strcasecmp(hs_line->key, "HiddenServiceDir"))
- warn_if_option_path_is_relative("HiddenServiceDir",hs_line->value);
+ n += warn_if_option_path_is_relative("HiddenServiceDir",hs_line->value);
+ }
+ return n != 0;
+}
+
+/* Validate options related to the scheduler. From the Schedulers list, the
+ * SchedulerTypes_ list is created with int values so once we select the
+ * scheduler, which can happen anytime at runtime, we don't have to parse
+ * strings and thus be quick.
+ *
+ * Return 0 on success else -1 and msg is set with an error message. */
+static int
+options_validate_scheduler(or_options_t *options, char **msg)
+{
+ tor_assert(options);
+ tor_assert(msg);
+
+ if (!options->Schedulers || smartlist_len(options->Schedulers) == 0) {
+ REJECT("Empty Schedulers list. Either remove the option so the defaults "
+ "can be used or set at least one value.");
+ }
+ /* Ok, we do have scheduler types, validate them. */
+ options->SchedulerTypes_ = smartlist_new();
+ SMARTLIST_FOREACH_BEGIN(options->Schedulers, const char *, type) {
+ int *sched_type;
+ if (!strcasecmp("KISTLite", type)) {
+ sched_type = tor_malloc_zero(sizeof(int));
+ *sched_type = SCHEDULER_KIST_LITE;
+ smartlist_add(options->SchedulerTypes_, sched_type);
+ } else if (!strcasecmp("KIST", type)) {
+ sched_type = tor_malloc_zero(sizeof(int));
+ *sched_type = SCHEDULER_KIST;
+ smartlist_add(options->SchedulerTypes_, sched_type);
+ } else if (!strcasecmp("Vanilla", type)) {
+ sched_type = tor_malloc_zero(sizeof(int));
+ *sched_type = SCHEDULER_VANILLA;
+ smartlist_add(options->SchedulerTypes_, sched_type);
+ } else {
+ tor_asprintf(msg, "Unknown type %s in option Schedulers. "
+ "Possible values are KIST, KISTLite and Vanilla.",
+ escaped(type));
+ return -1;
+ }
+ } SMARTLIST_FOREACH_END(type);
+
+ if (options->KISTSockBufSizeFactor < 0) {
+ REJECT("KISTSockBufSizeFactor must be at least 0");
}
+
+ /* Don't need to validate that the Interval is less than anything because
+ * zero is valid and all negative values are valid. */
+ if (options->KISTSchedRunInterval > KIST_SCHED_RUN_INTERVAL_MAX) {
+ tor_asprintf(msg, "KISTSchedRunInterval must not be more than %d (ms)",
+ KIST_SCHED_RUN_INTERVAL_MAX);
+ return -1;
+ }
+
+ return 0;
}
/* Validate options related to single onion services.
@@ -2841,13 +3056,13 @@ options_validate_single_onion(or_options_t *options, char **msg)
const int client_port_set = (options->SocksPort_set ||
options->TransPort_set ||
options->NATDPort_set ||
- options->DNSPort_set);
+ options->DNSPort_set ||
+ options->HTTPTunnelPort_set);
if (rend_service_non_anonymous_mode_enabled(options) && client_port_set &&
!options->Tor2webMode) {
REJECT("HiddenServiceNonAnonymousMode is incompatible with using Tor as "
"an anonymous client. Please set Socks/Trans/NATD/DNSPort to 0, or "
- "HiddenServiceNonAnonymousMode to 0, or use the non-anonymous "
- "Tor2webMode.");
+ "revert HiddenServiceNonAnonymousMode to 0.");
}
/* If you run a hidden service in non-anonymous mode, the hidden service
@@ -2857,12 +3072,12 @@ options_validate_single_onion(or_options_t *options, char **msg)
REJECT("Non-anonymous (Tor2web) mode is incompatible with using Tor as a "
"hidden service. Please remove all HiddenServiceDir lines, or use "
"a version of tor compiled without --enable-tor2web-mode, or use "
- " HiddenServiceNonAnonymousMode.");
+ "HiddenServiceNonAnonymousMode.");
}
if (rend_service_allow_non_anonymous_connection(options)
&& options->UseEntryGuards) {
- /* Single Onion services only use entry guards when uploading descriptors,
+ /* Single Onion services only use entry guards when uploading descriptors;
* all other connections are one-hop. Further, Single Onions causes the
* hidden service code to do things which break the path bias
* detector, and it's far easier to turn off entry guards (and
@@ -2904,13 +3119,21 @@ options_validate(or_options_t *old_options, or_options_t *options,
tor_assert(msg);
*msg = NULL;
+ if (parse_ports(options, 1, msg, &n_ports,
+ &world_writable_control_socket) < 0)
+ return -1;
+
/* Set UseEntryGuards from the configured value, before we check it below.
- * We change UseEntryGuards whenn it's incompatible with other options,
+ * We change UseEntryGuards when it's incompatible with other options,
* but leave UseEntryGuards_option with the original value.
* Always use the value of UseEntryGuards, not UseEntryGuards_option. */
options->UseEntryGuards = options->UseEntryGuards_option;
- warn_about_relative_paths(options);
+ if (warn_about_relative_paths(options) && options->RunAsDaemon) {
+ REJECT("You have specified at least one relative path (see above) "
+ "with the RunAsDaemon option. RunAsDaemon is not compatible "
+ "with relative paths.");
+ }
if (server_mode(options) &&
(!strcmpstart(uname, "Windows 95") ||
@@ -2922,10 +3145,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
"for details.", uname);
}
- if (parse_ports(options, 1, msg, &n_ports,
- &world_writable_control_socket) < 0)
- return -1;
-
if (parse_outbound_addresses(options, 1, msg) < 0)
return -1;
@@ -2991,13 +3210,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (!strcasecmp(options->TransProxyType, "default")) {
options->TransProxyType_parsed = TPT_DEFAULT;
} else if (!strcasecmp(options->TransProxyType, "pf-divert")) {
-#if !defined(__OpenBSD__) && !defined( DARWIN )
+#if !defined(OpenBSD) && !defined( DARWIN )
/* Later versions of OS X have pf */
REJECT("pf-divert is a OpenBSD-specific "
"and OS X/Darwin-specific feature.");
#else
options->TransProxyType_parsed = TPT_PF_DIVERT;
-#endif
+#endif /* !defined(OpenBSD) && !defined( DARWIN ) */
} else if (!strcasecmp(options->TransProxyType, "tproxy")) {
#if !defined(__linux__)
REJECT("TPROXY is a Linux-specific feature.");
@@ -3011,22 +3230,20 @@ options_validate(or_options_t *old_options, or_options_t *options,
"and OS X/Darwin-specific feature.");
#else
options->TransProxyType_parsed = TPT_IPFW;
-#endif
+#endif /* !defined(KERNEL_MAY_SUPPORT_IPFW) */
} else {
REJECT("Unrecognized value for TransProxyType");
}
if (strcasecmp(options->TransProxyType, "default") &&
!options->TransPort_set) {
- REJECT("Cannot use TransProxyType without any valid TransPort or "
- "TransListenAddress.");
+ REJECT("Cannot use TransProxyType without any valid TransPort.");
}
}
-#else
+#else /* !(defined(USE_TRANSPARENT)) */
if (options->TransPort_set)
- REJECT("TransPort and TransListenAddress are disabled "
- "in this build.");
-#endif
+ REJECT("TransPort is disabled in this build.");
+#endif /* defined(USE_TRANSPARENT) */
if (options->TokenBucketRefillInterval <= 0
|| options->TokenBucketRefillInterval > 1000) {
@@ -3039,17 +3256,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeNodes);
}
- if (options->SchedulerLowWaterMark__ == 0 ||
- options->SchedulerLowWaterMark__ > UINT32_MAX) {
- log_warn(LD_GENERAL, "Bad SchedulerLowWaterMark__ option");
- return -1;
- } else if (options->SchedulerHighWaterMark__ <=
- options->SchedulerLowWaterMark__ ||
- options->SchedulerHighWaterMark__ > UINT32_MAX) {
- log_warn(LD_GENERAL, "Bad SchedulerHighWaterMark option");
- return -1;
- }
-
if (options->NodeFamilies) {
options->NodeFamilySets = smartlist_new();
for (cl = options->NodeFamilies; cl; cl = cl->next) {
@@ -3062,15 +3268,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
- if (options->TLSECGroup && (strcasecmp(options->TLSECGroup, "P256") &&
- strcasecmp(options->TLSECGroup, "P224"))) {
- COMPLAIN("Unrecognized TLSECGroup: Falling back to the default.");
- tor_free(options->TLSECGroup);
- }
- if (!evaluate_ecgroup_for_tls(options->TLSECGroup)) {
- REJECT("Unsupported TLSECGroup.");
- }
-
if (options->ExcludeNodes && options->StrictNodes) {
COMPLAIN("You have asked to exclude certain relays from all positions "
"in your circuits. Expect hidden services and other Tor "
@@ -3111,7 +3308,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
"UseEntryGuards. Disabling.");
options->UseEntryGuards = 0;
}
- if (!options->DownloadExtraInfo && authdir_mode_any_main(options)) {
+ 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;
@@ -3265,23 +3462,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
"of the Internet, so they must not set Reachable*Addresses "
"or FascistFirewall or FirewallPorts or ClientUseIPv4 0.");
- /* We check if Reachable*Addresses blocks all addresses in
- * parse_reachable_addresses(). */
-
-#define WARN_PLEASE_USE_IPV6_LOG_MSG \
- "ClientPreferIPv6%sPort 1 is ignored unless tor is using IPv6. " \
- "Please set ClientUseIPv6 1, ClientUseIPv4 0, or configure bridges."
-
- if (!fascist_firewall_use_ipv6(options)
- && options->ClientPreferIPv6ORPort == 1)
- log_warn(LD_CONFIG, WARN_PLEASE_USE_IPV6_LOG_MSG, "OR");
-
- if (!fascist_firewall_use_ipv6(options)
- && options->ClientPreferIPv6DirPort == 1)
- log_warn(LD_CONFIG, WARN_PLEASE_USE_IPV6_LOG_MSG, "Dir");
-
-#undef WARN_PLEASE_USE_IPV6_LOG_MSG
-
if (options->UseBridges &&
server_mode(options))
REJECT("Servers must be able to freely connect to the rest "
@@ -3293,33 +3473,16 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->UseBridges && options->EntryNodes)
REJECT("You cannot set both UseBridges and EntryNodes.");
+ /* If we have UseBridges as 1 and UseEntryGuards as 0, we end up bypassing
+ * the use of bridges */
+ if (options->UseBridges && !options->UseEntryGuards)
+ REJECT("Setting UseBridges requires also setting UseEntryGuards.");
+
options->MaxMemInQueues =
compute_real_max_mem_in_queues(options->MaxMemInQueues_raw,
server_mode(options));
options->MaxMemInQueues_low_threshold = (options->MaxMemInQueues / 4) * 3;
- options->AllowInvalid_ = 0;
-
- if (options->AllowInvalidNodes) {
- SMARTLIST_FOREACH_BEGIN(options->AllowInvalidNodes, const char *, cp) {
- if (!strcasecmp(cp, "entry"))
- options->AllowInvalid_ |= ALLOW_INVALID_ENTRY;
- else if (!strcasecmp(cp, "exit"))
- options->AllowInvalid_ |= ALLOW_INVALID_EXIT;
- else if (!strcasecmp(cp, "middle"))
- options->AllowInvalid_ |= ALLOW_INVALID_MIDDLE;
- else if (!strcasecmp(cp, "introduction"))
- options->AllowInvalid_ |= ALLOW_INVALID_INTRODUCTION;
- else if (!strcasecmp(cp, "rendezvous"))
- options->AllowInvalid_ |= ALLOW_INVALID_RENDEZVOUS;
- else {
- tor_asprintf(msg,
- "Unrecognized value '%s' in AllowInvalidNodes", cp);
- return -1;
- }
- } SMARTLIST_FOREACH_END(cp);
- }
-
if (!options->SafeLogging ||
!strcasecmp(options->SafeLogging, "0")) {
options->SafeLogging_ = SAFELOG_SCRUB_NONE;
@@ -3355,6 +3518,23 @@ options_validate(or_options_t *old_options, or_options_t *options,
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 (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.");
@@ -3367,7 +3547,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->RendPostPeriod < min_rendpostperiod) {
log_warn(LD_CONFIG, "RendPostPeriod option is too short; "
"raising to %d seconds.", min_rendpostperiod);
- options->RendPostPeriod = min_rendpostperiod;;
+ options->RendPostPeriod = min_rendpostperiod;
}
if (options->RendPostPeriod > MAX_DIR_PERIOD) {
@@ -3376,17 +3556,17 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->RendPostPeriod = MAX_DIR_PERIOD;
}
- if (options->PredictedPortsRelevanceTime >
- MAX_PREDICTED_CIRCS_RELEVANCE) {
- log_warn(LD_CONFIG, "PredictedPortsRelevanceTime is too large; "
- "clipping to %ds.", MAX_PREDICTED_CIRCS_RELEVANCE);
- options->PredictedPortsRelevanceTime = MAX_PREDICTED_CIRCS_RELEVANCE;
- }
-
/* Check the Single Onion Service options */
if (options_validate_single_onion(options, msg) < 0)
return -1;
+ if (options->CircuitsAvailableTimeout > MAX_CIRCS_AVAILABLE_TIME) {
+ // options_t is immutable for new code (the above code is older),
+ // so just make the user fix the value themselves rather than
+ // silently keep a shadow value lower than what they asked for.
+ REJECT("CircuitsAvailableTimeout is too large. Max is 24 hours.");
+ }
+
#ifdef ENABLE_TOR2WEB_MODE
if (options->Tor2webMode && options->UseEntryGuards) {
/* tor2web mode clients do not (and should not) use entry guards
@@ -3401,7 +3581,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
"Tor2WebMode is enabled; disabling UseEntryGuards.");
options->UseEntryGuards = 0;
}
-#endif
+#endif /* defined(ENABLE_TOR2WEB_MODE) */
if (options->Tor2webRendezvousPoints && !options->Tor2webMode) {
REJECT("Tor2webRendezvousPoints cannot be set without Tor2webMode.");
@@ -3436,6 +3616,20 @@ options_validate(or_options_t *old_options, or_options_t *options,
return -1;
}
+ /* Inform the hidden service operator that pinning EntryNodes can possibly
+ * be harmful for the service anonymity. */
+ if (options->EntryNodes &&
+ routerset_is_list(options->EntryNodes) &&
+ (options->RendConfigLines != NULL)) {
+ log_warn(LD_CONFIG,
+ "EntryNodes is set with multiple entries and at least one "
+ "hidden service is configured. Pinning entry nodes can possibly "
+ "be harmful to the service anonymity. Because of this, we "
+ "recommend you either don't do that or make sure you know what "
+ "you are doing. For more details, please look at "
+ "https://trac.torproject.org/projects/tor/ticket/21155.");
+ }
+
/* Single Onion Services: non-anonymous hidden services */
if (rend_service_non_anonymous_mode_enabled(options)) {
log_warn(LD_CONFIG,
@@ -3461,7 +3655,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
int severity = LOG_NOTICE;
/* Be a little quieter if we've deliberately disabled
* LearnCircuitBuildTimeout. */
- if (circuit_build_times_disabled()) {
+ if (circuit_build_times_disabled_(options, 1)) {
severity = LOG_INFO;
}
log_fn(severity, LD_CONFIG, "You disabled LearnCircuitBuildTimeout, but "
@@ -3533,6 +3727,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("PortForwarding is not compatible with Sandbox; at most one can "
"be set");
}
+ if (options->PortForwarding && options->NoExec) {
+ COMPLAIN("Both PortForwarding and NoExec are set; PortForwarding will "
+ "be ignored.");
+ }
if (ensure_bandwidth_cap(&options->BandwidthRate,
"BandwidthRate", msg) < 0)
@@ -3791,13 +3989,14 @@ options_validate(or_options_t *old_options, or_options_t *options,
"have it group-readable.");
}
- if (options->MyFamily && options->BridgeRelay) {
+ 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 (check_nickname_list(&options->MyFamily, "MyFamily", msg))
+ 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();
@@ -3970,7 +4169,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours.");
}
- if (rend_config_services(options, 1) < 0)
+ if (hs_config_service_all(options, 1) < 0)
REJECT("Failed to configure rendezvous options. See logs for details.");
/* Parse client-side authorization for hidden services. */
@@ -3994,13 +4193,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
"AlternateDirAuthority and AlternateBridgeAuthority configured.");
}
- if (options->AllowSingleHopExits && !options->DirAuthorities) {
- COMPLAIN("You have set AllowSingleHopExits; now your relay will allow "
- "others to make one-hop exits. However, since by default most "
- "clients avoid relays that set this option, most clients will "
- "ignore you.");
- }
-
#define CHECK_DEFAULT(arg) \
STMT_BEGIN \
if (!options->TestingTorNetwork && \
@@ -4021,6 +4213,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
CHECK_DEFAULT(TestingServerConsensusDownloadSchedule);
CHECK_DEFAULT(TestingClientConsensusDownloadSchedule);
CHECK_DEFAULT(TestingBridgeDownloadSchedule);
+ CHECK_DEFAULT(TestingBridgeBootstrapDownloadSchedule);
CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest);
CHECK_DEFAULT(TestingDirConnectionMaxStall);
CHECK_DEFAULT(TestingConsensusMaxDownloadTries);
@@ -4034,6 +4227,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
CHECK_DEFAULT(TestingLinkKeySlop);
#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)
@@ -4197,6 +4394,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
"combination.");
+ if (options_validate_scheduler(options, msg) < 0) {
+ return -1;
+ }
+
return 0;
}
@@ -4231,7 +4432,7 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess)
#else
/* (presumably) 32-bit system. Let's hope for 1 GB. */
result = ONE_GIGABYTE;
-#endif
+#endif /* SIZEOF_VOID_P >= 8 */
} else {
/* We detected it, so let's pick 3/4 of the total RAM as our limit. */
const uint64_t avail = (ram / 4) * 3;
@@ -4266,8 +4467,8 @@ 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_MB_BANDWIDTH 300
-#define DIRCACHE_MIN_BANDWIDTH (DIRCACHE_MIN_MB_BANDWIDTH*ONE_MEGABYTE)
+#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
@@ -4287,21 +4488,21 @@ have_enough_mem_for_dircache(const or_options_t *options, size_t total_mem,
}
}
if (options->DirCache) {
- if (total_mem < DIRCACHE_MIN_BANDWIDTH) {
+ if (total_mem < DIRCACHE_MIN_MEM_BYTES) {
if (options->BridgeRelay) {
*msg = tor_strdup("Running a Bridge with less than "
- STRINGIFY(DIRCACHE_MIN_MB_BANDWIDTH) " MB of memory is "
- "not recommended.");
+ STRINGIFY(DIRCACHE_MIN_MEM_MB) " MB of memory is not "
+ "recommended.");
} else {
*msg = tor_strdup("Being a directory cache (default) with less than "
- STRINGIFY(DIRCACHE_MIN_MB_BANDWIDTH) " MB of memory is "
- "not recommended and may consume most of the available "
+ STRINGIFY(DIRCACHE_MIN_MEM_MB) " 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.");
}
}
} else {
- if (total_mem >= DIRCACHE_MIN_BANDWIDTH) {
+ if (total_mem >= DIRCACHE_MIN_MEM_BYTES) {
*msg = tor_strdup("DirCache is disabled and we are configured as a "
"relay. This may disqualify us from becoming a guard in the "
"future.");
@@ -4416,6 +4617,12 @@ options_transition_allowed(const or_options_t *old,
return -1;
}
+ if (old->NoExec && !new_val->NoExec) {
+ *msg = tor_strdup("While Tor is running, disabling "
+ "NoExec is not allowed.");
+ return -1;
+ }
+
if (sandbox_is_active()) {
#define SB_NOCHANGE_STR(opt) \
do { \
@@ -4426,7 +4633,6 @@ options_transition_allowed(const or_options_t *old,
} while (0)
SB_NOCHANGE_STR(Address);
- SB_NOCHANGE_STR(PidFile);
SB_NOCHANGE_STR(ServerDNSResolvConfFile);
SB_NOCHANGE_STR(DirPortFrontPage);
SB_NOCHANGE_STR(CookieAuthFile);
@@ -4466,6 +4672,7 @@ options_transition_affects_workers(const or_options_t *old_options,
old_options->SafeLogging_ != new_options->SafeLogging_ ||
old_options->ClientOnly != new_options->ClientOnly ||
server_mode(old_options) != server_mode(new_options) ||
+ dir_server_mode(old_options) != dir_server_mode(new_options) ||
public_server_mode(old_options) != public_server_mode(new_options) ||
!config_lines_eq(old_options->Logs, new_options->Logs) ||
old_options->LogMessageDomains != new_options->LogMessageDomains)
@@ -4507,7 +4714,9 @@ options_transition_affects_descriptor(const or_options_t *old_options,
get_effective_bwburst(old_options) !=
get_effective_bwburst(new_options) ||
!opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
- !opt_streq(old_options->MyFamily, new_options->MyFamily) ||
+ !opt_streq(old_options->BridgeDistribution,
+ new_options->BridgeDistribution) ||
+ !config_lines_eq(old_options->MyFamily, new_options->MyFamily) ||
!opt_streq(old_options->AccountingStart, new_options->AccountingStart) ||
old_options->AccountingMax != new_options->AccountingMax ||
old_options->AccountingRule != new_options->AccountingRule ||
@@ -4560,7 +4769,7 @@ get_windows_conf_root(void)
path[sizeof(path)-1] = '\0';
#else
strlcpy(path,tpath,sizeof(path));
-#endif
+#endif /* defined(UNICODE) */
/* Now we need to free the memory that the path-idl was stored in. In
* typical Windows fashion, we can't just call 'free()' on it. */
@@ -4576,7 +4785,7 @@ get_windows_conf_root(void)
is_set = 1;
return path;
}
-#endif
+#endif /* defined(_WIN32) */
/** Return the default location for our torrc file (if <b>defaults_file</b> is
* false), or for the torrc-defaults file (if <b>defaults_file</b> is true). */
@@ -4600,30 +4809,39 @@ get_default_conf_file(int defaults_file)
}
#else
return defaults_file ? CONFDIR "/torrc-defaults" : CONFDIR "/torrc";
-#endif
+#endif /* defined(DISABLE_SYSTEM_TORRC) || ... */
}
-/** Verify whether lst is a string containing valid-looking comma-separated
- * nicknames, or NULL. Will normalise <b>lst</b> to prefix '$' to any nickname
- * or fingerprint that needs it. Return 0 on success.
+/** 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
-check_nickname_list(char **lst, const char *name, char **msg)
+normalize_nickname_list(config_line_t **normalized_out,
+ const config_line_t *lst, const char *name,
+ char **msg)
{
- int r = 0;
- smartlist_t *sl;
- int changes = 0;
-
- if (!*lst)
+ if (!lst)
return 0;
- sl = smartlist_new();
- smartlist_split_string(sl, *lst, ",",
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);
+ config_line_t *new_nicknames = NULL;
+ config_line_t **new_nicknames_next = &new_nicknames;
- SMARTLIST_FOREACH_BEGIN(sl, char *, s)
+ 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] != '$') {
@@ -4632,36 +4850,45 @@ check_nickname_list(char **lst, const char *name, char **msg)
tor_asprintf(&prepended, "$%s", s);
if (is_legal_nickname_or_hexdigest(prepended)) {
- // The nickname is valid when it's prepended, swap the current
- // version with a prepended one
- tor_free(s);
- SMARTLIST_REPLACE_CURRENT(sl, s, prepended);
- changes = 1;
- continue;
+ // 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);
}
-
- // Still not valid, free and fallback to error message
- tor_free(prepended);
}
- tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
- r = -1;
- break;
+ if (!normalized) {
+ tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
+ valid_line = 0;
+ break;
+ }
+ } else {
+ normalized = tor_strdup(s);
}
- }
- SMARTLIST_FOREACH_END(s);
- // Replace the caller's nickname list with a fixed one
- if (changes && r == 0) {
- char *newNicknames = smartlist_join_strings(sl, ", ", 0, NULL);
- tor_free(*lst);
- *lst = newNicknames;
+ 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;
+ }
}
- SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
- smartlist_free(sl);
+ *normalized_out = new_nicknames;
- return r;
+ return 0;
}
/** Learn config file name from command line arguments, or use the default.
@@ -4733,9 +4960,9 @@ find_torrc_filename(config_line_t *cmd_arg,
} else {
fname = dflt ? tor_strdup(dflt) : NULL;
}
-#else
+#else /* !(!defined(_WIN32)) */
fname = dflt ? tor_strdup(dflt) : NULL;
-#endif
+#endif /* !defined(_WIN32) */
}
}
return fname;
@@ -4863,9 +5090,21 @@ options_init_from_torrc(int argc, char **argv)
printf("OpenSSL \t\t%-15s\t\t%s\n",
crypto_openssl_get_header_version_str(),
crypto_openssl_get_version_str());
- printf("Zlib \t\t%-15s\t\t%s\n",
- tor_zlib_get_header_version_str(),
- tor_zlib_get_version_str());
+ if (tor_compress_supports_method(ZLIB_METHOD)) {
+ printf("Zlib \t\t%-15s\t\t%s\n",
+ tor_compress_version_str(ZLIB_METHOD),
+ tor_compress_header_version_str(ZLIB_METHOD));
+ }
+ if (tor_compress_supports_method(LZMA_METHOD)) {
+ printf("Liblzma \t\t%-15s\t\t%s\n",
+ tor_compress_version_str(LZMA_METHOD),
+ tor_compress_header_version_str(LZMA_METHOD));
+ }
+ if (tor_compress_supports_method(ZSTD_METHOD)) {
+ printf("Libzstd \t\t%-15s\t\t%s\n",
+ tor_compress_version_str(ZSTD_METHOD),
+ tor_compress_header_version_str(ZSTD_METHOD));
+ }
//TODO: Hex versions?
exit(0);
}
@@ -4874,6 +5113,9 @@ options_init_from_torrc(int argc, char **argv)
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")) {
@@ -5005,6 +5247,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
config_line_t *cl;
int retval;
setopt_err_t err = SETOPT_ERR_MISC;
+ int cf_has_include = 0;
tor_assert(msg);
oldoptions = global_options; /* get_options unfortunately asserts if
@@ -5021,7 +5264,8 @@ options_init_from_string(const char *cf_defaults, const char *cf,
if (!body)
continue;
/* get config lines, assign them */
- retval = config_get_lines(body, &cl, 1);
+ retval = config_get_lines_include(body, &cl, 1,
+ body == cf ? &cf_has_include : NULL);
if (retval < 0) {
err = SETOPT_ERR_PARSE;
goto err;
@@ -5049,6 +5293,8 @@ options_init_from_string(const char *cf_defaults, const char *cf,
goto err;
}
+ newoptions->IncludeUsed = cf_has_include;
+
/* If this is a testing network configuration, change defaults
* for a list of dependent config options, re-initialize newoptions
* with the new defaults, and assign all options to it second time. */
@@ -5092,7 +5338,8 @@ options_init_from_string(const char *cf_defaults, const char *cf,
if (!body)
continue;
/* get config lines, assign them */
- retval = config_get_lines(body, &cl, 1);
+ retval = config_get_lines_include(body, &cl, 1,
+ body == cf ? &cf_has_include : NULL);
if (retval < 0) {
err = SETOPT_ERR_PARSE;
goto err;
@@ -5115,6 +5362,9 @@ options_init_from_string(const char *cf_defaults, const char *cf,
}
}
+ newoptions->IncludeUsed = cf_has_include;
+ in_option_validation = 1;
+
/* Validate newoptions */
if (options_validate(oldoptions, newoptions, newdefaultoptions,
0, msg) < 0) {
@@ -5126,17 +5376,20 @@ options_init_from_string(const char *cf_defaults, const char *cf,
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;
return SETOPT_OK;
err:
+ in_option_validation = 0;
or_options_free(newoptions);
or_options_free(newdefaultoptions);
if (*msg) {
@@ -5218,35 +5471,35 @@ addressmap_register_auto(const char *from, const char *to,
int from_wildcard = 0, to_wildcard = 0;
*msg = "whoops, forgot the error message";
- if (1) {
- if (!strcmp(to, "*") || !strcmp(from, "*")) {
- *msg = "can't remap from or to *";
- return -1;
- }
- /* Detect asterisks in expressions of type: '*.example.com' */
- if (!strncmp(from,"*.",2)) {
- from += 2;
- from_wildcard = 1;
- }
- if (!strncmp(to,"*.",2)) {
- to += 2;
- to_wildcard = 1;
- }
- if (to_wildcard && !from_wildcard) {
- *msg = "can only use wildcard (i.e. '*.') if 'from' address "
- "uses wildcard also";
- return -1;
- }
+ if (!strcmp(to, "*") || !strcmp(from, "*")) {
+ *msg = "can't remap from or to *";
+ return -1;
+ }
+ /* Detect asterisks in expressions of type: '*.example.com' */
+ if (!strncmp(from,"*.",2)) {
+ from += 2;
+ from_wildcard = 1;
+ }
+ if (!strncmp(to,"*.",2)) {
+ to += 2;
+ to_wildcard = 1;
+ }
- if (address_is_invalid_destination(to, 1)) {
- *msg = "destination is invalid";
- return -1;
- }
+ if (to_wildcard && !from_wildcard) {
+ *msg = "can only use wildcard (i.e. '*.') if 'from' address "
+ "uses wildcard also";
+ return -1;
+ }
- addressmap_register(from, tor_strdup(to), expires, addrmap_source,
- from_wildcard, to_wildcard);
+ if (address_is_invalid_destination(to, 1)) {
+ *msg = "destination is invalid";
+ return -1;
}
+
+ addressmap_register(from, tor_strdup(to), expires, addrmap_source,
+ from_wildcard, to_wildcard);
+
return 0;
}
@@ -5313,7 +5566,7 @@ options_init_logs(const or_options_t *old_options, or_options_t *options,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
if (smartlist_len(elts) == 0)
- smartlist_add(elts, tor_strdup("stdout"));
+ smartlist_add_strdup(elts, "stdout");
if (smartlist_len(elts) == 1 &&
(!strcasecmp(smartlist_get(elts,0), "stdout") ||
@@ -5340,7 +5593,7 @@ options_init_logs(const or_options_t *old_options, or_options_t *options,
}
#else
log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry.");
-#endif
+#endif /* defined(HAVE_SYSLOG_H) */
goto cleanup;
}
@@ -5657,6 +5910,15 @@ parse_transport_line(const or_options_t *options,
goto err;
}
+ if (is_managed && options->NoExec) {
+ log_warn(LD_CONFIG,
+ "Managed proxies are not compatible with NoExec mode; ignoring."
+ "(%sTransportPlugin line was %s)",
+ server ? "Server" : "Client", escaped(line));
+ r = 0;
+ goto done;
+ }
+
if (is_managed) {
/* managed */
@@ -5848,7 +6110,7 @@ get_options_from_transport_options_line(const char *line,const char *transport)
}
/* add it to the options smartlist */
- smartlist_add(options, tor_strdup(option));
+ smartlist_add_strdup(options, option);
log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
} SMARTLIST_FOREACH_END(option);
@@ -5927,6 +6189,8 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
dirinfo_type_t type = 0;
double weight = 1.0;
+ memset(v3_digest, 0, sizeof(v3_digest));
+
items = smartlist_new();
smartlist_split_string(items, line, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
@@ -6173,9 +6437,9 @@ port_cfg_new(size_t namelen)
tor_assert(namelen <= SIZE_T_CEILING - sizeof(port_cfg_t) - 1);
port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t) + namelen + 1);
cfg->entry_cfg.ipv4_traffic = 1;
+ cfg->entry_cfg.ipv6_traffic = 1;
cfg->entry_cfg.dns_request = 1;
cfg->entry_cfg.onion_traffic = 1;
- cfg->entry_cfg.cache_ipv4_answers = 1;
cfg->entry_cfg.prefer_ipv6_virtaddr = 1;
return cfg;
}
@@ -6190,8 +6454,9 @@ port_cfg_free(port_cfg_t *port)
/** Warn for every port in <b>ports</b> of type <b>listener_type</b> that is
* on a publicly routable address. */
static void
-warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname,
- int listener_type)
+warn_nonlocal_client_ports(const smartlist_t *ports,
+ const char *portname,
+ const int listener_type)
{
SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
if (port->type != listener_type)
@@ -6348,16 +6613,60 @@ 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>, and
- * entries of the "FooListenAddress" type from the list
- * <b>listenaddrs</b>. Two syntaxes are supported: a legacy syntax
- * where FooPort is at most a single entry containing a port number and
- * where FooListenAddress has any number of address:port combinations;
- * and a new syntax where there are no FooListenAddress entries and
- * where FooPort can have any number of entries of the format
- * "[Address:][Port] IsolationOptions".
+ * Read entries of the "FooPort" type from the list <b>ports</b>. Syntax is
+ * that FooPort can have any number of entries of the format
+ * "[Address:][Port] IsolationOptions".
*
* In log messages, describe the port type as <b>portname</b>.
*
@@ -6371,9 +6680,6 @@ warn_client_dns_cache(const char *option, int disabling)
* ports are not on a local address. If CL_PORT_FORBID_NONLOCAL is set,
* this is a control port with no password set: don't even allow it.
*
- * Unless CL_PORT_ALLOW_EXTRA_LISTENADDR is set in <b>flags</b>, warn
- * if FooListenAddress is set but FooPort is 0.
- *
* If CL_PORT_SERVER_OPTIONS is set in <b>flags</b>, do not allow stream
* isolation options in the FooPort entries; instead allow the
* server-port option set.
@@ -6388,7 +6694,6 @@ warn_client_dns_cache(const char *option, int disabling)
STATIC int
parse_port_config(smartlist_t *out,
const config_line_t *ports,
- const config_line_t *listenaddrs,
const char *portname,
int listener_type,
const char *defaultaddr,
@@ -6405,90 +6710,12 @@ parse_port_config(smartlist_t *out,
const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL;
const unsigned default_to_group_writable =
flags & CL_PORT_DFLT_GROUP_WRITABLE;
- const unsigned allow_spurious_listenaddr =
- flags & CL_PORT_ALLOW_EXTRA_LISTENADDR;
const unsigned takes_hostnames = flags & CL_PORT_TAKES_HOSTNAMES;
const unsigned is_unix_socket = flags & CL_PORT_IS_UNIXSOCKET;
int got_zero_port=0, got_nonzero_port=0;
char *unix_socket_path = NULL;
- /* FooListenAddress is deprecated; let's make it work like it used to work,
- * though. */
- if (listenaddrs) {
- int mainport = defaultport;
-
- if (ports && ports->next) {
- log_warn(LD_CONFIG, "%sListenAddress can't be used when there are "
- "multiple %sPort lines", portname, portname);
- return -1;
- } else if (ports) {
- if (!strcmp(ports->value, "auto")) {
- mainport = CFG_AUTO_PORT;
- } else {
- int ok;
- mainport = (int)tor_parse_long(ports->value, 10, 0, 65535, &ok, NULL);
- if (!ok) {
- log_warn(LD_CONFIG, "%sListenAddress can only be used with a single "
- "%sPort with value \"auto\" or 1-65535 and no options set.",
- portname, portname);
- return -1;
- }
- }
- }
-
- if (mainport == 0) {
- if (allow_spurious_listenaddr)
- return 1; /*DOCDOC*/
- log_warn(LD_CONFIG, "%sPort must be defined if %sListenAddress is used",
- portname, portname);
- return -1;
- }
-
- if (use_server_options && out) {
- /* Add a no_listen port. */
- port_cfg_t *cfg = port_cfg_new(0);
- cfg->type = listener_type;
- cfg->port = mainport;
- tor_addr_make_unspec(&cfg->addr); /* Server ports default to 0.0.0.0 */
- cfg->server_cfg.no_listen = 1;
- cfg->server_cfg.bind_ipv4_only = 1;
- /* cfg->entry_cfg defaults are already set by port_cfg_new */
- smartlist_add(out, cfg);
- }
-
- for (; listenaddrs; listenaddrs = listenaddrs->next) {
- tor_addr_t addr;
- uint16_t port = 0;
- if (tor_addr_port_lookup(listenaddrs->value, &addr, &port) < 0) {
- log_warn(LD_CONFIG, "Unable to parse %sListenAddress '%s'",
- portname, listenaddrs->value);
- return -1;
- }
- if (out) {
- port_cfg_t *cfg = port_cfg_new(0);
- cfg->type = listener_type;
- cfg->port = port ? port : mainport;
- tor_addr_copy(&cfg->addr, &addr);
- cfg->entry_cfg.session_group = SESSION_GROUP_UNSET;
- cfg->entry_cfg.isolation_flags = ISO_DEFAULT;
- cfg->server_cfg.no_advertise = 1;
- smartlist_add(out, cfg);
- }
- }
-
- if (warn_nonlocal && out) {
- if (is_control)
- warn_nonlocal_controller_ports(out, forbid_nonlocal);
- else if (is_ext_orport)
- warn_nonlocal_ext_orports(out, portname);
- else
- warn_nonlocal_client_ports(out, portname, listener_type);
- }
- return 0;
- } /* end if (listenaddrs) */
-
- /* No ListenAddress lines. If there's no FooPort, then maybe make a default
- * one. */
+ /* If there's no FooPort, then maybe make a default one. */
if (! ports) {
if (defaultport && defaultaddr && out) {
port_cfg_t *cfg = port_cfg_new(is_unix_socket ? strlen(defaultaddr) : 0);
@@ -6526,9 +6753,9 @@ parse_port_config(smartlist_t *out,
/* This must be kept in sync with port_cfg_new's defaults */
int no_listen = 0, no_advertise = 0, all_addrs = 0,
bind_ipv4_only = 0, bind_ipv6_only = 0,
- ipv4_traffic = 1, ipv6_traffic = 0, prefer_ipv6 = 0, dns_request = 1,
+ ipv4_traffic = 1, ipv6_traffic = 1, prefer_ipv6 = 0, dns_request = 1,
onion_traffic = 1,
- cache_ipv4 = 1, use_cached_ipv4 = 0,
+ cache_ipv4 = 0, use_cached_ipv4 = 0,
cache_ipv6 = 0, use_cached_ipv6 = 0,
prefer_ipv6_automap = 1, world_writable = 0, group_writable = 0,
relax_dirmode_check = 0,
@@ -6627,7 +6854,7 @@ parse_port_config(smartlist_t *out,
} else if (!strcasecmp(elt, "AllAddrs")) {
all_addrs = 1;
-#endif
+#endif /* 0 */
} else if (!strcasecmp(elt, "IPv4Only")) {
bind_ipv4_only = 1;
} else if (!strcasecmp(elt, "IPv6Only")) {
@@ -6889,6 +7116,7 @@ parse_port_config(smartlist_t *out,
SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
smartlist_clear(elts);
tor_free(addrport);
+ tor_free(unix_socket_path);
}
if (warn_nonlocal && out) {
@@ -6959,36 +7187,45 @@ parse_ports(or_options_t *options, int validate_only,
const unsigned gw_flag = options->SocksSocketsGroupWritable ?
CL_PORT_DFLT_GROUP_WRITABLE : 0;
if (parse_port_config(ports,
- options->SocksPort_lines, options->SocksListenAddress,
+ options->SocksPort_lines,
"Socks", CONN_TYPE_AP_LISTENER,
"127.0.0.1", 9050,
- CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR|
- CL_PORT_TAKES_HOSTNAMES|gw_flag) < 0) {
- *msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration");
+ ((validate_only ? 0 : CL_PORT_WARN_NONLOCAL)
+ | CL_PORT_TAKES_HOSTNAMES | gw_flag)) < 0) {
+ *msg = tor_strdup("Invalid SocksPort configuration");
goto err;
}
if (parse_port_config(ports,
- options->DNSPort_lines, options->DNSListenAddress,
+ options->DNSPort_lines,
"DNS", CONN_TYPE_AP_DNS_LISTENER,
"127.0.0.1", 0,
CL_PORT_WARN_NONLOCAL|CL_PORT_TAKES_HOSTNAMES) < 0) {
- *msg = tor_strdup("Invalid DNSPort/DNSListenAddress configuration");
+ *msg = tor_strdup("Invalid DNSPort configuration");
goto err;
}
if (parse_port_config(ports,
- options->TransPort_lines, options->TransListenAddress,
+ options->TransPort_lines,
"Trans", CONN_TYPE_AP_TRANS_LISTENER,
"127.0.0.1", 0,
CL_PORT_WARN_NONLOCAL) < 0) {
- *msg = tor_strdup("Invalid TransPort/TransListenAddress configuration");
+ *msg = tor_strdup("Invalid TransPort configuration");
goto err;
}
if (parse_port_config(ports,
- options->NATDPort_lines, options->NATDListenAddress,
+ options->NATDPort_lines,
"NATD", CONN_TYPE_AP_NATD_LISTENER,
"127.0.0.1", 0,
CL_PORT_WARN_NONLOCAL) < 0) {
- *msg = tor_strdup("Invalid NatdPort/NatdListenAddress configuration");
+ *msg = tor_strdup("Invalid NatdPort configuration");
+ goto err;
+ }
+ if (parse_port_config(ports,
+ options->HTTPTunnelPort_lines,
+ "HTTP Tunnel", CONN_TYPE_AP_HTTP_CONNECT_LISTENER,
+ "127.0.0.1", 0,
+ ((validate_only ? 0 : CL_PORT_WARN_NONLOCAL)
+ | CL_PORT_TAKES_HOSTNAMES | gw_flag)) < 0) {
+ *msg = tor_strdup("Invalid HTTPTunnelPort configuration");
goto err;
}
{
@@ -7004,16 +7241,14 @@ parse_ports(or_options_t *options, int validate_only,
if (parse_port_config(ports,
options->ControlPort_lines,
- options->ControlListenAddress,
"Control", CONN_TYPE_CONTROL_LISTENER,
"127.0.0.1", 0,
control_port_flags) < 0) {
- *msg = tor_strdup("Invalid ControlPort/ControlListenAddress "
- "configuration");
+ *msg = tor_strdup("Invalid ControlPort configuration");
goto err;
}
- if (parse_port_config(ports, options->ControlSocket, NULL,
+ if (parse_port_config(ports, options->ControlSocket,
"ControlSocket",
CONN_TYPE_CONTROL_LISTENER, NULL, 0,
control_port_flags | CL_PORT_IS_UNIXSOCKET) < 0) {
@@ -7023,15 +7258,15 @@ parse_ports(or_options_t *options, int validate_only,
}
if (! options->ClientOnly) {
if (parse_port_config(ports,
- options->ORPort_lines, options->ORListenAddress,
+ options->ORPort_lines,
"OR", CONN_TYPE_OR_LISTENER,
"0.0.0.0", 0,
CL_PORT_SERVER_OPTIONS) < 0) {
- *msg = tor_strdup("Invalid ORPort/ORListenAddress configuration");
+ *msg = tor_strdup("Invalid ORPort configuration");
goto err;
}
if (parse_port_config(ports,
- options->ExtORPort_lines, NULL,
+ options->ExtORPort_lines,
"ExtOR", CONN_TYPE_EXT_OR_LISTENER,
"127.0.0.1", 0,
CL_PORT_SERVER_OPTIONS|CL_PORT_WARN_NONLOCAL) < 0) {
@@ -7039,11 +7274,11 @@ parse_ports(or_options_t *options, int validate_only,
goto err;
}
if (parse_port_config(ports,
- options->DirPort_lines, options->DirListenAddress,
+ options->DirPort_lines,
"Dir", CONN_TYPE_DIR_LISTENER,
"0.0.0.0", 0,
CL_PORT_SERVER_OPTIONS) < 0) {
- *msg = tor_strdup("Invalid DirPort/DirListenAddress configuration");
+ *msg = tor_strdup("Invalid DirPort configuration");
goto err;
}
}
@@ -7070,6 +7305,8 @@ parse_ports(or_options_t *options, int validate_only,
!! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1);
options->NATDPort_set =
!! count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1);
+ options->HTTPTunnelPort_set =
+ !! 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);
@@ -7400,7 +7637,7 @@ normalize_data_directory(or_options_t *options)
strlcpy(p,get_windows_conf_root(),MAX_PATH);
options->DataDirectory = p;
return 0;
-#else
+#else /* !(defined(_WIN32)) */
const char *d = options->DataDirectory;
if (!d)
d = "~/.tor";
@@ -7426,7 +7663,7 @@ normalize_data_directory(or_options_t *options)
options->DataDirectory = fn;
}
return 0;
-#endif
+#endif /* defined(_WIN32) */
}
/** Check and normalize the value of options->DataDirectory; return 0 if it
@@ -7764,7 +8001,7 @@ getinfo_helper_config(control_connection_t *conn,
case CONFIG_TYPE_CSV: type = "CommaList"; break;
case CONFIG_TYPE_CSV_INTERVAL: type = "TimeIntervalCommaList"; break;
case CONFIG_TYPE_LINELIST: type = "LineList"; break;
- case CONFIG_TYPE_LINELIST_S: type = "Dependant"; break;
+ case CONFIG_TYPE_LINELIST_S: type = "Dependent"; break;
case CONFIG_TYPE_LINELIST_V: type = "Virtual"; break;
default:
case CONFIG_TYPE_OBSOLETE:
@@ -7846,60 +8083,98 @@ getinfo_helper_config(control_connection_t *conn,
return 0;
}
-/** Parse outbound bind address option lines. If <b>validate_only</b>
- * is not 0 update OutboundBindAddressIPv4_ and
- * OutboundBindAddressIPv6_ in <b>options</b>. On failure, set
- * <b>msg</b> (if provided) to a newly allocated string containing a
- * description of the problem and return -1. */
+/* Check whether an address has already been set against the options
+ * depending on address family and destination type. Any exsting
+ * value will lead to a fail, even if it is the same value. If not
+ * set and not only validating, copy it into this location too.
+ * Returns 0 on success or -1 if this address is already set.
+ */
static int
-parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
+verify_and_store_outbound_address(sa_family_t family, tor_addr_t *addr,
+ outbound_addr_t type, or_options_t *options, int validate_only)
{
- const config_line_t *lines = options->OutboundBindAddress;
- int found_v4 = 0, found_v6 = 0;
-
+ if (type>=OUTBOUND_ADDR_MAX || (family!=AF_INET && family!=AF_INET6)) {
+ return -1;
+ }
+ int fam_index=0;
+ if (family==AF_INET6) {
+ fam_index=1;
+ }
+ tor_addr_t *dest=&options->OutboundBindAddresses[type][fam_index];
+ if (!tor_addr_is_null(dest)) {
+ return -1;
+ }
if (!validate_only) {
- memset(&options->OutboundBindAddressIPv4_, 0,
- sizeof(options->OutboundBindAddressIPv4_));
- memset(&options->OutboundBindAddressIPv6_, 0,
- sizeof(options->OutboundBindAddressIPv6_));
+ tor_addr_copy(dest, addr);
}
+ return 0;
+}
+
+/* Parse a list of address lines for a specific destination type.
+ * Will store them into the options if not validate_only. If a
+ * problem occurs, a suitable error message is store in msg.
+ * Returns 0 on success or -1 if any address is already set.
+ */
+static int
+parse_outbound_address_lines(const config_line_t *lines, outbound_addr_t type,
+ or_options_t *options, int validate_only, char **msg)
+{
+ tor_addr_t addr;
+ sa_family_t family;
while (lines) {
- tor_addr_t addr, *dst_addr = NULL;
- int af = tor_addr_parse(&addr, lines->value);
- switch (af) {
- case AF_INET:
- if (found_v4) {
- if (msg)
- tor_asprintf(msg, "Multiple IPv4 outbound bind addresses "
- "configured: %s", lines->value);
- return -1;
- }
- found_v4 = 1;
- dst_addr = &options->OutboundBindAddressIPv4_;
- break;
- case AF_INET6:
- if (found_v6) {
- if (msg)
- tor_asprintf(msg, "Multiple IPv6 outbound bind addresses "
- "configured: %s", lines->value);
- return -1;
- }
- found_v6 = 1;
- dst_addr = &options->OutboundBindAddressIPv6_;
- break;
- default:
+ family = tor_addr_parse(&addr, lines->value);
+ if (verify_and_store_outbound_address(family, &addr, type,
+ options, validate_only)) {
if (msg)
- tor_asprintf(msg, "Outbound bind address '%s' didn't parse.",
- lines->value);
+ tor_asprintf(msg, "Multiple%s%s outbound bind addresses "
+ "configured: %s",
+ family==AF_INET?" IPv4":(family==AF_INET6?" IPv6":""),
+ type==OUTBOUND_ADDR_OR?" OR":
+ (type==OUTBOUND_ADDR_EXIT?" exit":""), lines->value);
return -1;
}
- if (!validate_only)
- tor_addr_copy(dst_addr, &addr);
lines = lines->next;
}
return 0;
}
+/** Parse outbound bind address option lines. If <b>validate_only</b>
+ * is not 0 update OutboundBindAddresses in <b>options</b>.
+ * Only one address can be set for any of these values.
+ * On failure, set <b>msg</b> (if provided) to a newly allocated string
+ * containing a description of the problem and return -1.
+ */
+static int
+parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
+{
+ if (!validate_only) {
+ memset(&options->OutboundBindAddresses, 0,
+ sizeof(options->OutboundBindAddresses));
+ }
+
+ if (parse_outbound_address_lines(options->OutboundBindAddress,
+ OUTBOUND_ADDR_EXIT_AND_OR, options,
+ validate_only, msg) < 0) {
+ goto err;
+ }
+
+ if (parse_outbound_address_lines(options->OutboundBindAddressOR,
+ OUTBOUND_ADDR_OR, options, validate_only,
+ msg) < 0) {
+ goto err;
+ }
+
+ if (parse_outbound_address_lines(options->OutboundBindAddressExit,
+ OUTBOUND_ADDR_EXIT, options, validate_only,
+ msg) < 0) {
+ goto err;
+ }
+
+ return 0;
+ err:
+ return -1;
+}
+
/** Load one of the geoip files, <a>family</a> determining which
* one. <a>default_fname</a> is used if on Windows and
* <a>fname</a> equals "<default>". */
@@ -7919,10 +8194,10 @@ config_load_geoip_file_(sa_family_t family,
}
geoip_load_file(family, fname);
tor_free(free_fname);
-#else
+#else /* !(defined(_WIN32)) */
(void)default_fname;
geoip_load_file(family, fname);
-#endif
+#endif /* defined(_WIN32) */
}
/** Load geoip files for IPv4 and IPv6 if <a>options</a> and
@@ -7997,9 +8272,9 @@ init_cookie_authentication(const char *fname, const char *header,
log_warn(LD_FS,"Unable to make %s group-readable.", escaped(fname));
}
}
-#else
+#else /* !(!defined(_WIN32)) */
(void) group_readable;
-#endif
+#endif /* !defined(_WIN32) */
/* Success! */
log_info(LD_GENERAL, "Generated auth cookie file in '%s'.", escaped(fname));