LCOV - code coverage report
Current view: top level - app/config - config.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 2298 2893 79.4 %
Date: 2021-11-24 03:28:48 Functions: 108 122 88.5 %

          Line data    Source code
       1             : /* Copyright (c) 2001 Matej Pfajfar.
       2             :  * Copyright (c) 2001-2004, Roger Dingledine.
       3             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       4             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       5             : /* See LICENSE for licensing information */
       6             : 
       7             : /**
       8             :  * \file config.c
       9             :  * \brief Code to interpret the user's configuration of Tor.
      10             :  *
      11             :  * This module handles torrc configuration file, including parsing it,
      12             :  * combining it with torrc.defaults and the command line, allowing
      13             :  * user changes to it (via editing and SIGHUP or via the control port),
      14             :  * writing it back to disk (because of SAVECONF from the control port),
      15             :  * and -- most importantly, acting on it.
      16             :  *
      17             :  * The module additionally has some tools for manipulating and
      18             :  * inspecting values that are calculated as a result of the
      19             :  * configured options.
      20             :  *
      21             :  * <h3>How to add new options</h3>
      22             :  *
      23             :  * To add new items to the torrc, there are a minimum of three places to edit:
      24             :  * <ul>
      25             :  *   <li>The or_options_t structure in or_options_st.h, where the options are
      26             :  *       stored.
      27             :  *   <li>The option_vars_ array below in this module, which configures
      28             :  *       the names of the torrc options, their types, their multiplicities,
      29             :  *       and their mappings to fields in or_options_t.
      30             :  *   <li>The manual in doc/man/tor.1.txt, to document what the new option
      31             :  *       is, and how it works.
      32             :  * </ul>
      33             :  *
      34             :  * Additionally, you might need to edit these places too:
      35             :  * <ul>
      36             :  *   <li>options_validate_cb() below, in case you want to reject some possible
      37             :  *       values of the new configuration option.
      38             :  *   <li>options_transition_allowed() below, in case you need to
      39             :  *       forbid some or all changes in the option while Tor is
      40             :  *       running.
      41             :  *   <li>options_transition_affects_workers(), in case changes in the option
      42             :  *       might require Tor to relaunch or reconfigure its worker threads.
      43             :  *       (This function is now in the relay module.)
      44             :  *   <li>options_transition_affects_descriptor(), in case changes in the
      45             :  *       option might require a Tor relay to build and publish a new server
      46             :  *       descriptor.
      47             :  *       (This function is now in the relay module.)
      48             :  *   <li>options_act() and/or options_act_reversible(), in case there's some
      49             :  *       action that needs to be taken immediately based on the option's
      50             :  *       value.
      51             :  * </ul>
      52             :  *
      53             :  * <h3>Changing the value of an option</h3>
      54             :  *
      55             :  * Because of the SAVECONF command from the control port, it's a bad
      56             :  * idea to change the value of any user-configured option in the
      57             :  * or_options_t.  If you want to sometimes do this anyway, we recommend
      58             :  * that you create a secondary field in or_options_t; that you have the
      59             :  * user option linked only to the secondary field; that you use the
      60             :  * secondary field to initialize the one that Tor actually looks at; and that
      61             :  * you use the one Tor looks as the one that you modify.
      62             :  **/
      63             : 
      64             : #define CONFIG_PRIVATE
      65             : #include "core/or/or.h"
      66             : #include "app/config/config.h"
      67             : #include "lib/confmgt/confmgt.h"
      68             : #include "app/config/statefile.h"
      69             : #include "app/main/main.h"
      70             : #include "app/main/subsysmgr.h"
      71             : #include "core/mainloop/connection.h"
      72             : #include "core/mainloop/mainloop.h"
      73             : #include "core/mainloop/netstatus.h"
      74             : #include "core/or/channel.h"
      75             : #include "core/or/circuitlist.h"
      76             : #include "core/or/circuitmux.h"
      77             : #include "core/or/circuitmux_ewma.h"
      78             : #include "core/or/circuitstats.h"
      79             : #include "core/or/connection_edge.h"
      80             : #include "core/or/dos.h"
      81             : #include "core/or/policies.h"
      82             : #include "core/or/relay.h"
      83             : #include "core/or/scheduler.h"
      84             : #include "feature/client/addressmap.h"
      85             : #include "feature/client/bridges.h"
      86             : #include "feature/client/entrynodes.h"
      87             : #include "feature/client/transports.h"
      88             : #include "feature/control/control.h"
      89             : #include "feature/control/control_auth.h"
      90             : #include "feature/control/control_events.h"
      91             : #include "feature/dirclient/dirclient_modes.h"
      92             : #include "feature/hibernate/hibernate.h"
      93             : #include "feature/hs/hs_config.h"
      94             : #include "feature/metrics/metrics.h"
      95             : #include "feature/nodelist/dirlist.h"
      96             : #include "feature/nodelist/networkstatus.h"
      97             : #include "feature/nodelist/nickname.h"
      98             : #include "feature/nodelist/nodelist.h"
      99             : #include "feature/nodelist/routerlist.h"
     100             : #include "feature/nodelist/routerset.h"
     101             : #include "feature/relay/dns.h"
     102             : #include "feature/relay/ext_orport.h"
     103             : #include "feature/relay/routermode.h"
     104             : #include "feature/relay/relay_config.h"
     105             : #include "feature/relay/transport_config.h"
     106             : #include "lib/geoip/geoip.h"
     107             : #include "feature/stats/geoip_stats.h"
     108             : #include "lib/compress/compress.h"
     109             : #include "lib/confmgt/structvar.h"
     110             : #include "lib/crypt_ops/crypto_init.h"
     111             : #include "lib/crypt_ops/crypto_rand.h"
     112             : #include "lib/crypt_ops/crypto_util.h"
     113             : #include "lib/encoding/confline.h"
     114             : #include "lib/net/resolve.h"
     115             : #include "lib/sandbox/sandbox.h"
     116             : #include "lib/version/torversion.h"
     117             : 
     118             : #ifdef ENABLE_NSS
     119             : #include "lib/crypt_ops/crypto_nss_mgt.h"
     120             : #else
     121             : #include "lib/crypt_ops/crypto_openssl_mgt.h"
     122             : #endif
     123             : 
     124             : #ifdef _WIN32
     125             : #include <shlobj.h>
     126             : #endif
     127             : #ifdef HAVE_FCNTL_H
     128             : #include <fcntl.h>
     129             : #endif
     130             : #ifdef HAVE_SYS_STAT_H
     131             : #include <sys/stat.h>
     132             : #endif
     133             : #ifdef HAVE_SYS_PARAM_H
     134             : #include <sys/param.h>
     135             : #endif
     136             : #ifdef HAVE_UNISTD_H
     137             : #include <unistd.h>
     138             : #endif
     139             : 
     140             : #include "lib/meminfo/meminfo.h"
     141             : #include "lib/osinfo/uname.h"
     142             : #include "lib/osinfo/libc.h"
     143             : #include "lib/process/daemon.h"
     144             : #include "lib/process/pidfile.h"
     145             : #include "lib/process/restrict.h"
     146             : #include "lib/process/setuid.h"
     147             : #include "lib/process/process.h"
     148             : #include "lib/net/gethostname.h"
     149             : #include "lib/thread/numcpus.h"
     150             : 
     151             : #include "lib/encoding/keyval.h"
     152             : #include "lib/fs/conffile.h"
     153             : #include "lib/evloop/procmon.h"
     154             : 
     155             : #include "feature/dirauth/authmode.h"
     156             : #include "feature/dirauth/dirauth_config.h"
     157             : 
     158             : #include "core/or/connection_st.h"
     159             : #include "core/or/port_cfg_st.h"
     160             : 
     161             : #ifdef HAVE_SYSTEMD
     162             : #   if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__)
     163             : /* Systemd's use of gcc's __INCLUDE_LEVEL__ extension macro appears to confuse
     164             :  * Coverity. Here's a kludge to unconfuse it.
     165             :  */
     166             : #   define __INCLUDE_LEVEL__ 2
     167             : #endif /* defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) */
     168             : #include <systemd/sd-daemon.h>
     169             : #endif /* defined(HAVE_SYSTEMD) */
     170             : 
     171             : /* Prefix used to indicate a Unix socket in a FooPort configuration. */
     172             : static const char unix_socket_prefix[] = "unix:";
     173             : /* Prefix used to indicate a Unix socket with spaces in it, in a FooPort
     174             :  * configuration. */
     175             : static const char unix_q_socket_prefix[] = "unix:\"";
     176             : 
     177             : /* limits for TCP send and recv buffer size used for constrained sockets */
     178             : #define MIN_CONSTRAINED_TCP_BUFFER 2048
     179             : #define MAX_CONSTRAINED_TCP_BUFFER 262144  /* 256k */
     180             : 
     181             : /** macro to help with the bulk rename of *DownloadSchedule to
     182             :  * *DowloadInitialDelay . */
     183             : #ifndef COCCI
     184             : #define DOWNLOAD_SCHEDULE(name) \
     185             :   { (#name "DownloadSchedule"), (#name "DownloadInitialDelay"), 0, 1 }
     186             : #else
     187             : #define DOWNLOAD_SCHEDULE(name) { NULL, NULL, 0, 1 }
     188             : #endif /* !defined(COCCI) */
     189             : 
     190             : /** A list of abbreviations and aliases to map command-line options, obsolete
     191             :  * option names, or alternative option names, to their current values. */
     192             : static const config_abbrev_t option_abbrevs_[] = {
     193             :   PLURAL(AuthDirBadDirCC),
     194             :   PLURAL(AuthDirBadExitCC),
     195             :   PLURAL(AuthDirInvalidCC),
     196             :   PLURAL(AuthDirRejectCC),
     197             :   PLURAL(EntryNode),
     198             :   PLURAL(ExcludeNode),
     199             :   PLURAL(FirewallPort),
     200             :   PLURAL(LongLivedPort),
     201             :   PLURAL(HiddenServiceNode),
     202             :   PLURAL(HiddenServiceExcludeNode),
     203             :   PLURAL(NumCPU),
     204             :   PLURAL(RendNode),
     205             :   PLURAL(RecommendedPackage),
     206             :   PLURAL(RendExcludeNode),
     207             :   PLURAL(StrictEntryNode),
     208             :   PLURAL(StrictExitNode),
     209             :   PLURAL(StrictNode),
     210             :   { "l", "Log", 1, 0},
     211             :   { "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0},
     212             :   { "AutomapHostSuffixes", "AutomapHostsSuffixes", 0, 0},
     213             :   { "AutomapHostOnResolve", "AutomapHostsOnResolve", 0, 0},
     214             :   { "BandwidthRateBytes", "BandwidthRate", 0, 0},
     215             :   { "BandwidthBurstBytes", "BandwidthBurst", 0, 0},
     216             :   { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0},
     217             :   { "DirServer", "DirAuthority", 0, 0}, /* XXXX later, make this warn? */
     218             :   { "MaxConn", "ConnLimit", 0, 1},
     219             :   { "MaxMemInCellQueues", "MaxMemInQueues", 0, 0},
     220             :   { "ORBindAddress", "ORListenAddress", 0, 0},
     221             :   { "DirBindAddress", "DirListenAddress", 0, 0},
     222             :   { "SocksBindAddress", "SocksListenAddress", 0, 0},
     223             :   { "UseHelperNodes", "UseEntryGuards", 0, 0},
     224             :   { "NumHelperNodes", "NumEntryGuards", 0, 0},
     225             :   { "UseEntryNodes", "UseEntryGuards", 0, 0},
     226             :   { "NumEntryNodes", "NumEntryGuards", 0, 0},
     227             :   { "ResolvConf", "ServerDNSResolvConfFile", 0, 1},
     228             :   { "SearchDomains", "ServerDNSSearchDomains", 0, 1},
     229             :   { "ServerDNSAllowBrokenResolvConf", "ServerDNSAllowBrokenConfig", 0, 0},
     230             :   { "PreferTunnelledDirConns", "PreferTunneledDirConns", 0, 0},
     231             :   { "BridgeAuthoritativeDirectory", "BridgeAuthoritativeDir", 0, 0},
     232             :   { "HashedControlPassword", "__HashedControlSessionPassword", 1, 0},
     233             :   { "VirtualAddrNetwork", "VirtualAddrNetworkIPv4", 0, 0},
     234             :   { "SocksSocketsGroupWritable", "UnixSocksGroupWritable", 0, 1},
     235             :   { "_HSLayer2Nodes", "HSLayer2Nodes", 0, 1 },
     236             :   { "_HSLayer3Nodes", "HSLayer3Nodes", 0, 1 },
     237             : 
     238             :   DOWNLOAD_SCHEDULE(ClientBootstrapConsensusAuthority),
     239             :   DOWNLOAD_SCHEDULE(ClientBootstrapConsensusAuthorityOnly),
     240             :   DOWNLOAD_SCHEDULE(ClientBootstrapConsensusFallback),
     241             :   DOWNLOAD_SCHEDULE(TestingBridge),
     242             :   DOWNLOAD_SCHEDULE(TestingBridgeBootstrap),
     243             :   DOWNLOAD_SCHEDULE(TestingClient),
     244             :   DOWNLOAD_SCHEDULE(TestingClientConsensus),
     245             :   DOWNLOAD_SCHEDULE(TestingServer),
     246             :   DOWNLOAD_SCHEDULE(TestingServerConsensus),
     247             : 
     248             :   { NULL, NULL, 0, 0},
     249             : };
     250             : 
     251             : /** dummy instance of or_options_t, used for type-checking its
     252             :  * members with CONF_CHECK_VAR_TYPE. */
     253             : DUMMY_TYPECHECK_INSTANCE(or_options_t);
     254             : 
     255             : /** An entry for config_vars: "The option <b>varname</b> has type
     256             :  * CONFIG_TYPE_<b>conftype</b>, and corresponds to
     257             :  * or_options_t.<b>member</b>"
     258             :  */
     259             : #define VAR(varname,conftype,member,initvalue)                          \
     260             :   CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, 0, initvalue)
     261             : 
     262             : /* As VAR, but uses a type definition in addition to a type enum. */
     263             : #define VAR_D(varname,conftype,member,initvalue)                        \
     264             :   CONFIG_VAR_DEFN(or_options_t, varname, conftype, member, 0, initvalue)
     265             : 
     266             : #define VAR_NODUMP(varname,conftype,member,initvalue)             \
     267             :   CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member,       \
     268             :                    CFLG_NODUMP, initvalue)
     269             : #define VAR_NODUMP_IMMUTABLE(varname,conftype,member,initvalue)   \
     270             :   CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member,       \
     271             :                    CFLG_NODUMP | CFLG_IMMUTABLE, initvalue)
     272             : #define VAR_INVIS(varname,conftype,member,initvalue)              \
     273             :   CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member,       \
     274             :                    CFLG_NODUMP | CFLG_NOSET | CFLG_NOLIST, initvalue)
     275             : 
     276             : #define V(member,conftype,initvalue)            \
     277             :   VAR(#member, conftype, member, initvalue)
     278             : 
     279             : #define VAR_IMMUTABLE(varname, conftype, member, initvalue)             \
     280             :   CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member,             \
     281             :                    CFLG_IMMUTABLE, initvalue)
     282             : 
     283             : #define V_IMMUTABLE(member,conftype,initvalue)                 \
     284             :   VAR_IMMUTABLE(#member, conftype, member, initvalue)
     285             : 
     286             : /** As V, but uses a type definition instead of a type enum */
     287             : #define V_D(member,type,initvalue)              \
     288             :   VAR_D(#member, type, member, initvalue)
     289             : 
     290             : /** An entry for config_vars: "The option <b>varname</b> is obsolete." */
     291             : #define OBSOLETE(varname) CONFIG_VAR_OBSOLETE(varname)
     292             : 
     293             : /**
     294             :  * Macro to declare *Port options.  Each one comes in three entries.
     295             :  * For example, most users should use "SocksPort" to configure the
     296             :  * socks port, but TorBrowser wants to use __SocksPort so that it
     297             :  * isn't stored by SAVECONF.  The SocksPortLines virtual option is
     298             :  * used to query both options from the controller.
     299             :  */
     300             : #define VPORT(member)                                           \
     301             :   VAR(#member "Lines", LINELIST_V, member ## _lines, NULL),     \
     302             :   VAR(#member, LINELIST_S, member ## _lines, NULL),             \
     303             :   VAR_NODUMP("__" #member, LINELIST_S, member ## _lines, NULL)
     304             : 
     305             : /** UINT64_MAX as a decimal string */
     306             : #define UINT64_MAX_STRING "18446744073709551615"
     307             : 
     308             : /** Array of configuration options.  Until we disallow nonstandard
     309             :  * abbreviations, order is significant, since the first matching option will
     310             :  * be chosen first.
     311             :  */
     312             : static const config_var_t option_vars_[] = {
     313             :   V(AccountingMax,               MEMUNIT,  "0 bytes"),
     314             :   VAR("AccountingRule",          STRING,   AccountingRule_option,  "max"),
     315             :   V(AccountingStart,             STRING,   NULL),
     316             :   V(Address,                     LINELIST, NULL),
     317             :   V(AddressDisableIPv6,          BOOL,     "0"),
     318             :   OBSOLETE("AllowDotExit"),
     319             :   OBSOLETE("AllowInvalidNodes"),
     320             :   V(AllowNonRFC953Hostnames,     BOOL,     "0"),
     321             :   OBSOLETE("AllowSingleHopCircuits"),
     322             :   OBSOLETE("AllowSingleHopExits"),
     323             :   V(AlternateBridgeAuthority,    LINELIST, NULL),
     324             :   V(AlternateDirAuthority,       LINELIST, NULL),
     325             :   OBSOLETE("AlternateHSAuthority"),
     326             :   V(AssumeReachable,             BOOL,     "0"),
     327             :   V(AssumeReachableIPv6,         AUTOBOOL, "auto"),
     328             :   OBSOLETE("AuthDirBadDir"),
     329             :   OBSOLETE("AuthDirBadDirCCs"),
     330             :   V(AuthDirBadExit,              LINELIST, NULL),
     331             :   V(AuthDirBadExitCCs,           CSV,      ""),
     332             :   V(AuthDirInvalid,              LINELIST, NULL),
     333             :   V(AuthDirInvalidCCs,           CSV,      ""),
     334             :   V(AuthDirReject,               LINELIST, NULL),
     335             :   V(AuthDirRejectCCs,            CSV,      ""),
     336             :   OBSOLETE("AuthDirRejectUnlisted"),
     337             :   OBSOLETE("AuthDirListBadDirs"),
     338             :   OBSOLETE("AuthDirMaxServersPerAuthAddr"),
     339             :   VAR("AuthoritativeDirectory",  BOOL, AuthoritativeDir,    "0"),
     340             :   V(AutomapHostsOnResolve,       BOOL,     "0"),
     341             :   V(AutomapHostsSuffixes,        CSV,      ".onion,.exit"),
     342             :   V(AvoidDiskWrites,             BOOL,     "0"),
     343             :   V(BandwidthBurst,              MEMUNIT,  "1 GB"),
     344             :   V(BandwidthRate,               MEMUNIT,  "1 GB"),
     345             :   V(BridgeAuthoritativeDir,      BOOL,     "0"),
     346             :   VAR("Bridge",                  LINELIST, Bridges,    NULL),
     347             :   V(BridgePassword,              STRING,   NULL),
     348             :   V(BridgeRecordUsageByCountry,  BOOL,     "1"),
     349             :   V(BridgeRelay,                 BOOL,     "0"),
     350             :   V(BridgeDistribution,          STRING,   NULL),
     351             :   VAR_IMMUTABLE("CacheDirectory",FILENAME, CacheDirectory_option, NULL),
     352             :   V(CacheDirectoryGroupReadable, AUTOBOOL,     "auto"),
     353             :   V(CellStatistics,              BOOL,     "0"),
     354             :   V(PaddingStatistics,           BOOL,     "1"),
     355             :   V(OverloadStatistics,          BOOL,     "1"),
     356             :   V(LearnCircuitBuildTimeout,    BOOL,     "1"),
     357             :   V(CircuitBuildTimeout,         INTERVAL, "0"),
     358             :   OBSOLETE("CircuitIdleTimeout"),
     359             :   V(CircuitsAvailableTimeout,    INTERVAL, "0"),
     360             :   V(CircuitStreamTimeout,        INTERVAL, "0"),
     361             :   V(CircuitPriorityHalflife,     DOUBLE,  "-1.0"), /*negative:'Use default'*/
     362             :   V(ClientDNSRejectInternalAddresses, BOOL,"1"),
     363             : #if defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS)
     364             :   /* The unit tests expect the ClientOnly default to be 0. */
     365             :   V(ClientOnly,                  BOOL,     "0"),
     366             : #else
     367             :   /* We must be a Client if the relay module is disabled. */
     368             :   V(ClientOnly,                  BOOL,     "1"),
     369             : #endif /* defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) */
     370             :   V(ClientPreferIPv6ORPort,      AUTOBOOL, "auto"),
     371             :   V(ClientPreferIPv6DirPort,     AUTOBOOL, "auto"),
     372             :   OBSOLETE("ClientAutoIPv6ORPort"),
     373             :   V(ClientRejectInternalAddresses, BOOL,   "1"),
     374             :   V(ClientTransportPlugin,       LINELIST, NULL),
     375             :   V(ClientUseIPv6,               BOOL,     "0"),
     376             :   V(ClientUseIPv4,               BOOL,     "1"),
     377             :   V(ConnLimit,                   POSINT,     "1000"),
     378             :   V(ConnDirectionStatistics,     BOOL,     "0"),
     379             :   V(ConstrainedSockets,          BOOL,     "0"),
     380             :   V(ConstrainedSockSize,         MEMUNIT,  "8192"),
     381             :   V(ContactInfo,                 STRING,   NULL),
     382             :   OBSOLETE("ControlListenAddress"),
     383             :   VPORT(ControlPort),
     384             :   V(ControlPortFileGroupReadable,BOOL,     "0"),
     385             :   V(ControlPortWriteToFile,      FILENAME, NULL),
     386             :   V(ControlSocket,               LINELIST, NULL),
     387             :   V(ControlSocketsGroupWritable, BOOL,     "0"),
     388             :   V(UnixSocksGroupWritable,    BOOL,     "0"),
     389             :   V(CookieAuthentication,        BOOL,     "0"),
     390             :   V(CookieAuthFileGroupReadable, BOOL,     "0"),
     391             :   V(CookieAuthFile,              FILENAME, NULL),
     392             :   V(CountPrivateBandwidth,       BOOL,     "0"),
     393             :   VAR_IMMUTABLE("DataDirectory", FILENAME, DataDirectory_option, NULL),
     394             :   V(DataDirectoryGroupReadable,  BOOL,     "0"),
     395             :   V(DisableOOSCheck,             BOOL,     "1"),
     396             :   V(DisableNetwork,              BOOL,     "0"),
     397             :   V(DirAllowPrivateAddresses,    BOOL,     "0"),
     398             :   OBSOLETE("DirListenAddress"),
     399             :   V(DirPolicy,                   LINELIST, NULL),
     400             :   VPORT(DirPort),
     401             :   V(DirPortFrontPage,            FILENAME, NULL),
     402             :   VAR("DirReqStatistics",        BOOL,     DirReqStatistics_option, "1"),
     403             :   VAR("DirAuthority",            LINELIST, DirAuthorities, NULL),
     404             : #if defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS)
     405             :   /* The unit tests expect the DirCache default to be 1. */
     406             :   V(DirCache,                    BOOL,     "1"),
     407             : #else
     408             :   /* We can't be a DirCache if the relay module is disabled. */
     409             :   V(DirCache,                    BOOL,     "0"),
     410             : #endif /* defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) */
     411             :   /* A DirAuthorityFallbackRate of 0.1 means that 0.5% of clients try an
     412             :    * authority when all fallbacks are up, and 2% try an authority when 25% of
     413             :    * fallbacks are down. (We rebuild the list when 25% of fallbacks are down).
     414             :    *
     415             :    * We want to reduce load on authorities, but keep these two figures within
     416             :    * an order of magnitude, so there isn't too much load shifting to
     417             :    * authorities when fallbacks go down. */
     418             :   V(DirAuthorityFallbackRate,    DOUBLE,   "0.1"),
     419             :   V_IMMUTABLE(DisableAllSwap,    BOOL,     "0"),
     420             :   V_IMMUTABLE(DisableDebuggerAttachment,   BOOL,     "1"),
     421             :   OBSOLETE("DisableIOCP"),
     422             :   OBSOLETE("DisableV2DirectoryInfo_"),
     423             :   OBSOLETE("DynamicDHGroups"),
     424             :   VPORT(DNSPort),
     425             :   OBSOLETE("DNSListenAddress"),
     426             :   V(DormantClientTimeout,        INTERVAL, "24 hours"),
     427             :   V(DormantTimeoutEnabled,       BOOL,     "1"),
     428             :   V(DormantTimeoutDisabledByIdleStreams,   BOOL,     "1"),
     429             :   V(DormantOnFirstStartup,       BOOL,      "0"),
     430             :   V(DormantCanceledByStartup,    BOOL,      "0"),
     431             :   V(DownloadExtraInfo,           BOOL,     "0"),
     432             :   V(TestingEnableConnBwEvent,    BOOL,     "0"),
     433             :   V(TestingEnableCellStatsEvent, BOOL,     "0"),
     434             :   OBSOLETE("TestingEnableTbEmptyEvent"),
     435             :   V(EnforceDistinctSubnets,      BOOL,     "1"),
     436             :   V_D(EntryNodes,                ROUTERSET,   NULL),
     437             :   V(EntryStatistics,             BOOL,     "0"),
     438             :   OBSOLETE("TestingEstimatedDescriptorPropagationTime"),
     439             :   V_D(ExcludeNodes,              ROUTERSET, NULL),
     440             :   V_D(ExcludeExitNodes,          ROUTERSET, NULL),
     441             :   OBSOLETE("ExcludeSingleHopRelays"),
     442             :   V_D(ExitNodes,                 ROUTERSET, NULL),
     443             :   /* Researchers need a way to tell their clients to use specific
     444             :    * middles that they also control, to allow safe live-network
     445             :    * experimentation with new padding machines. */
     446             :   V_D(MiddleNodes,               ROUTERSET, NULL),
     447             :   V(ExitPolicy,                  LINELIST, NULL),
     448             :   V(ExitPolicyRejectPrivate,     BOOL,     "1"),
     449             :   V(ExitPolicyRejectLocalInterfaces, BOOL, "0"),
     450             :   V(ExitPortStatistics,          BOOL,     "0"),
     451             :   V(ExtendAllowPrivateAddresses, BOOL,     "0"),
     452             :   V(ExitRelay,                   AUTOBOOL, "auto"),
     453             :   VPORT(ExtORPort),
     454             :   V(ExtORPortCookieAuthFile,     FILENAME,   NULL),
     455             :   V(ExtORPortCookieAuthFileGroupReadable, BOOL, "0"),
     456             :   V(ExtraInfoStatistics,         BOOL,     "1"),
     457             :   V(ExtendByEd25519ID,           AUTOBOOL, "auto"),
     458             :   V(FallbackDir,                 LINELIST, NULL),
     459             : 
     460             :   V(UseDefaultFallbackDirs,      BOOL,     "1"),
     461             : 
     462             :   OBSOLETE("FallbackNetworkstatusFile"),
     463             :   V(FascistFirewall,             BOOL,     "0"),
     464             :   V(FirewallPorts,               CSV,      ""),
     465             :   OBSOLETE("FastFirstHopPK"),
     466             :   V(FetchDirInfoEarly,           BOOL,     "0"),
     467             :   V(FetchDirInfoExtraEarly,      BOOL,     "0"),
     468             :   V(FetchServerDescriptors,      BOOL,     "1"),
     469             :   V(FetchHidServDescriptors,     BOOL,     "1"),
     470             :   V(FetchUselessDescriptors,     BOOL,     "0"),
     471             :   OBSOLETE("FetchV2Networkstatus"),
     472             :   V(GeoIPExcludeUnknown,         AUTOBOOL, "auto"),
     473             : #ifdef _WIN32
     474             :   V(GeoIPFile,                   FILENAME, "<default>"),
     475             :   V(GeoIPv6File,                 FILENAME, "<default>"),
     476             : #else
     477             :   V(GeoIPFile,                   FILENAME,
     478             :     SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"),
     479             :   V(GeoIPv6File,                 FILENAME,
     480             :     SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"),
     481             : #endif /* defined(_WIN32) */
     482             :   OBSOLETE("Group"),
     483             :   V(GuardLifetime,               INTERVAL, "0 minutes"),
     484             :   V(HeartbeatPeriod,             INTERVAL, "6 hours"),
     485             :   V(MainloopStats,               BOOL,     "0"),
     486             :   V(HashedControlPassword,       LINELIST, NULL),
     487             :   OBSOLETE("HidServDirectoryV2"),
     488             :   OBSOLETE("HiddenServiceAuthorizeClient"),
     489             :   OBSOLETE("HidServAuth"),
     490             :   VAR("HiddenServiceDir",    LINELIST_S, RendConfigLines,    NULL),
     491             :   VAR("HiddenServiceDirGroupReadable",  LINELIST_S, RendConfigLines, NULL),
     492             :   VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines,    NULL),
     493             :   VAR("HiddenServicePort",   LINELIST_S, RendConfigLines,    NULL),
     494             :   VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines,    NULL),
     495             :   VAR("HiddenServiceAllowUnknownPorts",LINELIST_S, RendConfigLines, NULL),
     496             :   VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL),
     497             :   VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL),
     498             :   VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL),
     499             :   VAR("HiddenServiceExportCircuitID", LINELIST_S,  RendConfigLines, NULL),
     500             :   VAR("HiddenServiceEnableIntroDoSDefense", LINELIST_S, RendConfigLines, NULL),
     501             :   VAR("HiddenServiceEnableIntroDoSRatePerSec",
     502             :       LINELIST_S, RendConfigLines, NULL),
     503             :   VAR("HiddenServiceEnableIntroDoSBurstPerSec",
     504             :       LINELIST_S, RendConfigLines, NULL),
     505             :   VAR("HiddenServiceOnionBalanceInstance",
     506             :       LINELIST_S, RendConfigLines, NULL),
     507             :   VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"),
     508             :   V(ClientOnionAuthDir,          FILENAME, NULL),
     509             :   OBSOLETE("CloseHSClientCircuitsImmediatelyOnTimeout"),
     510             :   OBSOLETE("CloseHSServiceRendCircuitsImmediatelyOnTimeout"),
     511             :   V_IMMUTABLE(HiddenServiceSingleHopMode,  BOOL,     "0"),
     512             :   V_IMMUTABLE(HiddenServiceNonAnonymousMode,BOOL,    "0"),
     513             :   V(HTTPProxy,                   STRING,   NULL),
     514             :   V(HTTPProxyAuthenticator,      STRING,   NULL),
     515             :   V(HTTPSProxy,                  STRING,   NULL),
     516             :   V(HTTPSProxyAuthenticator,     STRING,   NULL),
     517             :   VPORT(HTTPTunnelPort),
     518             :   V(IPv6Exit,                    BOOL,     "0"),
     519             :   VAR("ServerTransportPlugin",   LINELIST, ServerTransportPlugin,  NULL),
     520             :   V(ServerTransportListenAddr,   LINELIST, NULL),
     521             :   V(ServerTransportOptions,      LINELIST, NULL),
     522             :   V(SigningKeyLifetime,          INTERVAL, "30 days"),
     523             :   V(Socks4Proxy,                 STRING,   NULL),
     524             :   V(Socks5Proxy,                 STRING,   NULL),
     525             :   V(Socks5ProxyUsername,         STRING,   NULL),
     526             :   V(Socks5ProxyPassword,         STRING,   NULL),
     527             :   V(TCPProxy,                    STRING,   NULL),
     528             :   VAR_IMMUTABLE("KeyDirectory",  FILENAME, KeyDirectory_option, NULL),
     529             :   V(KeyDirectoryGroupReadable,   AUTOBOOL, "auto"),
     530             :   VAR_D("HSLayer2Nodes",         ROUTERSET,  HSLayer2Nodes,  NULL),
     531             :   VAR_D("HSLayer3Nodes",         ROUTERSET,  HSLayer3Nodes,  NULL),
     532             :   V(KeepalivePeriod,             INTERVAL, "5 minutes"),
     533             :   V_IMMUTABLE(KeepBindCapabilities,        AUTOBOOL, "auto"),
     534             :   VAR("Log",                     LINELIST, Logs,             NULL),
     535             :   V(LogMessageDomains,           BOOL,     "0"),
     536             :   V(LogTimeGranularity,          MSEC_INTERVAL, "1 second"),
     537             :   V(TruncateLogFile,             BOOL,     "0"),
     538             :   V_IMMUTABLE(SyslogIdentityTag, STRING,   NULL),
     539             :   OBSOLETE("AndroidIdentityTag"),
     540             :   V(LongLivedPorts,              CSV,
     541             :         "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
     542             :   VAR("MapAddress",              LINELIST, AddressMap,           NULL),
     543             :   V(MaxAdvertisedBandwidth,      MEMUNIT,  "1 GB"),
     544             :   V(MaxCircuitDirtiness,         INTERVAL, "10 minutes"),
     545             :   V(MaxClientCircuitsPending,    POSINT,     "32"),
     546             :   V(MaxConsensusAgeForDiffs,     INTERVAL, "0 seconds"),
     547             :   VAR("MaxMemInQueues",          MEMUNIT,   MaxMemInQueues_raw, "0"),
     548             :   OBSOLETE("MaxOnionsPending"),
     549             :   V(MaxOnionQueueDelay,          MSEC_INTERVAL, "1750 msec"),
     550             :   V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"),
     551             :   VPORT(MetricsPort),
     552             :   V(MetricsPortPolicy,           LINELIST, NULL),
     553             :   VAR("MyFamily",                LINELIST, MyFamily_lines,       NULL),
     554             :   V(NewCircuitPeriod,            INTERVAL, "30 seconds"),
     555             :   OBSOLETE("NamingAuthoritativeDirectory"),
     556             :   OBSOLETE("NATDListenAddress"),
     557             :   VPORT(NATDPort),
     558             :   V(Nickname,                    STRING,   NULL),
     559             :   OBSOLETE("PredictedPortsRelevanceTime"),
     560             :   OBSOLETE("WarnUnsafeSocks"),
     561             :   VAR("NodeFamily",              LINELIST, NodeFamilies,         NULL),
     562             :   V_IMMUTABLE(NoExec,            BOOL,     "0"),
     563             :   V(NumCPUs,                     POSINT,     "0"),
     564             :   V(NumDirectoryGuards,          POSINT,     "0"),
     565             :   V(NumEntryGuards,              POSINT,     "0"),
     566             :   V(NumPrimaryGuards,            POSINT,     "0"),
     567             :   V(OfflineMasterKey,            BOOL,     "0"),
     568             :   OBSOLETE("ORListenAddress"),
     569             :   VPORT(ORPort),
     570             :   V(OutboundBindAddress,         LINELIST,   NULL),
     571             :   V(OutboundBindAddressOR,       LINELIST,   NULL),
     572             :   V(OutboundBindAddressExit,     LINELIST,   NULL),
     573             :   V(OutboundBindAddressPT,       LINELIST,   NULL),
     574             : 
     575             :   OBSOLETE("PathBiasDisableRate"),
     576             :   V(PathBiasCircThreshold,       INT,      "-1"),
     577             :   V(PathBiasNoticeRate,          DOUBLE,   "-1"),
     578             :   V(PathBiasWarnRate,            DOUBLE,   "-1"),
     579             :   V(PathBiasExtremeRate,         DOUBLE,   "-1"),
     580             :   V(PathBiasScaleThreshold,      INT,      "-1"),
     581             :   OBSOLETE("PathBiasScaleFactor"),
     582             :   OBSOLETE("PathBiasMultFactor"),
     583             :   V(PathBiasDropGuards,          AUTOBOOL, "0"),
     584             :   OBSOLETE("PathBiasUseCloseCounts"),
     585             : 
     586             :   V(PathBiasUseThreshold,       INT,      "-1"),
     587             :   V(PathBiasNoticeUseRate,          DOUBLE,   "-1"),
     588             :   V(PathBiasExtremeUseRate,         DOUBLE,   "-1"),
     589             :   V(PathBiasScaleUseThreshold,      INT,      "-1"),
     590             : 
     591             :   V(PathsNeededToBuildCircuits,  DOUBLE,   "-1"),
     592             :   V(PerConnBWBurst,              MEMUNIT,  "0"),
     593             :   V(PerConnBWRate,               MEMUNIT,  "0"),
     594             :   V_IMMUTABLE(PidFile,           FILENAME,   NULL),
     595             :   V_IMMUTABLE(TestingTorNetwork, BOOL,     "0"),
     596             : 
     597             :   V(TestingLinkCertLifetime,          INTERVAL, "2 days"),
     598             :   V(TestingAuthKeyLifetime,          INTERVAL, "2 days"),
     599             :   V(TestingLinkKeySlop,              INTERVAL, "3 hours"),
     600             :   V(TestingAuthKeySlop,              INTERVAL, "3 hours"),
     601             :   V(TestingSigningKeySlop,           INTERVAL, "1 day"),
     602             : 
     603             :   OBSOLETE("OptimisticData"),
     604             :   OBSOLETE("PortForwarding"),
     605             :   OBSOLETE("PortForwardingHelper"),
     606             :   OBSOLETE("PreferTunneledDirConns"),
     607             :   V(ProtocolWarnings,            BOOL,     "0"),
     608             :   V(PublishServerDescriptor,     CSV,      "1"),
     609             :   V(PublishHidServDescriptors,   BOOL,     "1"),
     610             :   V(ReachableAddresses,          LINELIST, NULL),
     611             :   V(ReachableDirAddresses,       LINELIST, NULL),
     612             :   V(ReachableORAddresses,        LINELIST, NULL),
     613             :   OBSOLETE("RecommendedPackages"),
     614             :   V(ReducedConnectionPadding,    BOOL,     "0"),
     615             :   V(ConnectionPadding,           AUTOBOOL, "auto"),
     616             :   V(RefuseUnknownExits,          AUTOBOOL, "auto"),
     617             :   V(CircuitPadding,              BOOL,     "1"),
     618             :   V(ReducedCircuitPadding,       BOOL,     "0"),
     619             :   V(RejectPlaintextPorts,        CSV,      ""),
     620             :   V(RelayBandwidthBurst,         MEMUNIT,  "0"),
     621             :   V(RelayBandwidthRate,          MEMUNIT,  "0"),
     622             :   V(RendPostPeriod,              INTERVAL, "1 hour"), /* Used internally. */
     623             :   V(RephistTrackTime,            INTERVAL, "24 hours"),
     624             :   V_IMMUTABLE(RunAsDaemon,       BOOL,     "0"),
     625             :   V(ReducedExitPolicy,           BOOL,     "0"),
     626             :   OBSOLETE("RunTesting"), // currently unused
     627             :   V_IMMUTABLE(Sandbox,           BOOL,     "0"),
     628             :   V(SafeLogging,                 STRING,   "1"),
     629             :   V(SafeSocks,                   BOOL,     "0"),
     630             :   V(ServerDNSAllowBrokenConfig,  BOOL,     "1"),
     631             :   V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"),
     632             :   V(ServerDNSDetectHijacking,    BOOL,     "1"),
     633             :   V(ServerDNSRandomizeCase,      BOOL,     "1"),
     634             :   V(ServerDNSResolvConfFile,     FILENAME,   NULL),
     635             :   V(ServerDNSSearchDomains,      BOOL,     "0"),
     636             :   V(ServerDNSTestAddresses,      CSV,
     637             :       "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"),
     638             :   OBSOLETE("SchedulerLowWaterMark__"),
     639             :   OBSOLETE("SchedulerHighWaterMark__"),
     640             :   OBSOLETE("SchedulerMaxFlushCells__"),
     641             :   V(KISTSchedRunInterval,        MSEC_INTERVAL, "0 msec"),
     642             :   V(KISTSockBufSizeFactor,       DOUBLE,   "1.0"),
     643             :   V(Schedulers,                  CSV,      "KIST,KISTLite,Vanilla"),
     644             :   V(ShutdownWaitLength,          INTERVAL, "30 seconds"),
     645             :   OBSOLETE("SocksListenAddress"),
     646             :   V(SocksPolicy,                 LINELIST, NULL),
     647             :   VPORT(SocksPort),
     648             :   V(SocksTimeout,                INTERVAL, "2 minutes"),
     649             :   V(SSLKeyLifetime,              INTERVAL, "0"),
     650             :   OBSOLETE("StrictEntryNodes"),
     651             :   OBSOLETE("StrictExitNodes"),
     652             :   V(StrictNodes,                 BOOL,     "0"),
     653             :   OBSOLETE("Support022HiddenServices"),
     654             :   V(TestSocks,                   BOOL,     "0"),
     655             :   V_IMMUTABLE(TokenBucketRefillInterval,   MSEC_INTERVAL, "100 msec"),
     656             :   OBSOLETE("Tor2webMode"),
     657             :   OBSOLETE("Tor2webRendezvousPoints"),
     658             :   OBSOLETE("TLSECGroup"),
     659             :   V(TrackHostExits,              CSV,      NULL),
     660             :   V(TrackHostExitsExpire,        INTERVAL, "30 minutes"),
     661             :   OBSOLETE("TransListenAddress"),
     662             :   VPORT(TransPort),
     663             :   V(TransProxyType,              STRING,   "default"),
     664             :   OBSOLETE("TunnelDirConns"),
     665             :   V(UpdateBridgesFromAuthority,  BOOL,     "0"),
     666             :   V(UseBridges,                  BOOL,     "0"),
     667             :   VAR("UseEntryGuards",          BOOL,     UseEntryGuards_option, "1"),
     668             :   OBSOLETE("UseEntryGuardsAsDirGuards"),
     669             :   V(UseGuardFraction,            AUTOBOOL, "auto"),
     670             :   V(UseMicrodescriptors,         AUTOBOOL, "auto"),
     671             :   OBSOLETE("UseNTorHandshake"),
     672             :   V_IMMUTABLE(User,              STRING,   NULL),
     673             :   OBSOLETE("UserspaceIOCPBuffers"),
     674             :   OBSOLETE("V1AuthoritativeDirectory"),
     675             :   OBSOLETE("V2AuthoritativeDirectory"),
     676             :   VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir,   "0"),
     677             :   V(TestingV3AuthInitialVotingInterval, INTERVAL, "30 minutes"),
     678             :   V(TestingV3AuthInitialVoteDelay, INTERVAL, "5 minutes"),
     679             :   V(TestingV3AuthInitialDistDelay, INTERVAL, "5 minutes"),
     680             :   V(TestingV3AuthVotingStartOffset, INTERVAL, "0"),
     681             :   V(V3AuthVotingInterval,        INTERVAL, "1 hour"),
     682             :   V(V3AuthVoteDelay,             INTERVAL, "5 minutes"),
     683             :   V(V3AuthDistDelay,             INTERVAL, "5 minutes"),
     684             :   V(V3AuthNIntervalsValid,       POSINT,     "3"),
     685             :   V(V3AuthUseLegacyKey,          BOOL,     "0"),
     686             :   V(V3BandwidthsFile,            FILENAME, NULL),
     687             :   V(GuardfractionFile,           FILENAME, NULL),
     688             :   OBSOLETE("VoteOnHidServDirectoriesV2"),
     689             :   V(VirtualAddrNetworkIPv4,      STRING,   "127.192.0.0/10"),
     690             :   V(VirtualAddrNetworkIPv6,      STRING,   "[FE80::]/10"),
     691             :   V(WarnPlaintextPorts,          CSV,      "23,109,110,143"),
     692             :   OBSOLETE("UseFilteringSSLBufferevents"),
     693             :   OBSOLETE("__UseFilteringSSLBufferevents"),
     694             :   VAR_NODUMP("__ReloadTorrcOnSIGHUP",   BOOL,  ReloadTorrcOnSIGHUP,      "1"),
     695             :   VAR_NODUMP("__AllDirActionsPrivate",  BOOL,  AllDirActionsPrivate,     "0"),
     696             :   VAR_NODUMP("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
     697             :   VAR_NODUMP_IMMUTABLE("__DisableSignalHandlers", BOOL,
     698             :                        DisableSignalHandlers,    "0"),
     699             :   VAR_NODUMP("__LeaveStreamsUnattached",BOOL,  LeaveStreamsUnattached,   "0"),
     700             :   VAR_NODUMP("__HashedControlSessionPassword", LINELIST,
     701             :              HashedControlSessionPassword,
     702             :       NULL),
     703             :   VAR_NODUMP("__OwningControllerProcess",STRING,
     704             :                        OwningControllerProcess, NULL),
     705             :   VAR_NODUMP_IMMUTABLE("__OwningControllerFD", UINT64, OwningControllerFD,
     706             :              UINT64_MAX_STRING),
     707             :   V(TestingServerDownloadInitialDelay, CSV_INTERVAL, "0"),
     708             :   V(TestingClientDownloadInitialDelay, CSV_INTERVAL, "0"),
     709             :   V(TestingServerConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
     710             :   V(TestingClientConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
     711             :   /* With the ClientBootstrapConsensus*Download* below:
     712             :    * Clients with only authorities will try:
     713             :    *  - at least 3 authorities over 10 seconds, then exponentially backoff,
     714             :    *    with the next attempt 3-21 seconds later,
     715             :    * Clients with authorities and fallbacks will try:
     716             :    *  - at least 2 authorities and 4 fallbacks over 21 seconds, then
     717             :    *    exponentially backoff, with the next attempts 4-33 seconds later,
     718             :    * Clients will also retry when an application request arrives.
     719             :    * After a number of failed requests, clients retry every 3 days + 1 hour.
     720             :    *
     721             :    * Clients used to try 2 authorities over 10 seconds, then wait for
     722             :    * 60 minutes or an application request.
     723             :    *
     724             :    * When clients have authorities and fallbacks available, they use these
     725             :    * schedules: (we stagger the times to avoid thundering herds) */
     726             :   V(ClientBootstrapConsensusAuthorityDownloadInitialDelay, CSV_INTERVAL, "6"),
     727             :   V(ClientBootstrapConsensusFallbackDownloadInitialDelay, CSV_INTERVAL, "0"),
     728             :   /* When clients only have authorities available, they use this schedule: */
     729             :   V(ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay, CSV_INTERVAL,
     730             :     "0"),
     731             :   /* We don't want to overwhelm slow networks (or mirrors whose replies are
     732             :    * blocked), but we also don't want to fail if only some mirrors are
     733             :    * blackholed. Clients will try 3 directories simultaneously.
     734             :    * (Relays never use simultaneous connections.) */
     735             :   V(ClientBootstrapConsensusMaxInProgressTries, POSINT, "3"),
     736             :   /* When a client has any running bridges, check each bridge occasionally,
     737             :     * whether or not that bridge is actually up. */
     738             :   V(TestingBridgeDownloadInitialDelay, CSV_INTERVAL,"10800"),
     739             :   /* When a client is just starting, or has no running bridges, check each
     740             :    * bridge a few times quickly, and then try again later. These schedules
     741             :    * are much longer than the other schedules, because we try each and every
     742             :    * configured bridge with this schedule. */
     743             :   V(TestingBridgeBootstrapDownloadInitialDelay, CSV_INTERVAL, "0"),
     744             :   V(TestingClientMaxIntervalWithoutRequest, INTERVAL, "10 minutes"),
     745             :   V(TestingDirConnectionMaxStall, INTERVAL, "5 minutes"),
     746             :   OBSOLETE("TestingConsensusMaxDownloadTries"),
     747             :   OBSOLETE("ClientBootstrapConsensusMaxDownloadTries"),
     748             :   OBSOLETE("ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries"),
     749             :   OBSOLETE("TestingDescriptorMaxDownloadTries"),
     750             :   OBSOLETE("TestingMicrodescMaxDownloadTries"),
     751             :   OBSOLETE("TestingCertMaxDownloadTries"),
     752             :   VAR_INVIS("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_,
     753             :             "0"),
     754             : 
     755             :   END_OF_CONFIG_VARS
     756             : };
     757             : 
     758             : /** List of default directory authorities */
     759             : static const char *default_authorities[] = {
     760             : #ifndef COCCI
     761             : #include "auth_dirs.inc"
     762             : #endif
     763             :   NULL
     764             : };
     765             : 
     766             : /** List of fallback directory authorities. The list is generated by opt-in of
     767             :  * relays that meet certain stability criteria.
     768             :  */
     769             : static const char *default_fallbacks[] = {
     770             : #ifndef COCCI
     771             : #include "fallback_dirs.inc"
     772             : #endif
     773             :   NULL
     774             : };
     775             : 
     776             : /** Override default values with these if the user sets the TestingTorNetwork
     777             :  * option. */
     778             : static const struct {
     779             :   const char *k;
     780             :   const char *v;
     781             : } testing_tor_network_defaults[] = {
     782             : #ifndef COCCI
     783             : #include "testnet.inc"
     784             : #endif
     785             :   { NULL, NULL }
     786             : };
     787             : 
     788             : #undef VAR
     789             : #undef V
     790             : #undef OBSOLETE
     791             : 
     792             : static const config_deprecation_t option_deprecation_notes_[] = {
     793             :   /* Deprecated since 0.3.2.0-alpha. */
     794             :   { "HTTPProxy", "It only applies to direct unencrypted HTTP connections "
     795             :     "to your directory server, which your Tor probably wasn't using." },
     796             :   { "HTTPProxyAuthenticator", "HTTPProxy is deprecated in favor of HTTPSProxy "
     797             :     "which should be used with HTTPSProxyAuthenticator." },
     798             :   /* End of options deprecated since 0.3.2.1-alpha */
     799             : 
     800             :   /* Options deprecated since 0.3.2.2-alpha */
     801             :   { "ReachableDirAddresses", "It has no effect on relays, and has had no "
     802             :     "effect on clients since 0.2.8." },
     803             :   { "ClientPreferIPv6DirPort", "It has no effect on relays, and has had no "
     804             :     "effect on clients since 0.2.8." },
     805             :   /* End of options deprecated since 0.3.2.2-alpha. */
     806             : 
     807             :   /* Options deprecated since 0.4.3.1-alpha. */
     808             :   { "ClientAutoIPv6ORPort", "This option is unreliable if a connection isn't "
     809             :     "reliably dual-stack."},
     810             :   /* End of options deprecated since 0.4.3.1-alpha. */
     811             : 
     812             :   { NULL, NULL }
     813             : };
     814             : 
     815             : #ifdef _WIN32
     816             : static char *get_windows_conf_root(void);
     817             : #endif
     818             : 
     819             : static int options_check_transition_cb(const void *old,
     820             :                                        const void *new,
     821             :                                        char **msg);
     822             : static int validate_data_directories(or_options_t *options);
     823             : static int write_configuration_file(const char *fname,
     824             :                                     const or_options_t *options);
     825             : 
     826             : static void init_libevent(const or_options_t *options);
     827             : static int opt_streq(const char *s1, const char *s2);
     828             : static int parse_outbound_addresses(or_options_t *options, int validate_only,
     829             :                                     char **msg);
     830             : static void config_maybe_load_geoip_files_(const or_options_t *options,
     831             :                                            const or_options_t *old_options);
     832             : static int options_validate_cb(const void *old_options, void *options,
     833             :                                char **msg);
     834             : static void cleanup_protocol_warning_severity_level(void);
     835             : static void set_protocol_warning_severity_level(int warning_severity);
     836             : static void options_clear_cb(const config_mgr_t *mgr, void *opts);
     837             : static setopt_err_t options_validate_and_set(const or_options_t *old_options,
     838             :                                              or_options_t *new_options,
     839             :                                              char **msg_out);
     840             : struct listener_transaction_t;
     841             : static void options_rollback_listener_transaction(
     842             :                                            struct listener_transaction_t *xn);
     843             : 
     844             : /** Magic value for or_options_t. */
     845             : #define OR_OPTIONS_MAGIC 9090909
     846             : 
     847             : /** Configuration format for or_options_t. */
     848             : static const config_format_t options_format = {
     849             :   .size = sizeof(or_options_t),
     850             :   .magic = {
     851             :    "or_options_t",
     852             :    OR_OPTIONS_MAGIC,
     853             :    offsetof(or_options_t, magic_),
     854             :   },
     855             :   .abbrevs = option_abbrevs_,
     856             :   .deprecations = option_deprecation_notes_,
     857             :   .vars = option_vars_,
     858             :   .legacy_validate_fn = options_validate_cb,
     859             :   .check_transition_fn = options_check_transition_cb,
     860             :   .clear_fn = options_clear_cb,
     861             :   .has_config_suite = true,
     862             :   .config_suite_offset = offsetof(or_options_t, subconfigs_),
     863             : };
     864             : 
     865             : /*
     866             :  * Functions to read and write the global options pointer.
     867             :  */
     868             : 
     869             : /** Command-line and config-file options. */
     870             : static or_options_t *global_options = NULL;
     871             : /** The fallback options_t object; this is where we look for options not
     872             :  * in torrc before we fall back to Tor's defaults. */
     873             : static or_options_t *global_default_options = NULL;
     874             : /** Name of most recently read torrc file. */
     875             : static char *torrc_fname = NULL;
     876             : /** Name of the most recently read torrc-defaults file.*/
     877             : static char *torrc_defaults_fname = NULL;
     878             : /** Result of parsing the command line. */
     879             : static parsed_cmdline_t *global_cmdline = NULL;
     880             : /** List of port_cfg_t for all configured ports. */
     881             : static smartlist_t *configured_ports = NULL;
     882             : /** True iff we're currently validating options, and any calls to
     883             :  * get_options() are likely to be bugs. */
     884             : static int in_option_validation = 0;
     885             : /** True iff we have run options_act_once_on_startup() */
     886             : static bool have_set_startup_options = false;
     887             : 
     888             : /* A global configuration manager to handle all configuration objects. */
     889             : static config_mgr_t *options_mgr = NULL;
     890             : 
     891             : /** Return the global configuration manager object for torrc options. */
     892             : STATIC const config_mgr_t *
     893       32238 : get_options_mgr(void)
     894             : {
     895       32238 :   if (PREDICT_UNLIKELY(options_mgr == NULL)) {
     896        5553 :     options_mgr = config_mgr_new(&options_format);
     897        5553 :     int rv = subsystems_register_options_formats(options_mgr);
     898        5553 :     tor_assert(rv == 0);
     899        5553 :     config_mgr_freeze(options_mgr);
     900             :   }
     901       32238 :   return options_mgr;
     902             : }
     903             : 
     904             : #define CHECK_OPTIONS_MAGIC(opt) STMT_BEGIN                      \
     905             :     config_check_toplevel_magic(get_options_mgr(), (opt));       \
     906             :   STMT_END
     907             : 
     908             : /** Returns the currently configured options. */
     909      272675 : MOCK_IMPL(or_options_t *,
     910             : get_options_mutable, (void))
     911             : {
     912      272675 :   tor_assert(global_options);
     913      272675 :   tor_assert_nonfatal(! in_option_validation);
     914      272675 :   return global_options;
     915             : }
     916             : 
     917             : /** Returns the currently configured options */
     918      271777 : MOCK_IMPL(const or_options_t *,
     919             : get_options,(void))
     920             : {
     921      271777 :   return get_options_mutable();
     922             : }
     923             : 
     924             : /**
     925             :  * True iff we have noticed that this is a testing tor network, and we
     926             :  * should use the corresponding defaults.
     927             :  **/
     928             : static bool testing_network_configured = false;
     929             : 
     930             : /** Return a set of lines for any default options that we want to override
     931             :  * from those set in our config_var_t values. */
     932             : static config_line_t *
     933         956 : get_options_defaults(void)
     934             : {
     935         956 :   int i;
     936         956 :   config_line_t *result = NULL, **next = &result;
     937             : 
     938         956 :   if (testing_network_configured) {
     939           0 :     for (i = 0; testing_tor_network_defaults[i].k; ++i) {
     940           0 :       config_line_append(next,
     941             :                          testing_tor_network_defaults[i].k,
     942           0 :                          testing_tor_network_defaults[i].v);
     943           0 :       next = &(*next)->next;
     944             :     }
     945             :   }
     946             : 
     947         956 :   return result;
     948             : }
     949             : 
     950             : /** Change the current global options to contain <b>new_val</b> instead of
     951             :  * their current value; take action based on the new value; free the old value
     952             :  * as necessary.  Returns 0 on success, -1 on failure.
     953             :  */
     954             : int
     955         216 : set_options(or_options_t *new_val, char **msg)
     956             : {
     957         216 :   or_options_t *old_options = global_options;
     958         216 :   global_options = new_val;
     959             :   /* Note that we pass the *old* options below, for comparison. It
     960             :    * pulls the new options directly out of global_options. */
     961         216 :   if (options_act_reversible(old_options, msg)<0) {
     962           0 :     tor_assert(*msg);
     963           0 :     global_options = old_options;
     964           0 :     return -1;
     965             :   }
     966         431 :   if (subsystems_set_options(get_options_mgr(), new_val) < 0 ||
     967         215 :       options_act(old_options) < 0) { /* acting on the options failed. die. */
     968           1 :     if (! tor_event_loop_shutdown_is_pending()) {
     969           1 :       log_err(LD_BUG,
     970             :               "Acting on config options left us in a broken state. Dying.");
     971           1 :       tor_shutdown_event_loop_and_exit(1);
     972             :     }
     973           1 :     global_options = old_options;
     974           1 :     return -1;
     975             :   }
     976             :   /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
     977             :    * just starting up then the old_options will be undefined. */
     978         215 :   if (old_options && old_options != global_options) {
     979           5 :     config_line_t *changes =
     980           5 :       config_get_changes(get_options_mgr(), old_options, new_val);
     981           5 :     control_event_conf_changed(changes);
     982           5 :     config_free_lines(changes);
     983             :   }
     984             : 
     985         215 :   if (old_options != global_options) {
     986         215 :     or_options_free(old_options);
     987             :     /* If we are here it means we've successfully applied the new options and
     988             :      * that the global options have been changed to the new values. We'll
     989             :      * check if we need to remove or add periodic events. */
     990         215 :     periodic_events_on_new_options(global_options);
     991             :   }
     992             : 
     993             :   return 0;
     994             : }
     995             : 
     996             : /** Release additional memory allocated in options
     997             :  */
     998             : static void
     999        6591 : options_clear_cb(const config_mgr_t *mgr, void *opts)
    1000             : {
    1001        6591 :   (void)mgr;
    1002        6591 :   CHECK_OPTIONS_MAGIC(opts);
    1003        6591 :   or_options_t *options = opts;
    1004             : 
    1005        6591 :   routerset_free(options->ExcludeExitNodesUnion_);
    1006        6591 :   if (options->NodeFamilySets) {
    1007          12 :     SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *,
    1008             :                       rs, routerset_free(rs));
    1009           6 :     smartlist_free(options->NodeFamilySets);
    1010             :   }
    1011        6591 :   if (options->SchedulerTypes_) {
    1012        1528 :     SMARTLIST_FOREACH(options->SchedulerTypes_, int *, i, tor_free(i));
    1013         382 :     smartlist_free(options->SchedulerTypes_);
    1014             :   }
    1015        6591 :   if (options->FilesOpenedByIncludes) {
    1016         244 :     SMARTLIST_FOREACH(options->FilesOpenedByIncludes, char *, f, tor_free(f));
    1017         228 :     smartlist_free(options->FilesOpenedByIncludes);
    1018             :   }
    1019        6591 :   tor_free(options->DataDirectory);
    1020        6591 :   tor_free(options->CacheDirectory);
    1021        6591 :   tor_free(options->KeyDirectory);
    1022        6591 :   tor_free(options->BridgePassword_AuthDigest_);
    1023        6591 :   tor_free(options->command_arg);
    1024        6591 :   tor_free(options->master_key_fname);
    1025        6591 :   config_free_lines(options->MyFamily);
    1026        6591 : }
    1027             : 
    1028             : /** Release all memory allocated in options
    1029             :  */
    1030             : STATIC void
    1031        7309 : or_options_free_(or_options_t *options)
    1032             : {
    1033        7309 :   config_free(get_options_mgr(), options);
    1034        7309 : }
    1035             : 
    1036             : /** Release all memory and resources held by global configuration structures.
    1037             :  */
    1038             : void
    1039         241 : config_free_all(void)
    1040             : {
    1041         241 :   or_options_free(global_options);
    1042         241 :   global_options = NULL;
    1043         241 :   or_options_free(global_default_options);
    1044         241 :   global_default_options = NULL;
    1045             : 
    1046         241 :   parsed_cmdline_free(global_cmdline);
    1047             : 
    1048         241 :   if (configured_ports) {
    1049          32 :     SMARTLIST_FOREACH(configured_ports,
    1050             :                       port_cfg_t *, p, port_cfg_free(p));
    1051          10 :     smartlist_free(configured_ports);
    1052          10 :     configured_ports = NULL;
    1053             :   }
    1054             : 
    1055         241 :   tor_free(torrc_fname);
    1056         241 :   tor_free(torrc_defaults_fname);
    1057             : 
    1058         241 :   cleanup_protocol_warning_severity_level();
    1059             : 
    1060         241 :   have_set_startup_options = false;
    1061             : 
    1062         241 :   config_mgr_free(options_mgr);
    1063         241 : }
    1064             : 
    1065             : /** Make <b>address</b> -- a piece of information related to our operation as
    1066             :  * a client -- safe to log according to the settings in options->SafeLogging,
    1067             :  * and return it.
    1068             :  *
    1069             :  * (We return "[scrubbed]" if SafeLogging is "1", and address otherwise.)
    1070             :  */
    1071             : const char *
    1072        1488 : safe_str_client_opts(const or_options_t *options, const char *address)
    1073             : {
    1074        1488 :   tor_assert(address);
    1075        1488 :   if (!options) {
    1076        1488 :     options = get_options();
    1077             :   }
    1078             : 
    1079        1488 :   if (options->SafeLogging_ == SAFELOG_SCRUB_ALL)
    1080             :     return "[scrubbed]";
    1081             :   else
    1082           0 :     return address;
    1083             : }
    1084             : 
    1085             : /** Make <b>address</b> -- a piece of information of unspecified sensitivity
    1086             :  * -- safe to log according to the settings in options->SafeLogging, and
    1087             :  * return it.
    1088             :  *
    1089             :  * (We return "[scrubbed]" if SafeLogging is anything besides "0", and address
    1090             :  * otherwise.)
    1091             :  */
    1092             : const char *
    1093          54 : safe_str_opts(const or_options_t *options, const char *address)
    1094             : {
    1095          54 :   tor_assert(address);
    1096          54 :   if (!options) {
    1097          54 :     options = get_options();
    1098             :   }
    1099             : 
    1100          54 :   if (options->SafeLogging_ != SAFELOG_SCRUB_NONE)
    1101             :     return "[scrubbed]";
    1102             :   else
    1103          16 :     return address;
    1104             : }
    1105             : 
    1106             : /** Equivalent to escaped(safe_str_client(address)).  See reentrancy note on
    1107             :  * escaped(): don't use this outside the main thread, or twice in the same
    1108             :  * log statement. */
    1109             : const char *
    1110         255 : escaped_safe_str_client(const char *address)
    1111             : {
    1112         255 :   if (get_options()->SafeLogging_ == SAFELOG_SCRUB_ALL)
    1113             :     return "[scrubbed]";
    1114             :   else
    1115           0 :     return escaped(address);
    1116             : }
    1117             : 
    1118             : /** Equivalent to escaped(safe_str(address)).  See reentrancy note on
    1119             :  * escaped(): don't use this outside the main thread, or twice in the same
    1120             :  * log statement. */
    1121             : const char *
    1122          14 : escaped_safe_str(const char *address)
    1123             : {
    1124          14 :   if (get_options()->SafeLogging_ != SAFELOG_SCRUB_NONE)
    1125             :     return "[scrubbed]";
    1126             :   else
    1127           0 :     return escaped(address);
    1128             : }
    1129             : 
    1130             : /**
    1131             :  * The severity level that should be used for warnings of severity
    1132             :  * LOG_PROTOCOL_WARN.
    1133             :  *
    1134             :  * We keep this outside the options, and we use an atomic_counter_t, in case
    1135             :  * one thread needs to use LOG_PROTOCOL_WARN while an option transition is
    1136             :  * happening in the main thread.
    1137             :  */
    1138             : static atomic_counter_t protocol_warning_severity_level;
    1139             : 
    1140             : /** Return the severity level that should be used for warnings of severity
    1141             :  * LOG_PROTOCOL_WARN. */
    1142             : int
    1143         423 : get_protocol_warning_severity_level(void)
    1144             : {
    1145         423 :   return (int) atomic_counter_get(&protocol_warning_severity_level);
    1146             : }
    1147             : 
    1148             : /** Set the protocol warning severity level to <b>severity</b>. */
    1149             : static void
    1150        5766 : set_protocol_warning_severity_level(int warning_severity)
    1151             : {
    1152        5766 :   atomic_counter_exchange(&protocol_warning_severity_level,
    1153             :                           warning_severity);
    1154        5766 : }
    1155             : 
    1156             : /**
    1157             :  * Initialize the log warning severity level for protocol warnings. Call
    1158             :  * only once at startup.
    1159             :  */
    1160             : void
    1161        5553 : init_protocol_warning_severity_level(void)
    1162             : {
    1163        5553 :   atomic_counter_init(&protocol_warning_severity_level);
    1164        5553 :   set_protocol_warning_severity_level(LOG_WARN);
    1165        5553 : }
    1166             : 
    1167             : /**
    1168             :  * Tear down protocol_warning_severity_level.
    1169             :  */
    1170             : static void
    1171             : cleanup_protocol_warning_severity_level(void)
    1172             : {
    1173             :   /* Destroying a locked mutex is undefined behaviour. This mutex may be
    1174             :    * locked, because multiple threads can access it. But we need to destroy
    1175             :    * it, otherwise re-initialisation will trigger undefined behaviour.
    1176             :    * See #31735 for details. */
    1177             :   atomic_counter_destroy(&protocol_warning_severity_level);
    1178             : }
    1179             : 
    1180             : /** Add the default directory authorities directly into the trusted dir list,
    1181             :  * but only add them insofar as they share bits with <b>type</b>.
    1182             :  * Each authority's bits are restricted to the bits shared with <b>type</b>.
    1183             :  * If <b>type</b> is ALL_DIRINFO or NO_DIRINFO (zero), add all authorities. */
    1184             : STATIC void
    1185         224 : add_default_trusted_dir_authorities(dirinfo_type_t type)
    1186             : {
    1187         224 :   int i;
    1188        2464 :   for (i=0; default_authorities[i]; i++) {
    1189        2240 :     if (parse_dir_authority_line(default_authorities[i], type, 0)<0) {
    1190           0 :       log_err(LD_BUG, "Couldn't parse internal DirAuthority line %s",
    1191             :               default_authorities[i]);
    1192             :     }
    1193             :   }
    1194         224 : }
    1195             : 
    1196             : /** Add the default fallback directory servers into the fallback directory
    1197             :  * server list. */
    1198         211 : MOCK_IMPL(void,
    1199             : add_default_fallback_dir_servers,(void))
    1200             : {
    1201         211 :   int i;
    1202       42411 :   for (i=0; default_fallbacks[i]; i++) {
    1203       42200 :     if (parse_dir_fallback_line(default_fallbacks[i], 0)<0) {
    1204           0 :       log_err(LD_BUG, "Couldn't parse internal FallbackDir line %s",
    1205             :               default_fallbacks[i]);
    1206             :     }
    1207             :   }
    1208         211 : }
    1209             : 
    1210             : /** Look at all the config options for using alternate directory
    1211             :  * authorities, and make sure none of them are broken. Also, warn the
    1212             :  * user if we changed any dangerous ones.
    1213             :  */
    1214             : static int
    1215         452 : validate_dir_servers(const or_options_t *options,
    1216             :                      const or_options_t *old_options)
    1217             : {
    1218         452 :   config_line_t *cl;
    1219             : 
    1220         452 :   if (options->DirAuthorities &&
    1221          50 :       (options->AlternateDirAuthority || options->AlternateBridgeAuthority)) {
    1222           1 :     log_warn(LD_CONFIG,
    1223             :              "You cannot set both DirAuthority and Alternate*Authority.");
    1224           1 :     return -1;
    1225             :   }
    1226             : 
    1227             :   /* do we want to complain to the user about being partitionable? */
    1228         451 :   if ((options->DirAuthorities &&
    1229           0 :        (!old_options ||
    1230           0 :         !config_lines_eq(options->DirAuthorities,
    1231           0 :                          old_options->DirAuthorities))) ||
    1232         402 :       (options->AlternateDirAuthority &&
    1233           0 :        (!old_options ||
    1234           0 :         !config_lines_eq(options->AlternateDirAuthority,
    1235           0 :                          old_options->AlternateDirAuthority)))) {
    1236          51 :     log_warn(LD_CONFIG,
    1237             :              "You have used DirAuthority or AlternateDirAuthority to "
    1238             :              "specify alternate directory authorities in "
    1239             :              "your configuration. This is potentially dangerous: it can "
    1240             :              "make you look different from all other Tor users, and hurt "
    1241             :              "your anonymity. Even if you've specified the same "
    1242             :              "authorities as Tor uses by default, the defaults could "
    1243             :              "change in the future. Be sure you know what you're doing.");
    1244             :   }
    1245             : 
    1246             :   /* Now go through the four ways you can configure an alternate
    1247             :    * set of directory authorities, and make sure none are broken. */
    1248         500 :   for (cl = options->DirAuthorities; cl; cl = cl->next)
    1249          49 :     if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0)
    1250             :       return -1;
    1251         453 :   for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
    1252           2 :     if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0)
    1253             :       return -1;
    1254         453 :   for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
    1255           2 :     if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0)
    1256             :       return -1;
    1257         451 :   for (cl = options->FallbackDir; cl; cl = cl->next)
    1258           0 :     if (parse_dir_fallback_line(cl->value, 1)<0)
    1259             :       return -1;
    1260             :   return 0;
    1261             : }
    1262             : 
    1263             : /** Look at all the config options and assign new dir authorities
    1264             :  * as appropriate.
    1265             :  */
    1266             : int
    1267         227 : consider_adding_dir_servers(const or_options_t *options,
    1268             :                             const or_options_t *old_options)
    1269             : {
    1270         227 :   config_line_t *cl;
    1271         679 :   int need_to_update =
    1272         227 :     !smartlist_len(router_get_trusted_dir_servers()) ||
    1273           5 :     !smartlist_len(router_get_fallback_dir_servers()) || !old_options ||
    1274           4 :     !config_lines_eq(options->DirAuthorities, old_options->DirAuthorities) ||
    1275           2 :     !config_lines_eq(options->FallbackDir, old_options->FallbackDir) ||
    1276           4 :     (options->UseDefaultFallbackDirs != old_options->UseDefaultFallbackDirs) ||
    1277           2 :     !config_lines_eq(options->AlternateBridgeAuthority,
    1278         231 :                      old_options->AlternateBridgeAuthority) ||
    1279           2 :     !config_lines_eq(options->AlternateDirAuthority,
    1280           2 :                      old_options->AlternateDirAuthority);
    1281             : 
    1282         225 :   if (!need_to_update)
    1283             :     return 0; /* all done */
    1284             : 
    1285             :   /* "You cannot set both DirAuthority and Alternate*Authority."
    1286             :    * Checking that this restriction holds allows us to simplify
    1287             :    * the unit tests. */
    1288         225 :   tor_assert(!(options->DirAuthorities &&
    1289             :                (options->AlternateDirAuthority
    1290             :                 || options->AlternateBridgeAuthority)));
    1291             : 
    1292             :   /* Start from a clean slate. */
    1293         225 :   clear_dir_servers();
    1294             : 
    1295         225 :   if (!options->DirAuthorities) {
    1296             :     /* then we may want some of the defaults */
    1297         223 :     dirinfo_type_t type = NO_DIRINFO;
    1298         223 :     if (!options->AlternateBridgeAuthority) {
    1299         219 :       type |= BRIDGE_DIRINFO;
    1300             :     }
    1301         223 :     if (!options->AlternateDirAuthority) {
    1302         219 :       type |= V3_DIRINFO | EXTRAINFO_DIRINFO | MICRODESC_DIRINFO;
    1303             :       /* Only add the default fallback directories when the DirAuthorities,
    1304             :        * AlternateDirAuthority, and FallbackDir directory config options
    1305             :        * are set to their defaults, and when UseDefaultFallbackDirs is 1. */
    1306         219 :       if (!options->FallbackDir && options->UseDefaultFallbackDirs) {
    1307         213 :         add_default_fallback_dir_servers();
    1308             :       }
    1309             :     }
    1310             :     /* if type == NO_DIRINFO, we don't want to add any of the
    1311             :      * default authorities, because we've replaced them all */
    1312         223 :     if (type != NO_DIRINFO)
    1313         221 :       add_default_trusted_dir_authorities(type);
    1314             :   }
    1315             : 
    1316         227 :   for (cl = options->DirAuthorities; cl; cl = cl->next)
    1317           2 :     if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0)
    1318             :       return -1;
    1319         229 :   for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
    1320           4 :     if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0)
    1321             :       return -1;
    1322         229 :   for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
    1323           4 :     if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0)
    1324             :       return -1;
    1325         230 :   for (cl = options->FallbackDir; cl; cl = cl->next)
    1326           5 :     if (parse_dir_fallback_line(cl->value, 0)<0)
    1327             :       return -1;
    1328             :   return 0;
    1329             : }
    1330             : 
    1331             : /**
    1332             :  * Make sure that <b>directory</b> exists, with appropriate ownership and
    1333             :  * permissions (as modified by <b>group_readable</b>). If <b>create</b>,
    1334             :  * create the directory if it is missing. Return 0 on success.
    1335             :  * On failure, return -1 and set *<b>msg_out</b>.
    1336             :  */
    1337             : static int
    1338         657 : check_and_create_data_directory(int create,
    1339             :                                 const char *directory,
    1340             :                                 int group_readable,
    1341             :                                 const char *owner,
    1342             :                                 char **msg_out)
    1343             : {
    1344         657 :   cpd_check_t cpd_opts = create ? CPD_CREATE : CPD_CHECK;
    1345         657 :   if (group_readable)
    1346           6 :       cpd_opts |= CPD_GROUP_READ;
    1347         657 :   if (check_private_dir(directory,
    1348             :                         cpd_opts,
    1349             :                         owner) < 0) {
    1350           3 :     tor_asprintf(msg_out,
    1351             :                  "Couldn't %s private data directory \"%s\"",
    1352             :                  create ? "create" : "access",
    1353             :                  directory);
    1354           3 :     return -1;
    1355             :   }
    1356             : 
    1357             : #ifndef _WIN32
    1358         654 :   if (group_readable) {
    1359             :     /* Only new dirs created get new opts, also enforce group read. */
    1360           6 :     if (chmod(directory, 0750)) {
    1361           0 :       log_warn(LD_FS,"Unable to make %s group-readable: %s",
    1362             :                directory, strerror(errno));
    1363             :     }
    1364             :   }
    1365             : #endif /* !defined(_WIN32) */
    1366             : 
    1367             :   return 0;
    1368             : }
    1369             : 
    1370             : /**
    1371             :  * Ensure that our keys directory exists, with appropriate permissions.
    1372             :  * Return 0 on success, -1 on failure.
    1373             :  */
    1374             : int
    1375          70 : create_keys_directory(const or_options_t *options)
    1376             : {
    1377             :   /* Make sure DataDirectory exists, and is private. */
    1378          70 :   cpd_check_t cpd_opts = CPD_CREATE;
    1379          70 :   if (options->DataDirectoryGroupReadable)
    1380           0 :     cpd_opts |= CPD_GROUP_READ;
    1381          70 :   if (check_private_dir(options->DataDirectory, cpd_opts, options->User)) {
    1382           0 :     log_err(LD_OR, "Can't create/check datadirectory %s",
    1383             :             options->DataDirectory);
    1384           0 :     return -1;
    1385             :   }
    1386             : 
    1387             :   /* Check the key directory. */
    1388          70 :   if (check_private_dir(options->KeyDirectory, CPD_CREATE, options->User)) {
    1389           0 :     return -1;
    1390             :   }
    1391             :   return 0;
    1392             : }
    1393             : 
    1394             : /* Helps determine flags to pass to switch_id. */
    1395             : static int have_low_ports = -1;
    1396             : 
    1397             : /** Take case of initial startup tasks that must occur before any of the
    1398             :  * transactional option-related changes are allowed. */
    1399             : static int
    1400         214 : options_act_once_on_startup(char **msg_out)
    1401             : {
    1402         214 :   if (have_set_startup_options)
    1403             :     return 0;
    1404             : 
    1405         214 :   const or_options_t *options = get_options();
    1406         214 :   const bool running_tor = options->command == CMD_RUN_TOR;
    1407             : 
    1408         214 :   if (!running_tor)
    1409             :     return 0;
    1410             : 
    1411             :   /* Daemonize _first_, since we only want to open most of this stuff in
    1412             :    * the subprocess.  Libevent bases can't be reliably inherited across
    1413             :    * processes. */
    1414           4 :   if (options->RunAsDaemon) {
    1415           0 :     if (! start_daemon_has_been_called())
    1416           0 :       subsystems_prefork();
    1417             :     /* No need to roll back, since you can't change the value. */
    1418           0 :     if (start_daemon())
    1419           0 :       subsystems_postfork();
    1420             :   }
    1421             : 
    1422             : #ifdef HAVE_SYSTEMD
    1423             :   /* Our PID may have changed, inform supervisor */
    1424           4 :   sd_notifyf(0, "MAINPID=%ld\n", (long int)getpid());
    1425             : #endif
    1426             : 
    1427             :   /* Set up libevent.  (We need to do this before we can register the
    1428             :    * listeners as listeners.) */
    1429           4 :   init_libevent(options);
    1430             : 
    1431             :   /* This has to come up after libevent is initialized. */
    1432           4 :   control_initialize_event_queue();
    1433             : 
    1434             :   /*
    1435             :    * Initialize the scheduler - this has to come after
    1436             :    * options_init_from_torrc() sets up libevent - why yes, that seems
    1437             :    * completely sensible to hide the libevent setup in the option parsing
    1438             :    * code!  It also needs to happen before init_keys(), so it needs to
    1439             :    * happen here too.  How yucky. */
    1440           4 :   scheduler_init();
    1441             : 
    1442             :   /* Attempt to lock all current and future memory with mlockall() only once.
    1443             :    * This must happen before setuid. */
    1444           4 :   if (options->DisableAllSwap) {
    1445           0 :     if (tor_mlockall() == -1) {
    1446           0 :       *msg_out = tor_strdup("DisableAllSwap failure. Do you have proper "
    1447             :                         "permissions?");
    1448           0 :       return -1;
    1449             :     }
    1450             :   }
    1451             : 
    1452           4 :   have_set_startup_options = true;
    1453           4 :   return 0;
    1454             : }
    1455             : 
    1456             : /**
    1457             :  * Change our user ID if we're configured to do so.
    1458             :  **/
    1459             : static int
    1460         214 : options_switch_id(char **msg_out)
    1461             : {
    1462         214 :   const or_options_t *options = get_options();
    1463             : 
    1464             :   /* Setuid/setgid as appropriate */
    1465         214 :   if (options->User) {
    1466           0 :     tor_assert(have_low_ports != -1);
    1467           0 :     unsigned switch_id_flags = 0;
    1468           0 :     if (options->KeepBindCapabilities == 1) {
    1469           0 :       switch_id_flags |= SWITCH_ID_KEEP_BINDLOW;
    1470           0 :       switch_id_flags |= SWITCH_ID_WARN_IF_NO_CAPS;
    1471             :     }
    1472           0 :     if (options->KeepBindCapabilities == -1 && have_low_ports) {
    1473           0 :       switch_id_flags |= SWITCH_ID_KEEP_BINDLOW;
    1474             :     }
    1475           0 :     if (switch_id(options->User, switch_id_flags) != 0) {
    1476             :       /* No need to roll back, since you can't change the value. */
    1477           0 :       *msg_out = tor_strdup("Problem with User value. See logs for details.");
    1478           0 :       return -1;
    1479             :     }
    1480             :   }
    1481             : 
    1482             :   return 0;
    1483             : }
    1484             : 
    1485             : /**
    1486             :  * Helper. Given a data directory (<b>datadir</b>) and another directory
    1487             :  * (<b>subdir</b>) with respective group-writable permissions
    1488             :  * <b>datadir_gr</b> and <b>subdir_gr</b>, compute whether the subdir should
    1489             :  * be group-writeable.
    1490             :  **/
    1491             : static int
    1492         437 : compute_group_readable_flag(const char *datadir,
    1493             :                             const char *subdir,
    1494             :                             int datadir_gr,
    1495             :                             int subdir_gr)
    1496             : {
    1497         437 :   if (subdir_gr != -1) {
    1498             :     /* The user specified a default for "subdir", so we always obey it. */
    1499             :     return subdir_gr;
    1500             :   }
    1501             : 
    1502             :   /* The user left the subdir_gr option on "auto." */
    1503         431 :   if (0 == strcmp(subdir, datadir)) {
    1504             :     /* The directories are the same, so we use the group-readable flag from
    1505             :      * the datadirectory */
    1506             :     return datadir_gr;
    1507             :   } else {
    1508             :     /* The directories are different, so we default to "not group-readable" */
    1509         217 :     return 0;
    1510             :   }
    1511             : }
    1512             : 
    1513             : /**
    1514             :  * Create our DataDirectory, CacheDirectory, and KeyDirectory, and
    1515             :  * set their permissions correctly.
    1516             :  */
    1517             : STATIC int
    1518         220 : options_create_directories(char **msg_out)
    1519             : {
    1520         220 :   const or_options_t *options = get_options();
    1521         220 :   const bool running_tor = options->command == CMD_RUN_TOR;
    1522             : 
    1523             :   /* Ensure data directory is private; create if possible. */
    1524             :   /* It's okay to do this in "options_act_reversible()" even though it isn't
    1525             :    * actually reversible, since you can't change the DataDirectory while
    1526             :    * Tor is running. */
    1527         220 :   if (check_and_create_data_directory(running_tor /* create */,
    1528         220 :                                       options->DataDirectory,
    1529         220 :                                       options->DataDirectoryGroupReadable,
    1530         220 :                                       options->User,
    1531             :                                       msg_out) < 0) {
    1532             :     return -1;
    1533             :   }
    1534             : 
    1535             :   /* We need to handle the group-readable flag for the cache directory and key
    1536             :    * directory specially, since they may be the same as the data directory */
    1537         219 :   const int key_dir_group_readable = compute_group_readable_flag(
    1538         219 :                                         options->DataDirectory,
    1539         219 :                                         options->KeyDirectory,
    1540         219 :                                         options->DataDirectoryGroupReadable,
    1541         219 :                                         options->KeyDirectoryGroupReadable);
    1542             : 
    1543         219 :   if (check_and_create_data_directory(running_tor /* create */,
    1544             :                                       options->KeyDirectory,
    1545             :                                       key_dir_group_readable,
    1546         219 :                                       options->User,
    1547             :                                       msg_out) < 0) {
    1548             :     return -1;
    1549             :   }
    1550             : 
    1551         218 :   const int cache_dir_group_readable = compute_group_readable_flag(
    1552         218 :                                         options->DataDirectory,
    1553         218 :                                         options->CacheDirectory,
    1554         218 :                                         options->DataDirectoryGroupReadable,
    1555         218 :                                         options->CacheDirectoryGroupReadable);
    1556             : 
    1557         218 :   if (check_and_create_data_directory(running_tor /* create */,
    1558             :                                       options->CacheDirectory,
    1559             :                                       cache_dir_group_readable,
    1560         218 :                                       options->User,
    1561             :                                       msg_out) < 0) {
    1562           1 :     return -1;
    1563             :   }
    1564             : 
    1565             :   return 0;
    1566             : }
    1567             : 
    1568             : /** Structure to represent an incomplete configuration of a set of
    1569             :  * listeners.
    1570             :  *
    1571             :  * This structure is generated by options_start_listener_transaction(), and is
    1572             :  * either committed by options_commit_listener_transaction() or rolled back by
    1573             :  * options_rollback_listener_transaction(). */
    1574             : typedef struct listener_transaction_t {
    1575             :   bool set_conn_limit; /**< True if we've set the connection limit */
    1576             :   unsigned old_conn_limit; /**< If nonzero, previous connlimit value. */
    1577             :   smartlist_t *new_listeners; /**< List of new listeners that we opened. */
    1578             : } listener_transaction_t;
    1579             : 
    1580             : /**
    1581             :  * Start configuring our listeners based on the current value of
    1582             :  * get_options().
    1583             :  *
    1584             :  * The value <b>old_options</b> holds either the previous options object,
    1585             :  * or NULL if we're starting for the first time.
    1586             :  *
    1587             :  * On success, return a listener_transaction_t that we can either roll back or
    1588             :  * commit.
    1589             :  *
    1590             :  * On failure return NULL and write a message into a newly allocated string in
    1591             :  * *<b>msg_out</b>.
    1592             :  **/
    1593             : static listener_transaction_t *
    1594         214 : options_start_listener_transaction(const or_options_t *old_options,
    1595             :                                    char **msg_out)
    1596             : {
    1597         214 :   listener_transaction_t *xn = tor_malloc_zero(sizeof(listener_transaction_t));
    1598         214 :   xn->new_listeners = smartlist_new();
    1599         214 :   or_options_t *options = get_options_mutable();
    1600         214 :   const bool running_tor = options->command == CMD_RUN_TOR;
    1601             : 
    1602         214 :   if (! running_tor) {
    1603             :     return xn;
    1604             :   }
    1605             : 
    1606           4 :   int n_ports=0;
    1607             :   /* We need to set the connection limit before we can open the listeners. */
    1608           4 :   if (! sandbox_is_active()) {
    1609           4 :     if (set_max_file_descriptors((unsigned)options->ConnLimit,
    1610             :                                  &options->ConnLimit_) < 0) {
    1611           0 :       *msg_out = tor_strdup("Problem with ConnLimit value. "
    1612             :                             "See logs for details.");
    1613           0 :       goto rollback;
    1614             :     }
    1615           4 :     xn->set_conn_limit = true;
    1616           4 :     if (old_options)
    1617           0 :       xn->old_conn_limit = (unsigned)old_options->ConnLimit;
    1618             :   } else {
    1619           0 :     tor_assert(old_options);
    1620           0 :     options->ConnLimit_ = old_options->ConnLimit_;
    1621             :   }
    1622             : 
    1623             :   /* Adjust the port configuration so we can launch listeners. */
    1624             :   /* 31851: some ports are relay-only */
    1625           4 :   if (parse_ports(options, 0, msg_out, &n_ports, NULL)) {
    1626           0 :     if (!*msg_out)
    1627           0 :       *msg_out = tor_strdup("Unexpected problem parsing port config");
    1628           0 :     goto rollback;
    1629             :   }
    1630             : 
    1631             :   /* Set the hibernation state appropriately.*/
    1632           4 :   consider_hibernation(time(NULL));
    1633             : 
    1634             :   /* Launch the listeners.  (We do this before we setuid, so we can bind to
    1635             :    * ports under 1024.)  We don't want to rebind if we're hibernating or
    1636             :    * shutting down. If networking is disabled, this will close all but the
    1637             :    * control listeners, but disable those. */
    1638             :   /* 31851: some listeners are relay-only */
    1639           4 :   if (!we_are_hibernating()) {
    1640           4 :     if (retry_all_listeners(xn->new_listeners,
    1641             :                             options->DisableNetwork) < 0) {
    1642           0 :       *msg_out = tor_strdup("Failed to bind one of the listener ports.");
    1643           0 :       goto rollback;
    1644             :     }
    1645             :   }
    1646           4 :   if (options->DisableNetwork) {
    1647             :     /* Aggressively close non-controller stuff, NOW */
    1648           4 :     log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept "
    1649             :                "non-control network connections. Shutting down all existing "
    1650             :                "connections.");
    1651           4 :     connection_mark_all_noncontrol_connections();
    1652             :     /* We can't complete circuits until the network is re-enabled. */
    1653           4 :     note_that_we_maybe_cant_complete_circuits();
    1654             :   }
    1655             : 
    1656             : #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
    1657             :   /* Open /dev/pf before (possibly) dropping privileges. */
    1658             :   if (options->TransPort_set &&
    1659             :       options->TransProxyType_parsed == TPT_DEFAULT) {
    1660             :     if (get_pf_socket() < 0) {
    1661             :       *msg_out = tor_strdup("Unable to open /dev/pf for transparent proxy.");
    1662             :       goto rollback;
    1663             :     }
    1664             :   }
    1665             : #endif /* defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) */
    1666             : 
    1667             :   return xn;
    1668             : 
    1669           0 :  rollback:
    1670           0 :   options_rollback_listener_transaction(xn);
    1671           0 :   return NULL;
    1672             : }
    1673             : 
    1674             : /**
    1675             :  * Finish configuring the listeners that started to get configured with
    1676             :  * <b>xn</b>.  Frees <b>xn</b>.
    1677             :  **/
    1678             : static void
    1679         214 : options_commit_listener_transaction(listener_transaction_t *xn)
    1680             : {
    1681         214 :   tor_assert(xn);
    1682         214 :   if (xn->set_conn_limit) {
    1683           4 :     or_options_t *options = get_options_mutable();
    1684             :     /*
    1685             :      * If we adjusted the conn limit, recompute the OOS threshold too
    1686             :      *
    1687             :      * How many possible sockets to keep in reserve?  If we have lots of
    1688             :      * possible sockets, keep this below a limit and set ConnLimit_high_thresh
    1689             :      * very close to ConnLimit_, but if ConnLimit_ is low, shrink it in
    1690             :      * proportion.
    1691             :      *
    1692             :      * Somewhat arbitrarily, set socks_in_reserve to 5% of ConnLimit_, but
    1693             :      * cap it at 64.
    1694             :      */
    1695           4 :     int socks_in_reserve = options->ConnLimit_ / 20;
    1696           4 :     if (socks_in_reserve > 64) socks_in_reserve = 64;
    1697             : 
    1698           4 :     options->ConnLimit_high_thresh = options->ConnLimit_ - socks_in_reserve;
    1699           4 :     options->ConnLimit_low_thresh = (options->ConnLimit_ / 4) * 3;
    1700           4 :     log_info(LD_GENERAL,
    1701             :              "Recomputed OOS thresholds: ConnLimit %d, ConnLimit_ %d, "
    1702             :              "ConnLimit_high_thresh %d, ConnLimit_low_thresh %d",
    1703             :              options->ConnLimit, options->ConnLimit_,
    1704             :              options->ConnLimit_high_thresh,
    1705             :              options->ConnLimit_low_thresh);
    1706             : 
    1707             :     /* Give the OOS handler a chance with the new thresholds */
    1708           4 :     connection_check_oos(get_n_open_sockets(), 0);
    1709             :   }
    1710             : 
    1711         214 :   smartlist_free(xn->new_listeners);
    1712         214 :   tor_free(xn);
    1713         214 : }
    1714             : 
    1715             : /**
    1716             :  * Revert the listener configuration changes that that started to get
    1717             :  * configured with <b>xn</b>.  Frees <b>xn</b>.
    1718             :  **/
    1719             : static void
    1720           0 : options_rollback_listener_transaction(listener_transaction_t *xn)
    1721             : {
    1722           0 :   if (! xn)
    1723             :     return;
    1724             : 
    1725           0 :   or_options_t *options = get_options_mutable();
    1726             : 
    1727           0 :   if (xn->set_conn_limit && xn->old_conn_limit)
    1728           0 :     set_max_file_descriptors(xn->old_conn_limit, &options->ConnLimit_);
    1729             : 
    1730           0 :   SMARTLIST_FOREACH(xn->new_listeners, connection_t *, conn,
    1731             :   {
    1732             :     log_notice(LD_NET, "Closing partially-constructed %s",
    1733             :                connection_describe(conn));
    1734             :     connection_close_immediate(conn);
    1735             :     connection_mark_for_close(conn);
    1736             :   });
    1737             : 
    1738           0 :   smartlist_free(xn->new_listeners);
    1739           0 :   tor_free(xn);
    1740             : }
    1741             : 
    1742             : /** Structure to represent an incomplete configuration of a set of logs.
    1743             :  *
    1744             :  * This structure is generated by options_start_log_transaction(), and is
    1745             :  * either committed by options_commit_log_transaction() or rolled back by
    1746             :  * options_rollback_log_transaction(). */
    1747             : typedef struct log_transaction_t {
    1748             :   /** Previous lowest severity of any configured log. */
    1749             :   int old_min_log_level;
    1750             :   /** True if we have marked the previous logs to be closed */
    1751             :   bool logs_marked;
    1752             :   /** True if we initialized the new set of logs */
    1753             :   bool logs_initialized;
    1754             :   /** True if our safelogging configuration is different from what it was
    1755             :    * previously (or if we are starting for the first time). */
    1756             :   bool safelogging_changed;
    1757             : } log_transaction_t;
    1758             : 
    1759             : /**
    1760             :  * Start configuring our logs based on the current value of get_options().
    1761             :  *
    1762             :  * The value <b>old_options</b> holds either the previous options object,
    1763             :  * or NULL if we're starting for the first time.
    1764             :  *
    1765             :  * On success, return a log_transaction_t that we can either roll back or
    1766             :  * commit.
    1767             :  *
    1768             :  * On failure return NULL and write a message into a newly allocated string in
    1769             :  * *<b>msg_out</b>.
    1770             :  **/
    1771             : STATIC log_transaction_t *
    1772         219 : options_start_log_transaction(const or_options_t *old_options,
    1773             :                               char **msg_out)
    1774             : {
    1775         219 :   const or_options_t *options = get_options();
    1776         219 :   const bool running_tor = options->command == CMD_RUN_TOR;
    1777             : 
    1778         219 :   log_transaction_t *xn = tor_malloc_zero(sizeof(log_transaction_t));
    1779         219 :   xn->old_min_log_level = get_min_log_level();
    1780         219 :   xn->safelogging_changed = !old_options ||
    1781           7 :     old_options->SafeLogging_ != options->SafeLogging_;
    1782             : 
    1783         219 :   if (! running_tor)
    1784         210 :     goto done;
    1785             : 
    1786           9 :   mark_logs_temp(); /* Close current logs once new logs are open. */
    1787           9 :   xn->logs_marked = true;
    1788             :   /* Configure the tor_log(s) */
    1789           9 :   if (options_init_logs(old_options, options, 0)<0) {
    1790           1 :     *msg_out = tor_strdup("Failed to init Log options. See logs for details.");
    1791           1 :     options_rollback_log_transaction(xn);
    1792           1 :     xn = NULL;
    1793           1 :     goto done;
    1794             :   }
    1795             : 
    1796           8 :   xn->logs_initialized = true;
    1797             : 
    1798         219 :  done:
    1799         219 :   return xn;
    1800             : }
    1801             : 
    1802             : /**
    1803             :  * Finish configuring the logs that started to get configured with <b>xn</b>.
    1804             :  * Frees <b>xn</b>.
    1805             :  **/
    1806             : STATIC void
    1807         217 : options_commit_log_transaction(log_transaction_t *xn)
    1808             : {
    1809         217 :   const or_options_t *options = get_options();
    1810         217 :   tor_assert(xn);
    1811             : 
    1812         217 :   if (xn->logs_marked) {
    1813          14 :     log_severity_list_t *severity =
    1814           7 :       tor_malloc_zero(sizeof(log_severity_list_t));
    1815           7 :     close_temp_logs();
    1816           7 :     add_callback_log(severity, control_event_logmsg);
    1817           7 :     logs_set_pending_callback_callback(control_event_logmsg_pending);
    1818           7 :     control_adjust_event_log_severity();
    1819           7 :     tor_free(severity);
    1820           7 :     tor_log_update_sigsafe_err_fds();
    1821             :   }
    1822             : 
    1823         217 :   if (xn->logs_initialized) {
    1824           7 :     flush_log_messages_from_startup();
    1825             :   }
    1826             : 
    1827             :   {
    1828         217 :     const char *badness = NULL;
    1829         217 :     int bad_safelog = 0, bad_severity = 0, new_badness = 0;
    1830         217 :     if (options->SafeLogging_ != SAFELOG_SCRUB_ALL) {
    1831           4 :       bad_safelog = 1;
    1832           4 :       if (xn->safelogging_changed)
    1833           4 :         new_badness = 1;
    1834             :     }
    1835         217 :     if (get_min_log_level() >= LOG_INFO) {
    1836           2 :       bad_severity = 1;
    1837           2 :       if (get_min_log_level() != xn->old_min_log_level)
    1838           1 :         new_badness = 1;
    1839             :     }
    1840         217 :     if (bad_safelog && bad_severity)
    1841             :       badness = "you disabled SafeLogging, and "
    1842             :         "you're logging more than \"notice\"";
    1843         216 :     else if (bad_safelog)
    1844             :       badness = "you disabled SafeLogging";
    1845             :     else
    1846         213 :       badness = "you're logging more than \"notice\"";
    1847         217 :     if (new_badness)
    1848           5 :       log_warn(LD_GENERAL, "Your log may contain sensitive information - %s. "
    1849             :                "Don't log unless it serves an important reason. "
    1850             :                "Overwrite the log afterwards.", badness);
    1851             :   }
    1852             : 
    1853         217 :   tor_free(xn);
    1854         217 : }
    1855             : 
    1856             : /**
    1857             :  * Revert the log configuration changes that that started to get configured
    1858             :  * with <b>xn</b>.  Frees <b>xn</b>.
    1859             :  **/
    1860             : STATIC void
    1861           2 : options_rollback_log_transaction(log_transaction_t *xn)
    1862             : {
    1863           2 :   if (!xn)
    1864             :     return;
    1865             : 
    1866           2 :   if (xn->logs_marked) {
    1867           2 :     rollback_log_changes();
    1868           2 :     control_adjust_event_log_severity();
    1869             :   }
    1870             : 
    1871           2 :   tor_free(xn);
    1872             : }
    1873             : 
    1874             : /**
    1875             :  * Fetch the active option list, and take actions based on it. All of
    1876             :  * the things we do in this function should survive being done
    1877             :  * repeatedly, OR be done only once when starting Tor.  If present,
    1878             :  * <b>old_options</b> contains the previous value of the options.
    1879             :  *
    1880             :  * This function is only truly "reversible" _after_ the first time it
    1881             :  * is run.  The first time that it runs, it performs some irreversible
    1882             :  * tasks in the correct sequence between the reversible option changes.
    1883             :  *
    1884             :  * Option changes should only be marked as "reversible" if they cannot
    1885             :  * be validated before switching them, but they can be switched back if
    1886             :  * some other validation fails.
    1887             :  *
    1888             :  * Return 0 if all goes well, return -1 if things went badly.
    1889             :  */
    1890         214 : MOCK_IMPL(STATIC int,
    1891             : options_act_reversible,(const or_options_t *old_options, char **msg))
    1892             : {
    1893         214 :   const bool first_time = ! have_set_startup_options;
    1894         214 :   log_transaction_t *log_transaction = NULL;
    1895         214 :   listener_transaction_t *listener_transaction = NULL;
    1896         214 :   int r = -1;
    1897             : 
    1898             :   /* The ordering of actions in this function is not free, sadly.
    1899             :    *
    1900             :    * First of all, we _must_ daemonize before we take all kinds of
    1901             :    * initialization actions, since they need to happen in the
    1902             :    * subprocess.
    1903             :    */
    1904         214 :   if (options_act_once_on_startup(msg) < 0)
    1905           0 :     goto rollback;
    1906             : 
    1907             :   /* Once we've handled most of once-off initialization, we need to
    1908             :    * open our listeners before we switch IDs.  (If we open listeners first,
    1909             :    * we might not be able to bind to low ports.)
    1910             :    */
    1911         214 :   listener_transaction = options_start_listener_transaction(old_options, msg);
    1912         214 :   if (listener_transaction == NULL)
    1913           0 :     goto rollback;
    1914             : 
    1915         214 :   if (first_time) {
    1916         214 :     if (options_switch_id(msg) < 0)
    1917           0 :       goto rollback;
    1918             :   }
    1919             : 
    1920             :   /* On the other hand, we need to touch the file system _after_ we
    1921             :    * switch IDs: otherwise, we'll be making directories and opening files
    1922             :    * with the wrong permissions.
    1923             :    */
    1924         214 :   if (first_time) {
    1925         214 :     if (options_create_directories(msg) < 0)
    1926           0 :       goto rollback;
    1927             :   }
    1928             : 
    1929             :   /* Bail out at this point if we're not going to be a client or server:
    1930             :    * we don't run Tor itself. */
    1931         214 :   log_transaction = options_start_log_transaction(old_options, msg);
    1932         214 :   if (log_transaction == NULL)
    1933           0 :     goto rollback;
    1934             : 
    1935             :   // Commit!
    1936         214 :   r = 0;
    1937             : 
    1938         214 :   options_commit_log_transaction(log_transaction);
    1939             : 
    1940         214 :   options_commit_listener_transaction(listener_transaction);
    1941             : 
    1942         214 :   goto done;
    1943             : 
    1944           0 :  rollback:
    1945           0 :   r = -1;
    1946           0 :   tor_assert(*msg);
    1947             : 
    1948           0 :   options_rollback_log_transaction(log_transaction);
    1949           0 :   options_rollback_listener_transaction(listener_transaction);
    1950             : 
    1951         214 :  done:
    1952         214 :   return r;
    1953             : }
    1954             : 
    1955             : /** If we need to have a GEOIP ip-to-country map to run with our configured
    1956             :  * options, return 1 and set *<b>reason_out</b> to a description of why. */
    1957             : int
    1958           8 : options_need_geoip_info(const or_options_t *options, const char **reason_out)
    1959             : {
    1960           8 :   int bridge_usage = should_record_bridge_info(options);
    1961          16 :   int routerset_usage =
    1962          16 :     routerset_needs_geoip(options->EntryNodes) ||
    1963          16 :     routerset_needs_geoip(options->ExitNodes) ||
    1964          16 :     routerset_needs_geoip(options->MiddleNodes) ||
    1965          16 :     routerset_needs_geoip(options->ExcludeExitNodes) ||
    1966          16 :     routerset_needs_geoip(options->ExcludeNodes) ||
    1967          24 :     routerset_needs_geoip(options->HSLayer2Nodes) ||
    1968           8 :     routerset_needs_geoip(options->HSLayer3Nodes);
    1969             : 
    1970           8 :   if (routerset_usage && reason_out) {
    1971           0 :     *reason_out = "We've been configured to use (or avoid) nodes in certain "
    1972             :       "countries, and we need GEOIP information to figure out which ones they "
    1973             :       "are.";
    1974           8 :   } else if (bridge_usage && reason_out) {
    1975           0 :     *reason_out = "We've been configured to see which countries can access "
    1976             :       "us as a bridge, and we need GEOIP information to tell which countries "
    1977             :       "clients are in.";
    1978             :   }
    1979           8 :   return bridge_usage || routerset_usage;
    1980             : }
    1981             : 
    1982             : /* Used in the various options_transition_affects* functions. */
    1983             : #define YES_IF_CHANGED_BOOL(opt) \
    1984             :   if (!CFG_EQ_BOOL(old_options, new_options, opt)) return 1;
    1985             : #define YES_IF_CHANGED_INT(opt) \
    1986             :   if (!CFG_EQ_INT(old_options, new_options, opt)) return 1;
    1987             : #define YES_IF_CHANGED_STRING(opt) \
    1988             :   if (!CFG_EQ_STRING(old_options, new_options, opt)) return 1;
    1989             : #define YES_IF_CHANGED_LINELIST(opt) \
    1990             :   if (!CFG_EQ_LINELIST(old_options, new_options, opt)) return 1;
    1991             : #define YES_IF_CHANGED_SMARTLIST(opt) \
    1992             :   if (!CFG_EQ_SMARTLIST(old_options, new_options, opt)) return 1;
    1993             : #define YES_IF_CHANGED_ROUTERSET(opt) \
    1994             :   if (!CFG_EQ_ROUTERSET(old_options, new_options, opt)) return 1;
    1995             : 
    1996             : /**
    1997             :  * Return true if changing the configuration from <b>old</b> to <b>new</b>
    1998             :  * affects the guard subsystem.
    1999             :  */
    2000             : static int
    2001           3 : options_transition_affects_guards(const or_options_t *old_options,
    2002             :                                   const or_options_t *new_options)
    2003             : {
    2004             :   /* NOTE: Make sure this function stays in sync with
    2005             :    * node_passes_guard_filter */
    2006           3 :   tor_assert(old_options);
    2007           3 :   tor_assert(new_options);
    2008             : 
    2009           3 :   YES_IF_CHANGED_BOOL(UseEntryGuards);
    2010           0 :   YES_IF_CHANGED_BOOL(UseBridges);
    2011           0 :   YES_IF_CHANGED_BOOL(ClientUseIPv4);
    2012           0 :   YES_IF_CHANGED_BOOL(ClientUseIPv6);
    2013           0 :   YES_IF_CHANGED_BOOL(FascistFirewall);
    2014           0 :   YES_IF_CHANGED_ROUTERSET(ExcludeNodes);
    2015           0 :   YES_IF_CHANGED_ROUTERSET(EntryNodes);
    2016           0 :   YES_IF_CHANGED_SMARTLIST(FirewallPorts);
    2017           0 :   YES_IF_CHANGED_LINELIST(Bridges);
    2018           0 :   YES_IF_CHANGED_LINELIST(ReachableORAddresses);
    2019           0 :   YES_IF_CHANGED_LINELIST(ReachableDirAddresses);
    2020             : 
    2021             :   return 0;
    2022             : }
    2023             : 
    2024             : /** Fetch the active option list, and take actions based on it. All of the
    2025             :  * things we do should survive being done repeatedly.  If present,
    2026             :  * <b>old_options</b> contains the previous value of the options.
    2027             :  *
    2028             :  * Return 0 if all goes well, return -1 if it's time to die.
    2029             :  *
    2030             :  * Note: We haven't moved all the "act on new configuration" logic
    2031             :  * the options_act* functions yet.  Some is still in do_hup() and other
    2032             :  * places.
    2033             :  */
    2034         213 : MOCK_IMPL(STATIC int,
    2035             : options_act,(const or_options_t *old_options))
    2036             : {
    2037         213 :   config_line_t *cl;
    2038         213 :   or_options_t *options = get_options_mutable();
    2039         213 :   int running_tor = options->command == CMD_RUN_TOR;
    2040         213 :   char *msg=NULL;
    2041         426 :   const int transition_affects_guards =
    2042         213 :     old_options && options_transition_affects_guards(old_options, options);
    2043             : 
    2044         213 :   if (options->NoExec || options->Sandbox) {
    2045           0 :     tor_disable_spawning_background_processes();
    2046             :   }
    2047             : 
    2048             :   /* disable ptrace and later, other basic debugging techniques */
    2049             :   {
    2050             :     /* Remember if we already disabled debugger attachment */
    2051         213 :     static int disabled_debugger_attach = 0;
    2052             :     /* Remember if we already warned about being configured not to disable
    2053             :      * debugger attachment */
    2054         213 :     static int warned_debugger_attach = 0;
    2055             :     /* Don't disable debugger attachment when we're running the unit tests. */
    2056         213 :     if (options->DisableDebuggerAttachment && !disabled_debugger_attach &&
    2057           4 :         running_tor) {
    2058           4 :       int ok = tor_disable_debugger_attach();
    2059             :       /* LCOV_EXCL_START the warned_debugger_attach is 0 can't reach inside. */
    2060             :       if (warned_debugger_attach && ok == 1) {
    2061             :         log_notice(LD_CONFIG, "Disabled attaching debuggers for unprivileged "
    2062             :                    "users.");
    2063             :       }
    2064             :       /* LCOV_EXCL_STOP */
    2065           4 :       disabled_debugger_attach = (ok == 1);
    2066         209 :     } else if (!options->DisableDebuggerAttachment &&
    2067           3 :                !warned_debugger_attach) {
    2068           3 :       log_notice(LD_CONFIG, "Not disabling debugger attaching for "
    2069             :                  "unprivileged users.");
    2070           3 :       warned_debugger_attach = 1;
    2071             :     }
    2072             :   }
    2073             : 
    2074             :   /* Write control ports to disk as appropriate */
    2075         213 :   control_ports_write_to_file();
    2076             : 
    2077         213 :   if (running_tor && !have_lockfile()) {
    2078           4 :     if (try_locking(options, 1) < 0)
    2079             :       return -1;
    2080             :   }
    2081             : 
    2082             :   {
    2083         213 :     int warning_severity = options->ProtocolWarnings ? LOG_WARN : LOG_INFO;
    2084         213 :     set_protocol_warning_severity_level(warning_severity);
    2085             :   }
    2086             : 
    2087         213 :   if (consider_adding_dir_servers(options, old_options) < 0) {
    2088             :     // XXXX This should get validated earlier, and committed here, to
    2089             :     // XXXX lower opportunities for reaching an error case.
    2090             :     return -1;
    2091             :   }
    2092             : 
    2093         213 :   if (hs_service_non_anonymous_mode_enabled(options)) {
    2094           0 :     log_warn(LD_GENERAL, "This copy of Tor was compiled or configured to run "
    2095             :              "in a non-anonymous mode. It will provide NO ANONYMITY.");
    2096             :   }
    2097             : 
    2098             :   /* 31851: OutboundBindAddressExit is relay-only */
    2099         213 :   if (parse_outbound_addresses(options, 0, &msg) < 0) {
    2100             :     // LCOV_EXCL_START
    2101             :     log_warn(LD_BUG, "Failed parsing previously validated outbound "
    2102             :              "bind addresses: %s", msg);
    2103             :     tor_free(msg);
    2104             :     return -1;
    2105             :     // LCOV_EXCL_STOP
    2106             :   }
    2107             : 
    2108         213 :   if (options->Bridges) {
    2109           9 :     mark_bridge_list();
    2110          18 :     for (cl = options->Bridges; cl; cl = cl->next) {
    2111           9 :       bridge_line_t *bridge_line = parse_bridge_line(cl->value);
    2112           9 :       if (!bridge_line) {
    2113             :         // LCOV_EXCL_START
    2114             :         log_warn(LD_BUG,
    2115             :                  "Previously validated Bridge line could not be added!");
    2116             :         return -1;
    2117             :         // LCOV_EXCL_STOP
    2118             :       }
    2119           9 :       bridge_add_from_config(bridge_line);
    2120             :     }
    2121           9 :     sweep_bridge_list();
    2122             :   }
    2123             : 
    2124         213 :   if (running_tor && hs_config_service_all(options, 0)<0) {
    2125             :     // LCOV_EXCL_START
    2126             :     log_warn(LD_BUG,
    2127             :        "Previously validated hidden services line could not be added!");
    2128             :     return -1;
    2129             :     // LCOV_EXCL_STOP
    2130             :   }
    2131             : 
    2132         213 :   if (running_tor && hs_config_client_auth_all(options, 0) < 0) {
    2133             :     // LCOV_EXCL_START
    2134             :     log_warn(LD_BUG, "Previously validated client authorization for "
    2135             :                      "hidden services could not be added!");
    2136             :     return -1;
    2137             :     // LCOV_EXCL_STOP
    2138             :   }
    2139             : 
    2140         213 :   if (running_tor && !old_options &&
    2141           4 :       options->OwningControllerFD != UINT64_MAX) {
    2142           0 :     const unsigned ctrl_flags =
    2143             :       CC_LOCAL_FD_IS_OWNER |
    2144             :       CC_LOCAL_FD_IS_AUTHENTICATED;
    2145           0 :     tor_socket_t ctrl_sock = (tor_socket_t)options->OwningControllerFD;
    2146           0 :     if (control_connection_add_local_fd(ctrl_sock, ctrl_flags) < 0) {
    2147           0 :       log_warn(LD_CONFIG, "Could not add local controller connection with "
    2148             :                "given FD.");
    2149           0 :       return -1;
    2150             :     }
    2151             :   }
    2152             : 
    2153             :   /* Load state */
    2154         213 :   if (! or_state_loaded() && running_tor) {
    2155           4 :     if (or_state_load())
    2156             :       return -1;
    2157           4 :     if (options_act_dirauth_mtbf(options) < 0)
    2158             :       return -1;
    2159             :   }
    2160             : 
    2161             :   /* 31851: some of the code in these functions is relay-only */
    2162         213 :   mark_transport_list();
    2163         213 :   pt_prepare_proxy_list_for_config_read();
    2164         213 :   if (!options->DisableNetwork) {
    2165         175 :     if (options->ClientTransportPlugin) {
    2166           0 :       for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
    2167           0 :         if (pt_parse_transport_line(options, cl->value, 0, 0) < 0) {
    2168             :           // LCOV_EXCL_START
    2169             :           log_warn(LD_BUG,
    2170             :                    "Previously validated ClientTransportPlugin line "
    2171             :                    "could not be added!");
    2172             :           return -1;
    2173             :           // LCOV_EXCL_STOP
    2174             :         }
    2175             :       }
    2176             :     }
    2177             :   }
    2178             : 
    2179         213 :   if (options_act_server_transport(old_options) < 0)
    2180             :     return -1;
    2181             : 
    2182         213 :   sweep_transport_list();
    2183         213 :   sweep_proxy_list();
    2184             : 
    2185             :   /* Start the PT proxy configuration. By doing this configuration
    2186             :      here, we also figure out which proxies need to be restarted and
    2187             :      which not. */
    2188         213 :   if (pt_proxies_configuration_pending() && !net_is_disabled())
    2189           0 :     pt_configure_remaining_proxies();
    2190             : 
    2191             :   /* Bail out at this point if we're not going to be a client or server:
    2192             :    * we want to not fork, and to log stuff to stderr. */
    2193         213 :   if (!running_tor)
    2194             :     return 0;
    2195             : 
    2196             :   /* Finish backgrounding the process */
    2197           4 :   if (options->RunAsDaemon) {
    2198             :     /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
    2199           0 :     finish_daemon(options->DataDirectory);
    2200             :   }
    2201             : 
    2202           4 :   if (options_act_relay(old_options) < 0)
    2203             :     return -1;
    2204             : 
    2205             :   /* Write our PID to the PID file. If we do not have write permissions we
    2206             :    * will log a warning and exit. */
    2207           4 :   if (options->PidFile && !sandbox_is_active()) {
    2208           0 :     if (write_pidfile(options->PidFile) < 0) {
    2209           0 :       log_err(LD_CONFIG, "Unable to write PIDFile %s",
    2210             :               escaped(options->PidFile));
    2211           0 :       return -1;
    2212             :     }
    2213             :   }
    2214             : 
    2215             :   /* Register addressmap directives */
    2216           4 :   config_register_addressmaps(options);
    2217           4 :   parse_virtual_addr_network(options->VirtualAddrNetworkIPv4, AF_INET,0,NULL);
    2218           4 :   parse_virtual_addr_network(options->VirtualAddrNetworkIPv6, AF_INET6,0,NULL);
    2219             : 
    2220             :   /* Update address policies. */
    2221           4 :   if (policies_parse_from_options(options) < 0) {
    2222             :     /* This should be impossible, but let's be sure. */
    2223           0 :     log_warn(LD_BUG,"Error parsing already-validated policy options.");
    2224           0 :     return -1;
    2225             :   }
    2226             : 
    2227           4 :   if (init_control_cookie_authentication(options->CookieAuthentication) < 0) {
    2228           0 :     log_warn(LD_CONFIG,"Error creating control cookie authentication file.");
    2229           0 :     return -1;
    2230             :   }
    2231             : 
    2232           4 :   monitor_owning_controller_process(options->OwningControllerProcess);
    2233             : 
    2234             :   /* reload keys as needed for rendezvous services. */
    2235           4 :   if (hs_service_load_all_keys() < 0) {
    2236           0 :     log_warn(LD_GENERAL,"Error loading rendezvous service keys");
    2237           0 :     return -1;
    2238             :   }
    2239             : 
    2240             :   /* Inform the scheduler subsystem that a configuration changed happened. It
    2241             :    * might be a change of scheduler or parameter. */
    2242           4 :   scheduler_conf_changed();
    2243             : 
    2244           4 :   if (options_act_relay_accounting(old_options) < 0)
    2245             :     return -1;
    2246             : 
    2247             :   /* Change the cell EWMA settings */
    2248           4 :   cmux_ewma_set_options(options, networkstatus_get_latest_consensus());
    2249             : 
    2250             :   /* Update the BridgePassword's hashed version as needed.  We store this as a
    2251             :    * digest so that we can do side-channel-proof comparisons on it.
    2252             :    */
    2253           4 :   if (options->BridgePassword) {
    2254           0 :     char *http_authenticator;
    2255           0 :     http_authenticator = alloc_http_authenticator(options->BridgePassword);
    2256           0 :     if (!http_authenticator) {
    2257             :       // XXXX This should get validated in options_validate().
    2258           0 :       log_warn(LD_BUG, "Unable to allocate HTTP authenticator. Not setting "
    2259             :                "BridgePassword.");
    2260           0 :       return -1;
    2261             :     }
    2262           0 :     options->BridgePassword_AuthDigest_ = tor_malloc(DIGEST256_LEN);
    2263           0 :     crypto_digest256(options->BridgePassword_AuthDigest_,
    2264             :                      http_authenticator, strlen(http_authenticator),
    2265             :                      DIGEST_SHA256);
    2266           0 :     tor_free(http_authenticator);
    2267             :   }
    2268             : 
    2269           4 :   config_maybe_load_geoip_files_(options, old_options);
    2270             : 
    2271           4 :   if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) {
    2272             :     /* ExcludeUnknown is true or "auto" */
    2273           0 :     const int is_auto = options->GeoIPExcludeUnknown == -1;
    2274           0 :     int changed;
    2275             : 
    2276           0 :     changed  = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto);
    2277           0 :     changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto);
    2278             : 
    2279           0 :     if (changed)
    2280           0 :       routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto);
    2281             :   }
    2282             : 
    2283             :   /* Check for transitions that need action. */
    2284           4 :   if (old_options) {
    2285           0 :     int revise_trackexithosts = 0;
    2286           0 :     int revise_automap_entries = 0;
    2287           0 :     int abandon_circuits = 0;
    2288           0 :     if ((options->UseEntryGuards && !old_options->UseEntryGuards) ||
    2289           0 :         options->UseBridges != old_options->UseBridges ||
    2290           0 :         (options->UseBridges &&
    2291           0 :          !config_lines_eq(options->Bridges, old_options->Bridges)) ||
    2292           0 :         !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes) ||
    2293           0 :         !routerset_equal(old_options->ExcludeExitNodes,
    2294           0 :                          options->ExcludeExitNodes) ||
    2295           0 :         !routerset_equal(old_options->EntryNodes, options->EntryNodes) ||
    2296           0 :         !routerset_equal(old_options->ExitNodes, options->ExitNodes) ||
    2297           0 :         !routerset_equal(old_options->HSLayer2Nodes,
    2298           0 :                          options->HSLayer2Nodes) ||
    2299           0 :         !routerset_equal(old_options->HSLayer3Nodes,
    2300           0 :                          options->HSLayer3Nodes) ||
    2301           0 :         !routerset_equal(old_options->MiddleNodes, options->MiddleNodes) ||
    2302           0 :         options->StrictNodes != old_options->StrictNodes) {
    2303           0 :       log_info(LD_CIRC,
    2304             :                "Changed to using entry guards or bridges, or changed "
    2305             :                "preferred or excluded node lists. "
    2306             :                "Abandoning previous circuits.");
    2307           0 :       abandon_circuits = 1;
    2308             :     }
    2309             : 
    2310           0 :     if (transition_affects_guards) {
    2311           0 :       if (guards_update_all()) {
    2312             :         abandon_circuits = 1;
    2313             :       }
    2314             :     }
    2315             : 
    2316           0 :     if (abandon_circuits) {
    2317           0 :       circuit_mark_all_unused_circs();
    2318           0 :       circuit_mark_all_dirty_circs_as_unusable();
    2319           0 :       revise_trackexithosts = 1;
    2320             :     }
    2321             : 
    2322           0 :     if (!smartlist_strings_eq(old_options->TrackHostExits,
    2323           0 :                               options->TrackHostExits))
    2324             :       revise_trackexithosts = 1;
    2325             : 
    2326           0 :     if (revise_trackexithosts)
    2327           0 :       addressmap_clear_excluded_trackexithosts(options);
    2328             : 
    2329           0 :     if (!options->AutomapHostsOnResolve &&
    2330           0 :         old_options->AutomapHostsOnResolve) {
    2331             :         revise_automap_entries = 1;
    2332             :     } else {
    2333           0 :       if (!smartlist_strings_eq(old_options->AutomapHostsSuffixes,
    2334           0 :                                 options->AutomapHostsSuffixes))
    2335             :         revise_automap_entries = 1;
    2336           0 :       else if (!opt_streq(old_options->VirtualAddrNetworkIPv4,
    2337           0 :                           options->VirtualAddrNetworkIPv4) ||
    2338           0 :                !opt_streq(old_options->VirtualAddrNetworkIPv6,
    2339           0 :                           options->VirtualAddrNetworkIPv6))
    2340             :         revise_automap_entries = 1;
    2341             :     }
    2342             : 
    2343             :     if (revise_automap_entries)
    2344           0 :       addressmap_clear_invalid_automaps(options);
    2345             : 
    2346           0 :     if (options_act_bridge_stats(old_options) < 0)
    2347             :       return -1;
    2348             : 
    2349           0 :     if (dns_reset())
    2350             :       return -1;
    2351             : 
    2352           0 :     if (options_act_relay_bandwidth(old_options) < 0)
    2353             :       return -1;
    2354             : 
    2355           0 :     if (options->BandwidthRate != old_options->BandwidthRate ||
    2356           0 :         options->BandwidthBurst != old_options->BandwidthBurst)
    2357           0 :       connection_bucket_adjust(options);
    2358             : 
    2359           0 :     if (options->MainloopStats != old_options->MainloopStats) {
    2360           0 :       reset_main_loop_counters();
    2361             :     }
    2362             :   }
    2363             : 
    2364             :   /* 31851: These options are relay-only, but we need to disable them if we
    2365             :    * are in client mode. In 29211, we will disable all relay options in
    2366             :    * client mode. */
    2367             :   /* Only collect directory-request statistics on relays and bridges. */
    2368           8 :   options->DirReqStatistics = options->DirReqStatistics_option &&
    2369           4 :     server_mode(options);
    2370           8 :   options->HiddenServiceStatistics =
    2371           4 :     options->HiddenServiceStatistics_option && server_mode(options);
    2372             : 
    2373             :   /* Only collect other relay-only statistics on relays. */
    2374           4 :   if (!public_server_mode(options)) {
    2375           0 :     options->CellStatistics = 0;
    2376           0 :     options->EntryStatistics = 0;
    2377           0 :     options->ConnDirectionStatistics = 0;
    2378           0 :     options->ExitPortStatistics = 0;
    2379             :   }
    2380             : 
    2381           4 :   bool print_notice = 0;
    2382           4 :   if (options_act_relay_stats(old_options, &print_notice) < 0)
    2383             :     return -1;
    2384           4 :   if (options_act_dirauth_stats(old_options, &print_notice) < 0)
    2385             :     return -1;
    2386           4 :   if (print_notice)
    2387           0 :     options_act_relay_stats_msg();
    2388             : 
    2389           4 :   if (options_act_relay_desc(old_options) < 0)
    2390             :     return -1;
    2391             : 
    2392           4 :   if (options_act_dirauth(old_options) < 0)
    2393             :     return -1;
    2394             : 
    2395             :   /* We may need to reschedule some directory stuff if our status changed. */
    2396           4 :   if (old_options) {
    2397           0 :     if (!bool_eq(dirclient_fetches_dir_info_early(options),
    2398           0 :                  dirclient_fetches_dir_info_early(old_options)) ||
    2399           0 :         !bool_eq(dirclient_fetches_dir_info_later(options),
    2400           0 :                  dirclient_fetches_dir_info_later(old_options)) ||
    2401           0 :         !config_lines_eq(old_options->Bridges, options->Bridges)) {
    2402             :       /* Make sure update_router_have_minimum_dir_info() gets called. */
    2403           0 :       router_dir_info_changed();
    2404             :       /* We might need to download a new consensus status later or sooner than
    2405             :        * we had expected. */
    2406           0 :       update_consensus_networkstatus_fetch_time(time(NULL));
    2407             :     }
    2408             :   }
    2409             : 
    2410           4 :   if (options_act_relay_dos(old_options) < 0)
    2411             :     return -1;
    2412           4 :   if (options_act_relay_dir(old_options) < 0)
    2413           0 :     return -1;
    2414             : 
    2415             :   return 0;
    2416             : }
    2417             : 
    2418             : /**
    2419             :  * Enumeration to describe the syntax for a command-line option.
    2420             :  **/
    2421             : typedef enum {
    2422             :   /** Describe an option that does not take an argument. */
    2423             :   ARGUMENT_NONE = 0,
    2424             :   /** Describes an option that takes a single argument. */
    2425             :   ARGUMENT_NECESSARY = 1,
    2426             :   /** Describes an option that takes a single optional argument. */
    2427             :   ARGUMENT_OPTIONAL = 2
    2428             : } takes_argument_t;
    2429             : 
    2430             : /** Table describing arguments that Tor accepts on the command line,
    2431             :  * other than those that are the same as in torrc. */
    2432             : static const struct {
    2433             :   /** The string that the user has to provide. */
    2434             :   const char *name;
    2435             :   /** Optional short name. */
    2436             :   const char *short_name;
    2437             :   /** Does this option accept an argument? */
    2438             :   takes_argument_t takes_argument;
    2439             :   /** If not CMD_RUN_TOR, what should Tor do when it starts? */
    2440             :   tor_cmdline_mode_t command;
    2441             :   /** If nonzero, set the quiet level to this. 1 is "hush", 2 is "quiet" */
    2442             :   int quiet;
    2443             : } CMDLINE_ONLY_OPTIONS[] = {
    2444             :   { .name="--torrc-file",
    2445             :     .short_name="-f",
    2446             :     .takes_argument=ARGUMENT_NECESSARY },
    2447             :   { .name="--allow-missing-torrc" },
    2448             :   { .name="--defaults-torrc",
    2449             :     .takes_argument=ARGUMENT_NECESSARY },
    2450             :   { .name="--hash-password",
    2451             :     .takes_argument=ARGUMENT_NECESSARY,
    2452             :     .command=CMD_HASH_PASSWORD,
    2453             :     .quiet=QUIET_HUSH  },
    2454             :   { .name="--dump-config",
    2455             :     .takes_argument=ARGUMENT_OPTIONAL,
    2456             :     .command=CMD_DUMP_CONFIG,
    2457             :     .quiet=QUIET_SILENT },
    2458             :   { .name="--list-fingerprint",
    2459             :     .takes_argument=ARGUMENT_OPTIONAL,
    2460             :     .command=CMD_LIST_FINGERPRINT },
    2461             :   { .name="--keygen",
    2462             :     .command=CMD_KEYGEN },
    2463             :   { .name="--key-expiration",
    2464             :     .takes_argument=ARGUMENT_OPTIONAL,
    2465             :     .command=CMD_KEY_EXPIRATION },
    2466             :   { .name="--format",
    2467             :     .takes_argument=ARGUMENT_NECESSARY },
    2468             :   { .name="--newpass" },
    2469             :   { .name="--no-passphrase" },
    2470             :   { .name="--passphrase-fd",
    2471             :     .takes_argument=ARGUMENT_NECESSARY },
    2472             :   { .name="--verify-config",
    2473             :     .command=CMD_VERIFY_CONFIG },
    2474             :   { .name="--ignore-missing-torrc" },
    2475             :   { .name="--quiet",
    2476             :     .quiet=QUIET_SILENT },
    2477             :   { .name="--hush",
    2478             :     .quiet=QUIET_HUSH },
    2479             :   { .name="--version",
    2480             :     .command=CMD_IMMEDIATE,
    2481             :     .quiet=QUIET_HUSH },
    2482             :   { .name="--list-modules",
    2483             :     .command=CMD_IMMEDIATE,
    2484             :     .quiet=QUIET_HUSH },
    2485             :   { .name="--library-versions",
    2486             :     .command=CMD_IMMEDIATE,
    2487             :     .quiet=QUIET_HUSH },
    2488             :   { .name="--help",
    2489             :     .short_name="-h",
    2490             :     .command=CMD_IMMEDIATE,
    2491             :     .quiet=QUIET_HUSH  },
    2492             :   { .name="--list-torrc-options",
    2493             :     .command=CMD_IMMEDIATE,
    2494             :     .quiet=QUIET_HUSH },
    2495             :   { .name="--list-deprecated-options",
    2496             :     .command=CMD_IMMEDIATE },
    2497             :   { .name="--nt-service" },
    2498             :   { .name="-nt-service" },
    2499             :   { .name="--dbg-dump-subsystem-list",
    2500             :     .command=CMD_IMMEDIATE,
    2501             :     .quiet=QUIET_HUSH },
    2502             :   { .name=NULL },
    2503             : };
    2504             : 
    2505             : /** Helper: Read a list of configuration options from the command line.  If
    2506             :  * successful, return a newly allocated parsed_cmdline_t; otherwise return
    2507             :  * NULL.
    2508             :  *
    2509             :  * If <b>ignore_errors</b> is set, try to recover from all recoverable
    2510             :  * errors and return the best command line we can.
    2511             :  */
    2512             : parsed_cmdline_t *
    2513         470 : config_parse_commandline(int argc, char **argv, int ignore_errors)
    2514             : {
    2515         470 :   parsed_cmdline_t *result = tor_malloc_zero(sizeof(parsed_cmdline_t));
    2516         470 :   result->command = CMD_RUN_TOR;
    2517         470 :   config_line_t *param = NULL;
    2518             : 
    2519         470 :   config_line_t **new_cmdline = &result->cmdline_opts;
    2520         470 :   config_line_t **new = &result->other_opts;
    2521             : 
    2522         470 :   char *s, *arg;
    2523         470 :   int i = 1;
    2524             : 
    2525        2350 :   while (i < argc) {
    2526       17462 :     unsigned command = CONFIG_LINE_NORMAL;
    2527       17462 :     takes_argument_t want_arg = ARGUMENT_NECESSARY;
    2528       17462 :     int is_cmdline = 0;
    2529             :     int j;
    2530       17462 :     bool is_a_command = false;
    2531             : 
    2532       17462 :     for (j = 0; CMDLINE_ONLY_OPTIONS[j].name != NULL; ++j) {
    2533       17070 :       if (!strcmp(argv[i], CMDLINE_ONLY_OPTIONS[j].name) ||
    2534       16040 :           (CMDLINE_ONLY_OPTIONS[j].short_name &&
    2535        2276 :            !strcmp(argv[i], CMDLINE_ONLY_OPTIONS[j].short_name))) {
    2536        1490 :         is_cmdline = 1;
    2537        1490 :         want_arg = CMDLINE_ONLY_OPTIONS[j].takes_argument;
    2538        1490 :         if (CMDLINE_ONLY_OPTIONS[j].command != CMD_RUN_TOR) {
    2539         464 :           is_a_command = true;
    2540         464 :           result->command = CMDLINE_ONLY_OPTIONS[j].command;
    2541             :         }
    2542        1490 :         quiet_level_t quiet = CMDLINE_ONLY_OPTIONS[j].quiet;
    2543        1490 :         if (quiet > result->quiet_level)
    2544         310 :           result->quiet_level = quiet;
    2545             :         break;
    2546             :       }
    2547             :     }
    2548             : 
    2549        1882 :     s = argv[i];
    2550             : 
    2551             :     /* Each keyword may be prefixed with one or two dashes. */
    2552        1882 :     if (*s == '-')
    2553        1854 :       s++;
    2554        1882 :     if (*s == '-')
    2555        1394 :       s++;
    2556             :     /* Figure out the command, if any. */
    2557        1882 :     if (*s == '+') {
    2558           8 :       s++;
    2559           8 :       command = CONFIG_LINE_APPEND;
    2560        1874 :     } else if (*s == '/') {
    2561          12 :       s++;
    2562          12 :       command = CONFIG_LINE_CLEAR;
    2563             :       /* A 'clear' command has no argument. */
    2564          12 :       want_arg = 0;
    2565             :     }
    2566             : 
    2567        1882 :     const int is_last = (i == argc-1);
    2568             : 
    2569        1882 :     if (want_arg == ARGUMENT_NECESSARY && is_last) {
    2570           4 :       if (ignore_errors) {
    2571           2 :         arg = tor_strdup("");
    2572             :       } else {
    2573           2 :         log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
    2574             :             argv[i]);
    2575           2 :         parsed_cmdline_free(result);
    2576           2 :         return NULL;
    2577             :       }
    2578        1878 :     } else if (want_arg == ARGUMENT_OPTIONAL &&
    2579             :                /* optional arguments may never start with '-'. */
    2580         232 :                (is_last || argv[i+1][0] == '-')) {
    2581          40 :       arg = tor_strdup("");
    2582          40 :       want_arg = ARGUMENT_NONE; // prevent skipping the next flag.
    2583             :     } else {
    2584        1838 :       arg = (want_arg != ARGUMENT_NONE) ? tor_strdup(argv[i+1]) :
    2585         288 :                                               tor_strdup("");
    2586             :     }
    2587             : 
    2588        1880 :     param = tor_malloc_zero(sizeof(config_line_t));
    2589        1880 :     param->key = is_cmdline ? tor_strdup(argv[i]) :
    2590         392 :                  tor_strdup(config_expand_abbrev(get_options_mgr(), s, 1, 1));
    2591        1880 :     param->value = arg;
    2592        1880 :     param->command = command;
    2593        1880 :     param->next = NULL;
    2594        1880 :     log_debug(LD_CONFIG, "command line: parsed keyword '%s', value '%s'",
    2595             :         param->key, param->value);
    2596             : 
    2597        1880 :     if (is_a_command) {
    2598         463 :       result->command_arg = param->value;
    2599             :     }
    2600             : 
    2601        1880 :     if (is_cmdline) {
    2602        1488 :       *new_cmdline = param;
    2603        1488 :       new_cmdline = &((*new_cmdline)->next);
    2604             :     } else {
    2605         392 :       *new = param;
    2606         392 :       new = &((*new)->next);
    2607             :     }
    2608             : 
    2609        2208 :     i += want_arg ? 2 : 1;
    2610             :   }
    2611             : 
    2612             :   return result;
    2613             : }
    2614             : 
    2615             : /** Release all storage held by <b>cmdline</b>. */
    2616             : void
    2617         478 : parsed_cmdline_free_(parsed_cmdline_t *cmdline)
    2618             : {
    2619         478 :   if (!cmdline)
    2620             :     return;
    2621         470 :   config_free_lines(cmdline->cmdline_opts);
    2622         470 :   config_free_lines(cmdline->other_opts);
    2623         470 :   tor_free(cmdline);
    2624             : }
    2625             : 
    2626             : /** Return true iff key is a valid configuration option. */
    2627             : int
    2628           8 : option_is_recognized(const char *key)
    2629             : {
    2630           8 :   return config_find_option_name(get_options_mgr(), key) != NULL;
    2631             : }
    2632             : 
    2633             : /** Return the canonical name of a configuration option, or NULL
    2634             :  * if no such option exists. */
    2635             : const char *
    2636           1 : option_get_canonical_name(const char *key)
    2637             : {
    2638           1 :   return config_find_option_name(get_options_mgr(), key);
    2639             : }
    2640             : 
    2641             : /** Return a canonical list of the options assigned for key.
    2642             :  */
    2643             : config_line_t *
    2644           4 : option_get_assignment(const or_options_t *options, const char *key)
    2645             : {
    2646           4 :   return config_get_assigned_option(get_options_mgr(), options, key, 1);
    2647             : }
    2648             : 
    2649             : /** Try assigning <b>list</b> to the global options. You do this by duping
    2650             :  * options, assigning list to the new one, then validating it. If it's
    2651             :  * ok, then throw out the old one and stick with the new one. Else,
    2652             :  * revert to old and return failure.  Return SETOPT_OK on success, or
    2653             :  * a setopt_err_t on failure.
    2654             :  *
    2655             :  * If not success, point *<b>msg</b> to a newly allocated string describing
    2656             :  * what went wrong.
    2657             :  */
    2658             : setopt_err_t
    2659           5 : options_trial_assign(config_line_t *list, unsigned flags, char **msg)
    2660             : {
    2661           5 :   int r;
    2662           5 :   or_options_t *trial_options = config_dup(get_options_mgr(), get_options());
    2663             : 
    2664           5 :   if ((r=config_assign(get_options_mgr(), trial_options,
    2665             :                        list, flags, msg)) < 0) {
    2666           1 :     or_options_free(trial_options);
    2667           1 :     return r;
    2668             :   }
    2669           4 :   const or_options_t *cur_options = get_options();
    2670             : 
    2671           4 :   return options_validate_and_set(cur_options, trial_options, msg);
    2672             : }
    2673             : 
    2674             : /** Print a usage message for tor. */
    2675             : static void
    2676           0 : print_usage(void)
    2677             : {
    2678           0 :   printf(
    2679             : "Copyright (c) 2001-2004, Roger Dingledine\n"
    2680             : "Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n"
    2681             : "Copyright (c) 2007-2021, The Tor Project, Inc.\n\n"
    2682             : "tor -f <torrc> [args]\n"
    2683             : "See man page for options, or https://www.torproject.org/ for "
    2684             : "documentation.\n");
    2685           0 : }
    2686             : 
    2687             : /** Print all non-obsolete torrc options. */
    2688             : static void
    2689           1 : list_torrc_options(void)
    2690             : {
    2691           1 :   smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
    2692         430 :   SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
    2693             :     /* Possibly this should check listable, rather than (or in addition to)
    2694             :      * settable. See ticket 31654.
    2695             :      */
    2696         429 :     if (! config_var_is_settable(var)) {
    2697             :       /* This variable cannot be set, or cannot be set by this name. */
    2698          85 :       continue;
    2699             :     }
    2700         344 :     printf("%s\n", var->member.name);
    2701         429 :   } SMARTLIST_FOREACH_END(var);
    2702           1 :   smartlist_free(vars);
    2703           1 : }
    2704             : 
    2705             : /** Print all deprecated but non-obsolete torrc options. */
    2706             : static void
    2707           0 : list_deprecated_options(void)
    2708             : {
    2709           0 :   smartlist_t *deps = config_mgr_list_deprecated_vars(get_options_mgr());
    2710             :   /* Possibly this should check whether the variables are listable,
    2711             :    * but currently it does not.  See ticket 31654. */
    2712           0 :   SMARTLIST_FOREACH(deps, const char *, name,
    2713             :                     printf("%s\n", name));
    2714           0 :   smartlist_free(deps);
    2715           0 : }
    2716             : 
    2717             : /** Print all compile-time modules and their enabled/disabled status. */
    2718             : static void
    2719           4 : list_enabled_modules(void)
    2720             : {
    2721           4 :   printf("%s: %s\n", "relay", have_module_relay() ? "yes" : "no");
    2722           4 :   printf("%s: %s\n", "dirauth", have_module_dirauth() ? "yes" : "no");
    2723             :   // We don't list dircache, because it cannot be enabled or disabled
    2724             :   // independently from relay.  Listing it here would proliferate
    2725             :   // test variants in test_parseconf.sh to no useful purpose.
    2726           4 : }
    2727             : 
    2728             : /** Prints compile-time and runtime library versions. */
    2729             : static void
    2730           0 : print_library_versions(void)
    2731             : {
    2732           0 :   printf("Tor version %s. \n", get_version());
    2733           0 :   printf("Library versions\tCompiled\t\tRuntime\n");
    2734           0 :   printf("Libevent\t\t%-15s\t\t%s\n",
    2735             :                     tor_libevent_get_header_version_str(),
    2736             :                     tor_libevent_get_version_str());
    2737             : #ifdef ENABLE_OPENSSL
    2738           0 :   printf("OpenSSL \t\t%-15s\t\t%s\n",
    2739             :                      crypto_openssl_get_header_version_str(),
    2740             :                      crypto_openssl_get_version_str());
    2741             : #endif
    2742             : #ifdef ENABLE_NSS
    2743             :   printf("NSS \t\t%-15s\t\t%s\n",
    2744             :                 crypto_nss_get_header_version_str(),
    2745             :                 crypto_nss_get_version_str());
    2746             : #endif
    2747           0 :   if (tor_compress_supports_method(ZLIB_METHOD)) {
    2748           0 :     printf("Zlib    \t\t%-15s\t\t%s\n",
    2749             :                       tor_compress_version_str(ZLIB_METHOD),
    2750             :                       tor_compress_header_version_str(ZLIB_METHOD));
    2751             :   }
    2752           0 :   if (tor_compress_supports_method(LZMA_METHOD)) {
    2753           0 :     printf("Liblzma \t\t%-15s\t\t%s\n",
    2754             :                       tor_compress_version_str(LZMA_METHOD),
    2755             :                       tor_compress_header_version_str(LZMA_METHOD));
    2756             :   }
    2757           0 :   if (tor_compress_supports_method(ZSTD_METHOD)) {
    2758           0 :     printf("Libzstd \t\t%-15s\t\t%s\n",
    2759             :                       tor_compress_version_str(ZSTD_METHOD),
    2760             :                       tor_compress_header_version_str(ZSTD_METHOD));
    2761             :   }
    2762           0 :   if (tor_libc_get_name()) {
    2763           0 :     printf("%-7s \t\t%-15s\t\t%s\n",
    2764             :            tor_libc_get_name(),
    2765             :            tor_libc_get_header_version_str(),
    2766             :            tor_libc_get_version_str());
    2767             :   }
    2768             :   //TODO: Hex versions?
    2769           0 : }
    2770             : 
    2771             : /** Handles the --no-passphrase command line option. */
    2772             : static int
    2773           3 : handle_cmdline_no_passphrase(tor_cmdline_mode_t command)
    2774             : {
    2775           3 :   if (command == CMD_KEYGEN) {
    2776           2 :     get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_OFF;
    2777           2 :     return 0;
    2778             :   } else {
    2779           1 :     log_err(LD_CONFIG, "--no-passphrase specified without --keygen!");
    2780           1 :     return -1;
    2781             :   }
    2782             : }
    2783             : 
    2784             : /** Handles the --format command line option. */
    2785             : static int
    2786           4 : handle_cmdline_format(tor_cmdline_mode_t command, const char *value)
    2787             : {
    2788           4 :   if (command == CMD_KEY_EXPIRATION) {
    2789             :     // keep the same order as enum key_expiration_format
    2790           3 :     const char *formats[] = { "iso8601", "timestamp" };
    2791           3 :     int format = -1;
    2792           6 :     for (unsigned i = 0; i < ARRAY_LENGTH(formats); i++) {
    2793           5 :       if (!strcmp(value, formats[i])) {
    2794           2 :         format = i;
    2795           2 :         break;
    2796             :       }
    2797             :     }
    2798             : 
    2799           3 :     if (format < 0) {
    2800           1 :       log_err(LD_CONFIG, "Invalid --format value %s", escaped(value));
    2801           1 :       return -1;
    2802             :     } else {
    2803           2 :       get_options_mutable()->key_expiration_format = format;
    2804             :     }
    2805           2 :     return 0;
    2806             :   } else {
    2807           1 :     log_err(LD_CONFIG, "--format specified without --key-expiration!");
    2808           1 :     return -1;
    2809             :   }
    2810             : }
    2811             : 
    2812             : /** Handles the --newpass command line option. */
    2813             : static int
    2814           1 : handle_cmdline_newpass(tor_cmdline_mode_t command)
    2815             : {
    2816           1 :   if (command == CMD_KEYGEN) {
    2817           0 :     get_options_mutable()->change_key_passphrase = 1;
    2818           0 :     return 0;
    2819             :   } else {
    2820           1 :     log_err(LD_CONFIG, "--newpass specified without --keygen!");
    2821           1 :     return -1;
    2822             :   }
    2823             : }
    2824             : 
    2825             : /** Handles the --passphrase-fd command line option. */
    2826             : static int
    2827           5 : handle_cmdline_passphrase_fd(tor_cmdline_mode_t command, const char *value)
    2828             : {
    2829           5 :   if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) {
    2830           1 :     log_err(LD_CONFIG, "--no-passphrase specified with --passphrase-fd!");
    2831           1 :     return -1;
    2832           4 :   } else if (command != CMD_KEYGEN) {
    2833           1 :     log_err(LD_CONFIG, "--passphrase-fd specified without --keygen!");
    2834           1 :     return -1;
    2835             :   } else {
    2836           3 :     int ok = 1;
    2837           3 :     long fd = tor_parse_long(value, 10, 0, INT_MAX, &ok, NULL);
    2838           3 :     if (fd < 0 || ok == 0) {
    2839           1 :       log_err(LD_CONFIG, "Invalid --passphrase-fd value %s", escaped(value));
    2840           1 :       return -1;
    2841             :     }
    2842           2 :     get_options_mutable()->keygen_passphrase_fd = (int)fd;
    2843           2 :     get_options_mutable()->use_keygen_passphrase_fd = 1;
    2844           2 :     get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_ON;
    2845           2 :     return 0;
    2846             :   }
    2847             : }
    2848             : 
    2849             : /** Handles the --master-key command line option. */
    2850             : static int
    2851           0 : handle_cmdline_master_key(tor_cmdline_mode_t command, const char *value)
    2852             : {
    2853           0 :   if (command != CMD_KEYGEN) {
    2854           0 :     log_err(LD_CONFIG, "--master-key without --keygen!");
    2855           0 :     return -1;
    2856             :   } else {
    2857           0 :     get_options_mutable()->master_key_fname = tor_strdup(value);
    2858           0 :     return 0;
    2859             :   }
    2860             : }
    2861             : 
    2862             : /* Return true if <b>options</b> is using the default authorities, and false
    2863             :  * if any authority-related option has been overridden. */
    2864             : int
    2865          11 : using_default_dir_authorities(const or_options_t *options)
    2866             : {
    2867          11 :   return (!options->DirAuthorities && !options->AlternateDirAuthority);
    2868             : }
    2869             : 
    2870             : /** Return a new empty or_options_t.  Used for testing. */
    2871             : or_options_t *
    2872        6358 : options_new(void)
    2873             : {
    2874        6358 :   or_options_t *options = config_new(get_options_mgr());
    2875        6358 :   options->command = CMD_RUN_TOR;
    2876        6358 :   return options;
    2877             : }
    2878             : 
    2879             : /** Set <b>options</b> to hold reasonable defaults for most options.
    2880             :  * Each option defaults to zero. */
    2881             : void
    2882         956 : options_init(or_options_t *options)
    2883             : {
    2884         956 :   config_init(get_options_mgr(), options);
    2885         956 :   config_line_t *dflts = get_options_defaults();
    2886         956 :   char *msg=NULL;
    2887         956 :   if (config_assign(get_options_mgr(), options, dflts,
    2888             :                     CAL_WARN_DEPRECATIONS, &msg)<0) {
    2889           0 :     log_err(LD_BUG, "Unable to set default options: %s", msg);
    2890           0 :     tor_free(msg);
    2891           0 :     tor_assert_unreached();
    2892             :   }
    2893         956 :   config_free_lines(dflts);
    2894         956 :   tor_free(msg);
    2895         956 : }
    2896             : 
    2897             : /** Return a string containing a possible configuration file that would give
    2898             :  * the configuration in <b>options</b>.  If <b>minimal</b> is true, do not
    2899             :  * include options that are the same as Tor's defaults.
    2900             :  */
    2901             : char *
    2902         110 : options_dump(const or_options_t *options, int how_to_dump)
    2903             : {
    2904         110 :   const or_options_t *use_defaults;
    2905         110 :   int minimal;
    2906         110 :   switch (how_to_dump) {
    2907         110 :     case OPTIONS_DUMP_MINIMAL:
    2908         110 :       use_defaults = global_default_options;
    2909         110 :       minimal = 1;
    2910         110 :       break;
    2911             :     case OPTIONS_DUMP_ALL:
    2912             :       use_defaults = NULL;
    2913             :       minimal = 0;
    2914             :       break;
    2915           0 :     default:
    2916           0 :       log_warn(LD_BUG, "Bogus value for how_to_dump==%d", how_to_dump);
    2917           0 :       return NULL;
    2918             :   }
    2919             : 
    2920         110 :   return config_dump(get_options_mgr(), use_defaults, options, minimal, 0);
    2921             : }
    2922             : 
    2923             : /** Return 0 if every element of sl is a string holding a decimal
    2924             :  * representation of a port number, or if sl is NULL.
    2925             :  * Otherwise set *msg and return -1. */
    2926             : static int
    2927        2142 : validate_ports_csv(smartlist_t *sl, const char *name, char **msg)
    2928             : {
    2929        2142 :   int i;
    2930        2142 :   tor_assert(name);
    2931             : 
    2932        2142 :   if (!sl)
    2933             :     return 0;
    2934             : 
    2935       10644 :   SMARTLIST_FOREACH(sl, const char *, cp,
    2936             :   {
    2937             :     i = atoi(cp);
    2938             :     if (i < 1 || i > 65535) {
    2939             :       tor_asprintf(msg, "Port '%s' out of range in %s", cp, name);
    2940             :       return -1;
    2941             :     }
    2942             :   });
    2943             :   return 0;
    2944             : }
    2945             : 
    2946             : /** If <b>value</b> exceeds ROUTER_MAX_DECLARED_BANDWIDTH, write
    2947             :  * a complaint into *<b>msg</b> using string <b>desc</b>, and return -1.
    2948             :  * Else return 0.
    2949             :  */
    2950             : int
    2951        4610 : config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
    2952             : {
    2953        4610 :   if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
    2954             :     /* This handles an understandable special case where somebody says "2gb"
    2955             :      * whereas our actual maximum is 2gb-1 (INT_MAX) */
    2956          25 :     --*value;
    2957             :   }
    2958        4610 :   if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
    2959          23 :     tor_asprintf(msg, "%s (%"PRIu64") must be at most %d",
    2960             :                  desc, (*value),
    2961             :                  ROUTER_MAX_DECLARED_BANDWIDTH);
    2962          23 :     return -1;
    2963             :   }
    2964             :   return 0;
    2965             : }
    2966             : 
    2967             : /** Lowest allowable value for RendPostPeriod; if this is too low, hidden
    2968             :  * services can overload the directory system. */
    2969             : #define MIN_REND_POST_PERIOD (10*60)
    2970             : #define MIN_REND_POST_PERIOD_TESTING (5)
    2971             : 
    2972             : /** Highest allowable value for CircuitsAvailableTimeout.
    2973             :  * If this is too large, client connections will stay open for too long,
    2974             :  * incurring extra padding overhead. */
    2975             : #define MAX_CIRCS_AVAILABLE_TIME (24*60*60)
    2976             : 
    2977             : /** Highest allowable value for RendPostPeriod. */
    2978             : #define MAX_DIR_PERIOD ((7*24*60*60)/2)
    2979             : 
    2980             : /** Lowest allowable value for MaxCircuitDirtiness; if this is too low, Tor
    2981             :  * will generate too many circuits and potentially overload the network. */
    2982             : #define MIN_MAX_CIRCUIT_DIRTINESS 10
    2983             : 
    2984             : /** Highest allowable value for MaxCircuitDirtiness: prevents time_t
    2985             :  * overflows. */
    2986             : #define MAX_MAX_CIRCUIT_DIRTINESS (30*24*60*60)
    2987             : 
    2988             : /** Lowest allowable value for CircuitStreamTimeout; if this is too low, Tor
    2989             :  * will generate too many circuits and potentially overload the network. */
    2990             : #define MIN_CIRCUIT_STREAM_TIMEOUT 10
    2991             : 
    2992             : /** Lowest recommended value for CircuitBuildTimeout; if it is set too low
    2993             :  * and LearnCircuitBuildTimeout is off, the failure rate for circuit
    2994             :  * construction may be very high.  In that case, if it is set below this
    2995             :  * threshold emit a warning.
    2996             :  * */
    2997             : #define RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT (10)
    2998             : 
    2999             : /**
    3000             :  * Validate <b>new_options</b>.  If it is valid, and it is a reasonable
    3001             :  * replacement for <b>old_options</b>, replace the previous value of the
    3002             :  * global options, and return return SETOPT_OK.
    3003             :  *
    3004             :  * If it is not valid, then free <b>new_options</b>, set *<b>msg_out</b> to a
    3005             :  * newly allocated error message, and return an error code.
    3006             :  */
    3007             : static setopt_err_t
    3008         232 : options_validate_and_set(const or_options_t *old_options,
    3009             :                          or_options_t *new_options,
    3010             :                          char **msg_out)
    3011             : {
    3012         232 :   setopt_err_t rv;
    3013         232 :   validation_status_t vs;
    3014             : 
    3015         232 :   in_option_validation = 1;
    3016         232 :   vs = config_validate(get_options_mgr(), old_options, new_options, msg_out);
    3017             : 
    3018         232 :   if (vs == VSTAT_TRANSITION_ERR) {
    3019           1 :     rv = SETOPT_ERR_TRANSITION;
    3020           1 :     goto err;
    3021         231 :   } else if (vs < 0) {
    3022          24 :     rv = SETOPT_ERR_PARSE;
    3023          24 :     goto err;
    3024             :   }
    3025         207 :   in_option_validation = 0;
    3026             : 
    3027         207 :   if (set_options(new_options, msg_out)) {
    3028           1 :     rv = SETOPT_ERR_SETTING;
    3029           1 :     goto err;
    3030             :   }
    3031             : 
    3032             :   rv = SETOPT_OK;
    3033             :   new_options = NULL; /* prevent free */
    3034         232 :  err:
    3035         232 :   in_option_validation = 0;
    3036         232 :   tor_assert(new_options == NULL || rv != SETOPT_OK);
    3037         232 :   or_options_free(new_options);
    3038         232 :   return rv;
    3039             : }
    3040             : 
    3041             : #ifdef TOR_UNIT_TESTS
    3042             : /**
    3043             :  * Return 0 if every setting in <b>options</b> is reasonable, is a
    3044             :  * permissible transition from <b>old_options</b>, and none of the
    3045             :  * testing-only settings differ from <b>default_options</b> unless in
    3046             :  * testing mode.  Else return -1.  Should have no side effects, except for
    3047             :  * normalizing the contents of <b>options</b>.
    3048             :  *
    3049             :  * On error, tor_strdup an error explanation into *<b>msg</b>.
    3050             :  */
    3051             : int
    3052         349 : options_validate(const or_options_t *old_options, or_options_t *options,
    3053             :                  char **msg)
    3054             : {
    3055         349 :   validation_status_t vs;
    3056         349 :   vs = config_validate(get_options_mgr(), old_options, options, msg);
    3057         349 :   return vs < 0 ? -1 : 0;
    3058             : }
    3059             : #endif /* defined(TOR_UNIT_TESTS) */
    3060             : 
    3061             : #define REJECT(arg) \
    3062             :   STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
    3063             : #if defined(__GNUC__) && __GNUC__ <= 3
    3064             : #define COMPLAIN(args...) \
    3065             :   STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END
    3066             : #else
    3067             : #define COMPLAIN(args, ...)                                     \
    3068             :   STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END
    3069             : #endif /* defined(__GNUC__) && __GNUC__ <= 3 */
    3070             : 
    3071             : /** Log a warning message iff <b>filepath</b> is not absolute.
    3072             :  * Warning message must contain option name <b>option</b> and
    3073             :  * an absolute path that <b>filepath</b> will resolve to.
    3074             :  *
    3075             :  * In case <b>filepath</b> is absolute, do nothing.
    3076             :  *
    3077             :  * Return 1 if there were relative paths; 0 otherwise.
    3078             :  */
    3079             : static int
    3080        1214 : warn_if_option_path_is_relative(const char *option,
    3081             :                                 const char *filepath)
    3082             : {
    3083        1214 :   if (filepath && path_is_relative(filepath)) {
    3084           4 :     char *abs_path = make_path_absolute(filepath);
    3085           4 :     COMPLAIN("Path for %s (%s) is relative and will resolve to %s."
    3086             :              " Is this what you wanted?", option, filepath, abs_path);
    3087           4 :     tor_free(abs_path);
    3088           4 :     return 1;
    3089             :   }
    3090             :   return 0;
    3091             : }
    3092             : 
    3093             : /** Scan <b>options</b> for occurrences of relative file/directory
    3094             :  * paths and log a warning whenever one is found.
    3095             :  *
    3096             :  * Return 1 if there were relative paths; 0 otherwise.
    3097             :  */
    3098             : static int
    3099         563 : warn_about_relative_paths(const or_options_t *options)
    3100             : {
    3101         563 :   tor_assert(options);
    3102         563 :   int n = 0;
    3103         563 :   const config_mgr_t *mgr = get_options_mgr();
    3104             : 
    3105         563 :   smartlist_t *vars = config_mgr_list_vars(mgr);
    3106      242090 :   SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, cv) {
    3107      241527 :     config_line_t *line;
    3108      241527 :     if (cv->member.type != CONFIG_TYPE_FILENAME)
    3109      233082 :       continue;
    3110        8445 :     const char *name = cv->member.name;
    3111        8445 :     line = config_get_assigned_option(mgr, options, name, 0);
    3112        8445 :     if (line)
    3113        1204 :       n += warn_if_option_path_is_relative(name, line->value);
    3114        8445 :     config_free_lines(line);
    3115      241527 :   } SMARTLIST_FOREACH_END(cv);
    3116         563 :   smartlist_free(vars);
    3117             : 
    3118         584 :   for (config_line_t *hs_line = options->RendConfigLines; hs_line;
    3119          21 :        hs_line = hs_line->next) {
    3120          21 :     if (!strcasecmp(hs_line->key, "HiddenServiceDir"))
    3121          10 :       n += warn_if_option_path_is_relative("HiddenServiceDir",hs_line->value);
    3122             :   }
    3123         563 :   return n != 0;
    3124             : }
    3125             : 
    3126             : /* Validate options related to the scheduler. From the Schedulers list, the
    3127             :  * SchedulerTypes_ list is created with int values so once we select the
    3128             :  * scheduler, which can happen anytime at runtime, we don't have to parse
    3129             :  * strings and thus be quick.
    3130             :  *
    3131             :  * Return 0 on success else -1 and msg is set with an error message. */
    3132             : static int
    3133         386 : options_validate_scheduler(or_options_t *options, char **msg)
    3134             : {
    3135         386 :   tor_assert(options);
    3136         386 :   tor_assert(msg);
    3137             : 
    3138         386 :   if (!options->Schedulers || smartlist_len(options->Schedulers) == 0) {
    3139           0 :     REJECT("Empty Schedulers list. Either remove the option so the defaults "
    3140             :            "can be used or set at least one value.");
    3141             :   }
    3142             :   /* Ok, we do have scheduler types, validate them. */
    3143         386 :   if (options->SchedulerTypes_) {
    3144          12 :     SMARTLIST_FOREACH(options->SchedulerTypes_, int *, iptr, tor_free(iptr));
    3145           3 :     smartlist_free(options->SchedulerTypes_);
    3146             :   }
    3147         386 :   options->SchedulerTypes_ = smartlist_new();
    3148        1544 :   SMARTLIST_FOREACH_BEGIN(options->Schedulers, const char *, type) {
    3149        1158 :     int *sched_type;
    3150        1158 :     if (!strcasecmp("KISTLite", type)) {
    3151         386 :       sched_type = tor_malloc_zero(sizeof(int));
    3152         386 :       *sched_type = SCHEDULER_KIST_LITE;
    3153         386 :       smartlist_add(options->SchedulerTypes_, sched_type);
    3154         772 :     } else if (!strcasecmp("KIST", type)) {
    3155         386 :       sched_type = tor_malloc_zero(sizeof(int));
    3156         386 :       *sched_type = SCHEDULER_KIST;
    3157         386 :       smartlist_add(options->SchedulerTypes_, sched_type);
    3158         386 :     } else if (!strcasecmp("Vanilla", type)) {
    3159         386 :       sched_type = tor_malloc_zero(sizeof(int));
    3160         386 :       *sched_type = SCHEDULER_VANILLA;
    3161         386 :       smartlist_add(options->SchedulerTypes_, sched_type);
    3162             :     } else {
    3163           0 :       tor_asprintf(msg, "Unknown type %s in option Schedulers. "
    3164             :                         "Possible values are KIST, KISTLite and Vanilla.",
    3165             :                    escaped(type));
    3166           0 :       return -1;
    3167             :     }
    3168        1158 :   } SMARTLIST_FOREACH_END(type);
    3169             : 
    3170         386 :   if (options->KISTSockBufSizeFactor < 0) {
    3171           0 :     REJECT("KISTSockBufSizeFactor must be at least 0");
    3172             :   }
    3173             : 
    3174             :   /* Don't need to validate that the Interval is less than anything because
    3175             :    * zero is valid and all negative values are valid. */
    3176         386 :   if (options->KISTSchedRunInterval > KIST_SCHED_RUN_INTERVAL_MAX) {
    3177           0 :     tor_asprintf(msg, "KISTSchedRunInterval must not be more than %d (ms)",
    3178             :                  KIST_SCHED_RUN_INTERVAL_MAX);
    3179           0 :     return -1;
    3180             :   }
    3181             : 
    3182             :   return 0;
    3183             : }
    3184             : 
    3185             : /* Validate options related to single onion services.
    3186             :  * Modifies some options that are incompatible with single onion services.
    3187             :  * On failure returns -1, and sets *msg to an error string.
    3188             :  * Returns 0 on success. */
    3189             : STATIC int
    3190         513 : options_validate_single_onion(or_options_t *options, char **msg)
    3191             : {
    3192             :   /* The two single onion service options must have matching values. */
    3193         513 :   if (options->HiddenServiceSingleHopMode &&
    3194           6 :       !options->HiddenServiceNonAnonymousMode) {
    3195           2 :     REJECT("HiddenServiceSingleHopMode does not provide any server anonymity. "
    3196             :            "It must be used with HiddenServiceNonAnonymousMode set to 1.");
    3197             :   }
    3198         511 :   if (options->HiddenServiceNonAnonymousMode &&
    3199             :       !options->HiddenServiceSingleHopMode) {
    3200           2 :     REJECT("HiddenServiceNonAnonymousMode does not provide any server "
    3201             :            "anonymity. It must be used with HiddenServiceSingleHopMode set to "
    3202             :            "1.");
    3203             :   }
    3204             : 
    3205             :   /* Now that we've checked that the two options are consistent, we can safely
    3206             :    * call the hs_service_* functions that abstract these options. */
    3207             : 
    3208             :   /* If you run an anonymous client with an active Single Onion service, the
    3209             :    * client loses anonymity. */
    3210         509 :   const int client_port_set = (options->SocksPort_set ||
    3211             :                                options->TransPort_set ||
    3212             :                                options->NATDPort_set ||
    3213         509 :                                options->DNSPort_set ||
    3214             :                                options->HTTPTunnelPort_set);
    3215         509 :   if (hs_service_non_anonymous_mode_enabled(options) && client_port_set) {
    3216           1 :     REJECT("HiddenServiceNonAnonymousMode is incompatible with using Tor as "
    3217             :            "an anonymous client. Please set Socks/Trans/NATD/DNSPort to 0, or "
    3218             :            "revert HiddenServiceNonAnonymousMode to 0.");
    3219             :   }
    3220             : 
    3221         508 :   if (hs_service_allow_non_anonymous_connection(options)
    3222           3 :       && options->UseEntryGuards) {
    3223             :     /* Single Onion services only use entry guards when uploading descriptors;
    3224             :      * all other connections are one-hop. Further, Single Onions causes the
    3225             :      * hidden service code to do things which break the path bias
    3226             :      * detector, and it's far easier to turn off entry guards (and
    3227             :      * thus the path bias detector with it) than to figure out how to
    3228             :      * make path bias compatible with single onions.
    3229             :      */
    3230           3 :     log_notice(LD_CONFIG,
    3231             :                "HiddenServiceSingleHopMode is enabled; disabling "
    3232             :                "UseEntryGuards.");
    3233           3 :     options->UseEntryGuards = 0;
    3234             :   }
    3235             : 
    3236             :   return 0;
    3237             : }
    3238             : 
    3239             : /**
    3240             :  * Legacy validation/normalization callback for or_options_t.  See
    3241             :  * legacy_validate_fn_t for more information.
    3242             :  */
    3243             : static int
    3244         576 : options_validate_cb(const void *old_options_, void *options_, char **msg)
    3245             : {
    3246         576 :   if (old_options_)
    3247           8 :     CHECK_OPTIONS_MAGIC(old_options_);
    3248         576 :   CHECK_OPTIONS_MAGIC(options_);
    3249         576 :   const or_options_t *old_options = old_options_;
    3250         576 :   or_options_t *options = options_;
    3251             : 
    3252         576 :   config_line_t *cl;
    3253         576 :   int n_ports=0;
    3254         576 :   int world_writable_control_socket=0;
    3255             : 
    3256         576 :   tor_assert(msg);
    3257         576 :   *msg = NULL;
    3258             : 
    3259         576 :   if (parse_ports(options, 1, msg, &n_ports,
    3260             :                   &world_writable_control_socket) < 0)
    3261             :     return -1;
    3262             : 
    3263             : #ifndef HAVE_SYS_UN_H
    3264             :   if (options->ControlSocket || options->ControlSocketsGroupWritable) {
    3265             :     *msg = tor_strdup("Unix domain sockets (ControlSocket) not supported "
    3266             :                       "on this OS/with this build.");
    3267             :     return -1;
    3268             :   }
    3269             : #else /* defined(HAVE_SYS_UN_H) */
    3270         566 :   if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
    3271           1 :     *msg = tor_strdup("Setting ControlSocketsGroupWritable without setting "
    3272             :                       "a ControlSocket makes no sense.");
    3273           1 :     return -1;
    3274             :   }
    3275             : #endif /* !defined(HAVE_SYS_UN_H) */
    3276             : 
    3277             :   /* Set UseEntryGuards from the configured value, before we check it below.
    3278             :    * We change UseEntryGuards when it's incompatible with other options,
    3279             :    * but leave UseEntryGuards_option with the original value.
    3280             :    * Always use the value of UseEntryGuards, not UseEntryGuards_option. */
    3281         565 :   options->UseEntryGuards = options->UseEntryGuards_option;
    3282             : 
    3283         565 :   if (options_validate_relay_os(old_options, options, msg) < 0)
    3284             :     return -1;
    3285             : 
    3286             :   /* 31851: OutboundBindAddressExit is unused in client mode */
    3287         565 :   if (parse_outbound_addresses(options, 1, msg) < 0)
    3288             :     return -1;
    3289             : 
    3290         564 :   if (validate_data_directories(options)<0)
    3291           1 :     REJECT("Invalid DataDirectory");
    3292             : 
    3293             :   /* need to check for relative paths after we populate
    3294             :    * options->DataDirectory (just above). */
    3295         563 :   if (warn_about_relative_paths(options) && options->RunAsDaemon) {
    3296           1 :     REJECT("You have specified at least one relative path (see above) "
    3297             :            "with the RunAsDaemon option. RunAsDaemon is not compatible "
    3298             :            "with relative paths.");
    3299             :   }
    3300             : 
    3301         562 :   if (options_validate_relay_info(old_options, options, msg) < 0)
    3302             :     return -1;
    3303             : 
    3304             :   /* 31851: this function is currently a no-op in client mode */
    3305         558 :   check_network_configuration(server_mode(options));
    3306             : 
    3307             :   /* Validate the tor_log(s) */
    3308         558 :   if (options_init_logs(old_options, options, 1)<0)
    3309           1 :     REJECT("Failed to validate Log options. See logs for details.");
    3310             : 
    3311             :   /* XXXX require that the only port not be DirPort? */
    3312             :   /* XXXX require that at least one port be listened-upon. */
    3313         557 :   if (n_ports == 0 && !options->RendConfigLines)
    3314           5 :     log_warn(LD_CONFIG,
    3315             :         "SocksPort, TransPort, NATDPort, DNSPort, and ORPort are all "
    3316             :         "undefined, and there aren't any hidden services configured.  "
    3317             :         "Tor will still run, but probably won't do anything.");
    3318             : 
    3319         557 :   options->TransProxyType_parsed = TPT_DEFAULT;
    3320             : #ifdef USE_TRANSPARENT
    3321         557 :   if (options->TransProxyType) {
    3322         557 :     if (!strcasecmp(options->TransProxyType, "default")) {
    3323             :       options->TransProxyType_parsed = TPT_DEFAULT;
    3324           5 :     } else if (!strcasecmp(options->TransProxyType, "pf-divert")) {
    3325             : #if !defined(OpenBSD) && !defined(DARWIN)
    3326             :       /* Later versions of OS X have pf */
    3327           1 :       REJECT("pf-divert is a OpenBSD-specific "
    3328             :              "and OS X/Darwin-specific feature.");
    3329             : #else
    3330             :       options->TransProxyType_parsed = TPT_PF_DIVERT;
    3331             : #endif /* !defined(OpenBSD) && !defined(DARWIN) */
    3332           4 :     } else if (!strcasecmp(options->TransProxyType, "tproxy")) {
    3333             : #if !defined(__linux__)
    3334             :       REJECT("TPROXY is a Linux-specific feature.");
    3335             : #else
    3336           2 :       options->TransProxyType_parsed = TPT_TPROXY;
    3337             : #endif
    3338           2 :     } else if (!strcasecmp(options->TransProxyType, "ipfw")) {
    3339             : #ifndef KERNEL_MAY_SUPPORT_IPFW
    3340             :       /* Earlier versions of OS X have ipfw */
    3341           1 :       REJECT("ipfw is a FreeBSD-specific "
    3342             :              "and OS X/Darwin-specific feature.");
    3343             : #else
    3344             :       options->TransProxyType_parsed = TPT_IPFW;
    3345             : #endif /* !defined(KERNEL_MAY_SUPPORT_IPFW) */
    3346             :     } else {
    3347           1 :       REJECT("Unrecognized value for TransProxyType");
    3348             :     }
    3349             : 
    3350         554 :     if (strcasecmp(options->TransProxyType, "default") &&
    3351           2 :         !options->TransPort_set) {
    3352           1 :       REJECT("Cannot use TransProxyType without any valid TransPort.");
    3353             :     }
    3354             :   }
    3355             : #else /* !defined(USE_TRANSPARENT) */
    3356             :   if (options->TransPort_set)
    3357             :     REJECT("TransPort is disabled in this build.");
    3358             : #endif /* defined(USE_TRANSPARENT) */
    3359             : 
    3360         553 :   if (options->TokenBucketRefillInterval <= 0
    3361         553 :       || options->TokenBucketRefillInterval > 1000) {
    3362           2 :     REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
    3363             :   }
    3364             : 
    3365         551 :   if (options->AssumeReachable && options->AssumeReachableIPv6 == 0) {
    3366           0 :     REJECT("Cannot set AssumeReachable 1 and AssumeReachableIPv6 0.");
    3367             :   }
    3368             : 
    3369         551 :   if (options->ExcludeExitNodes || options->ExcludeNodes) {
    3370           8 :     options->ExcludeExitNodesUnion_ = routerset_new();
    3371           8 :     routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes);
    3372           8 :     routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeNodes);
    3373             :   }
    3374             : 
    3375         551 :   if (options->NodeFamilies) {
    3376           6 :     options->NodeFamilySets = smartlist_new();
    3377          14 :     for (cl = options->NodeFamilies; cl; cl = cl->next) {
    3378           8 :       routerset_t *rs = routerset_new();
    3379           8 :       if (routerset_parse(rs, cl->value, cl->key) == 0) {
    3380           6 :         smartlist_add(options->NodeFamilySets, rs);
    3381             :       } else {
    3382           8 :         routerset_free(rs);
    3383             :       }
    3384             :     }
    3385             :   }
    3386             : 
    3387         551 :   if (options->ExcludeNodes && options->StrictNodes) {
    3388           4 :     COMPLAIN("You have asked to exclude certain relays from all positions "
    3389             :              "in your circuits. Expect hidden services and other Tor "
    3390             :              "features to be broken in unpredictable ways.");
    3391             :   }
    3392             : 
    3393         551 :   if (options_validate_dirauth_mode(old_options, options, msg) < 0)
    3394             :     return -1;
    3395             : 
    3396         541 :   if (options->FetchDirInfoExtraEarly && !options->FetchDirInfoEarly)
    3397           1 :     REJECT("FetchDirInfoExtraEarly requires that you also set "
    3398             :            "FetchDirInfoEarly");
    3399             : 
    3400         540 :   if (options->ConnLimit <= 0) {
    3401           1 :     tor_asprintf(msg,
    3402             :         "ConnLimit must be greater than 0, but was set to %d",
    3403             :         options->ConnLimit);
    3404           1 :     return -1;
    3405             :   }
    3406             : 
    3407         539 :   if (options->PathsNeededToBuildCircuits >= 0.0) {
    3408           3 :     if (options->PathsNeededToBuildCircuits < 0.25) {
    3409           1 :       log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too low. Increasing "
    3410             :                "to 0.25");
    3411           1 :       options->PathsNeededToBuildCircuits = 0.25;
    3412           2 :     } else if (options->PathsNeededToBuildCircuits > 0.95) {
    3413           1 :       log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too high. Decreasing "
    3414             :                "to 0.95");
    3415           1 :       options->PathsNeededToBuildCircuits = 0.95;
    3416             :     }
    3417             :   }
    3418             : 
    3419         539 :   if (options->MaxClientCircuitsPending <= 0 ||
    3420             :       options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) {
    3421           2 :     tor_asprintf(msg,
    3422             :                  "MaxClientCircuitsPending must be between 1 and %d, but "
    3423             :                  "was set to %d", MAX_MAX_CLIENT_CIRCUITS_PENDING,
    3424             :                  options->MaxClientCircuitsPending);
    3425           2 :     return -1;
    3426             :   }
    3427             : 
    3428         537 :   if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0)
    3429             :     return -1;
    3430             : 
    3431         536 :   if (validate_ports_csv(options->LongLivedPorts, "LongLivedPorts", msg) < 0)
    3432             :     return -1;
    3433             : 
    3434         535 :   if (validate_ports_csv(options->RejectPlaintextPorts,
    3435             :                          "RejectPlaintextPorts", msg) < 0)
    3436             :     return -1;
    3437             : 
    3438         534 :   if (validate_ports_csv(options->WarnPlaintextPorts,
    3439             :                          "WarnPlaintextPorts", msg) < 0)
    3440             :     return -1;
    3441             : 
    3442         533 :   if (options->FascistFirewall && !options->ReachableAddresses) {
    3443           4 :     if (options->FirewallPorts && smartlist_len(options->FirewallPorts)) {
    3444             :       /* We already have firewall ports set, so migrate them to
    3445             :        * ReachableAddresses, which will set ReachableORAddresses and
    3446             :        * ReachableDirAddresses if they aren't set explicitly. */
    3447           1 :       smartlist_t *instead = smartlist_new();
    3448           1 :       config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
    3449           1 :       new_line->key = tor_strdup("ReachableAddresses");
    3450             :       /* If we're configured with the old format, we need to prepend some
    3451             :        * open ports. */
    3452           2 :       SMARTLIST_FOREACH(options->FirewallPorts, const char *, portno,
    3453             :       {
    3454             :         int p = atoi(portno);
    3455             :         if (p<0) continue;
    3456             :         smartlist_add_asprintf(instead, "*:%d", p);
    3457             :       });
    3458           1 :       new_line->value = smartlist_join_strings(instead,",",0,NULL);
    3459             :       /* These have been deprecated since 0.1.1.5-alpha-cvs */
    3460           1 :       log_notice(LD_CONFIG,
    3461             :           "Converting FascistFirewall and FirewallPorts "
    3462             :           "config options to new format: \"ReachableAddresses %s\"",
    3463             :           new_line->value);
    3464           1 :       options->ReachableAddresses = new_line;
    3465           2 :       SMARTLIST_FOREACH(instead, char *, cp, tor_free(cp));
    3466           1 :       smartlist_free(instead);
    3467             :     } else {
    3468             :       /* We do not have FirewallPorts set, so add 80 to
    3469             :        * ReachableDirAddresses, and 443 to ReachableORAddresses. */
    3470           2 :       if (!options->ReachableDirAddresses) {
    3471           1 :         config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
    3472           1 :         new_line->key = tor_strdup("ReachableDirAddresses");
    3473           1 :         new_line->value = tor_strdup("*:80");
    3474           1 :         options->ReachableDirAddresses = new_line;
    3475           1 :         log_notice(LD_CONFIG, "Converting FascistFirewall config option "
    3476             :             "to new format: \"ReachableDirAddresses *:80\"");
    3477             :       }
    3478           2 :       if (!options->ReachableORAddresses) {
    3479           1 :         config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
    3480           1 :         new_line->key = tor_strdup("ReachableORAddresses");
    3481           1 :         new_line->value = tor_strdup("*:443");
    3482           1 :         options->ReachableORAddresses = new_line;
    3483           1 :         log_notice(LD_CONFIG, "Converting FascistFirewall config option "
    3484             :             "to new format: \"ReachableORAddresses *:443\"");
    3485             :       }
    3486             :     }
    3487             :   }
    3488             : 
    3489         533 :   if ((options->ReachableAddresses ||
    3490         526 :        options->ReachableORAddresses ||
    3491         523 :        options->ReachableDirAddresses ||
    3492         535 :        options->ClientUseIPv4 == 0) &&
    3493          13 :       server_mode(options))
    3494           4 :     REJECT("Servers must be able to freely connect to the rest "
    3495             :            "of the Internet, so they must not set Reachable*Addresses "
    3496             :            "or FascistFirewall or FirewallPorts or ClientUseIPv4 0.");
    3497             : 
    3498         543 :   if (options->UseBridges &&
    3499          14 :       server_mode(options))
    3500           1 :     REJECT("Servers must be able to freely connect to the rest "
    3501             :            "of the Internet, so they must not set UseBridges.");
    3502             : 
    3503             :   /* If both of these are set, we'll end up with funny behavior where we
    3504             :    * demand enough entrynodes be up and running else we won't build
    3505             :    * circuits, yet we never actually use them. */
    3506         528 :   if (options->UseBridges && options->EntryNodes)
    3507           2 :     REJECT("You cannot set both UseBridges and EntryNodes.");
    3508             : 
    3509             :   /* If we have UseBridges as 1 and UseEntryGuards as 0, we end up bypassing
    3510             :    * the use of bridges */
    3511         526 :   if (options->UseBridges && !options->UseEntryGuards)
    3512           1 :     REJECT("Setting UseBridges requires also setting UseEntryGuards.");
    3513             : 
    3514        1050 :   options->MaxMemInQueues =
    3515         525 :     compute_real_max_mem_in_queues(options->MaxMemInQueues_raw,
    3516         525 :                                    server_mode(options));
    3517         525 :   options->MaxMemInQueues_low_threshold = (options->MaxMemInQueues / 4) * 3;
    3518             : 
    3519         525 :   if (!options->SafeLogging ||
    3520         525 :       !strcasecmp(options->SafeLogging, "0")) {
    3521           5 :     options->SafeLogging_ = SAFELOG_SCRUB_NONE;
    3522         520 :   } else if (!strcasecmp(options->SafeLogging, "relay")) {
    3523           1 :     options->SafeLogging_ = SAFELOG_SCRUB_RELAY;
    3524         519 :   } else if (!strcasecmp(options->SafeLogging, "1")) {
    3525         518 :     options->SafeLogging_ = SAFELOG_SCRUB_ALL;
    3526             :   } else {
    3527           1 :     tor_asprintf(msg,
    3528             :                      "Unrecognized value '%s' in SafeLogging",
    3529             :                      escaped(options->SafeLogging));
    3530           1 :     return -1;
    3531             :   }
    3532             : 
    3533         524 :   if (options_validate_publish_server(old_options, options, msg) < 0)
    3534             :     return -1;
    3535             : 
    3536         518 :   if (options_validate_relay_padding(old_options, options, msg) < 0)
    3537             :     return -1;
    3538             : 
    3539        1026 :   const int min_rendpostperiod =
    3540         513 :     options->TestingTorNetwork ?
    3541         513 :     MIN_REND_POST_PERIOD_TESTING : MIN_REND_POST_PERIOD;
    3542         513 :   if (options->RendPostPeriod < min_rendpostperiod) {
    3543           1 :     log_warn(LD_CONFIG, "RendPostPeriod option is too short; "
    3544             :              "raising to %d seconds.", min_rendpostperiod);
    3545           1 :     options->RendPostPeriod = min_rendpostperiod;
    3546             :   }
    3547             : 
    3548         513 :   if (options->RendPostPeriod > MAX_DIR_PERIOD) {
    3549           1 :     log_warn(LD_CONFIG, "RendPostPeriod is too large; clipping to %ds.",
    3550             :              MAX_DIR_PERIOD);
    3551           1 :     options->RendPostPeriod = MAX_DIR_PERIOD;
    3552             :   }
    3553             : 
    3554             :   /* Check the Single Onion Service options */
    3555         513 :   if (options_validate_single_onion(options, msg) < 0)
    3556             :     return -1;
    3557             : 
    3558         508 :   if (options->CircuitsAvailableTimeout > MAX_CIRCS_AVAILABLE_TIME) {
    3559             :     // options_t is immutable for new code (the above code is older),
    3560             :     // so just make the user fix the value themselves rather than
    3561             :     // silently keep a shadow value lower than what they asked for.
    3562           0 :     REJECT("CircuitsAvailableTimeout is too large. Max is 24 hours.");
    3563             :   }
    3564             : 
    3565         508 :   if (options->EntryNodes && !options->UseEntryGuards) {
    3566           1 :     REJECT("If EntryNodes is set, UseEntryGuards must be enabled.");
    3567             :   }
    3568             : 
    3569         507 :   if (!(options->UseEntryGuards) &&
    3570          65 :       (options->RendConfigLines != NULL) &&
    3571           2 :       !hs_service_allow_non_anonymous_connection(options)) {
    3572           1 :     log_warn(LD_CONFIG,
    3573             :              "UseEntryGuards is disabled, but you have configured one or more "
    3574             :              "hidden services on this Tor instance.  Your hidden services "
    3575             :              "will be very easy to locate using a well-known attack -- see "
    3576             :              "https://freehaven.net/anonbib/#hs-attack06 for details.");
    3577             :   }
    3578             : 
    3579         507 :   if (options->NumPrimaryGuards && options->NumEntryGuards &&
    3580             :       options->NumEntryGuards > options->NumPrimaryGuards) {
    3581           0 :     REJECT("NumEntryGuards must not be greater than NumPrimaryGuards.");
    3582             :   }
    3583             : 
    3584         520 :   if (options->EntryNodes &&
    3585          16 :       routerset_is_list(options->EntryNodes) &&
    3586           3 :       (routerset_len(options->EntryNodes) == 1) &&
    3587           0 :       (options->RendConfigLines != NULL)) {
    3588           0 :     tor_asprintf(msg,
    3589             :              "You have one single EntryNodes and at least one hidden service "
    3590             :              "configured. This is bad because it's very easy to locate your "
    3591             :              "entry guard which can then lead to the deanonymization of your "
    3592             :              "hidden service -- for more details, see "
    3593             :              "https://bugs.torproject.org/tpo/core/tor/14917. "
    3594             :              "For this reason, the use of one EntryNodes with an hidden "
    3595             :              "service is prohibited until a better solution is found.");
    3596           0 :     return -1;
    3597             :   }
    3598             : 
    3599             :   /* Inform the hidden service operator that pinning EntryNodes can possibly
    3600             :    * be harmful for the service anonymity. */
    3601         520 :   if (options->EntryNodes &&
    3602          13 :       routerset_is_list(options->EntryNodes) &&
    3603           3 :       (options->RendConfigLines != NULL)) {
    3604           0 :     log_warn(LD_CONFIG,
    3605             :              "EntryNodes is set with multiple entries and at least one "
    3606             :              "hidden service is configured. Pinning entry nodes can possibly "
    3607             :              "be harmful to the service anonymity. Because of this, we "
    3608             :              "recommend you either don't do that or make sure you know what "
    3609             :              "you are doing. For more details, please look at "
    3610             :              "https://bugs.torproject.org/tpo/core/tor/21155.");
    3611             :   }
    3612             : 
    3613             :   /* Single Onion Services: non-anonymous hidden services */
    3614         507 :   if (hs_service_non_anonymous_mode_enabled(options)) {
    3615           3 :     log_warn(LD_CONFIG,
    3616             :              "HiddenServiceNonAnonymousMode is set. Every hidden service on "
    3617             :              "this tor instance is NON-ANONYMOUS. If "
    3618             :              "the HiddenServiceNonAnonymousMode option is changed, Tor will "
    3619             :              "refuse to launch hidden services from the same directories, to "
    3620             :              "protect your anonymity against config errors. This setting is "
    3621             :              "for experimental use only.");
    3622             :   }
    3623             : 
    3624         507 :   if (!options->LearnCircuitBuildTimeout && options->CircuitBuildTimeout &&
    3625             :       options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) {
    3626           1 :     log_warn(LD_CONFIG,
    3627             :         "CircuitBuildTimeout is shorter (%d seconds) than the recommended "
    3628             :         "minimum (%d seconds), and LearnCircuitBuildTimeout is disabled.  "
    3629             :         "If tor isn't working, raise this value or enable "
    3630             :         "LearnCircuitBuildTimeout.",
    3631             :         options->CircuitBuildTimeout,
    3632             :         RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT );
    3633         506 :   } else if (!options->LearnCircuitBuildTimeout &&
    3634           0 :              !options->CircuitBuildTimeout) {
    3635           0 :     int severity = LOG_NOTICE;
    3636             :     /* Be a little quieter if we've deliberately disabled
    3637             :      * LearnCircuitBuildTimeout. */
    3638           0 :     if (circuit_build_times_disabled_(options, 1)) {
    3639           0 :       severity = LOG_INFO;
    3640             :     }
    3641           0 :     log_fn(severity, LD_CONFIG, "You disabled LearnCircuitBuildTimeout, but "
    3642             :            "didn't specify a CircuitBuildTimeout. I'll pick a plausible "
    3643             :            "default.");
    3644             :   }
    3645             : 
    3646         507 :   if (options->DormantClientTimeout < 10*60 && !options->TestingTorNetwork) {
    3647           0 :     REJECT("DormantClientTimeout is too low. It must be at least 10 minutes.");
    3648             :   }
    3649             : 
    3650         507 :   if (options->PathBiasNoticeRate > 1.0) {
    3651           1 :     tor_asprintf(msg,
    3652             :               "PathBiasNoticeRate is too high. "
    3653             :               "It must be between 0 and 1.0");
    3654           1 :     return -1;
    3655             :   }
    3656         506 :   if (options->PathBiasWarnRate > 1.0) {
    3657           1 :     tor_asprintf(msg,
    3658             :               "PathBiasWarnRate is too high. "
    3659             :               "It must be between 0 and 1.0");
    3660           1 :     return -1;
    3661             :   }
    3662         505 :   if (options->PathBiasExtremeRate > 1.0) {
    3663           1 :     tor_asprintf(msg,
    3664             :               "PathBiasExtremeRate is too high. "
    3665             :               "It must be between 0 and 1.0");
    3666           1 :     return -1;
    3667             :   }
    3668         504 :   if (options->PathBiasNoticeUseRate > 1.0) {
    3669           1 :     tor_asprintf(msg,
    3670             :               "PathBiasNoticeUseRate is too high. "
    3671             :               "It must be between 0 and 1.0");
    3672           1 :     return -1;
    3673             :   }
    3674         503 :   if (options->PathBiasExtremeUseRate > 1.0) {
    3675           1 :     tor_asprintf(msg,
    3676             :               "PathBiasExtremeUseRate is too high. "
    3677             :               "It must be between 0 and 1.0");
    3678           1 :     return -1;
    3679             :   }
    3680             : 
    3681         502 :   if (options->MaxCircuitDirtiness < MIN_MAX_CIRCUIT_DIRTINESS) {
    3682           0 :     log_warn(LD_CONFIG, "MaxCircuitDirtiness option is too short; "
    3683             :              "raising to %d seconds.", MIN_MAX_CIRCUIT_DIRTINESS);
    3684           0 :     options->MaxCircuitDirtiness = MIN_MAX_CIRCUIT_DIRTINESS;
    3685             :   }
    3686             : 
    3687         502 :   if (options->MaxCircuitDirtiness > MAX_MAX_CIRCUIT_DIRTINESS) {
    3688           1 :     log_warn(LD_CONFIG, "MaxCircuitDirtiness option is too high; "
    3689             :              "setting to %d days.", MAX_MAX_CIRCUIT_DIRTINESS/86400);
    3690           1 :     options->MaxCircuitDirtiness = MAX_MAX_CIRCUIT_DIRTINESS;
    3691             :   }
    3692             : 
    3693         502 :   if (options->CircuitStreamTimeout &&
    3694             :       options->CircuitStreamTimeout < MIN_CIRCUIT_STREAM_TIMEOUT) {
    3695           1 :     log_warn(LD_CONFIG, "CircuitStreamTimeout option is too short; "
    3696             :              "raising to %d seconds.", MIN_CIRCUIT_STREAM_TIMEOUT);
    3697           1 :     options->CircuitStreamTimeout = MIN_CIRCUIT_STREAM_TIMEOUT;
    3698             :   }
    3699             : 
    3700         502 :   if (options->HeartbeatPeriod &&
    3701           1 :       options->HeartbeatPeriod < MIN_HEARTBEAT_PERIOD &&
    3702           1 :       !options->TestingTorNetwork) {
    3703           1 :     log_warn(LD_CONFIG, "HeartbeatPeriod option is too short; "
    3704             :              "raising to %d seconds.", MIN_HEARTBEAT_PERIOD);
    3705           1 :     options->HeartbeatPeriod = MIN_HEARTBEAT_PERIOD;
    3706             :   }
    3707             : 
    3708         502 :   if (options->KeepalivePeriod < 1)
    3709           0 :     REJECT("KeepalivePeriod option must be positive.");
    3710             : 
    3711         502 :   if (config_ensure_bandwidth_cap(&options->BandwidthRate,
    3712             :                            "BandwidthRate", msg) < 0)
    3713             :     return -1;
    3714         499 :   if (config_ensure_bandwidth_cap(&options->BandwidthBurst,
    3715             :                            "BandwidthBurst", msg) < 0)
    3716             :     return -1;
    3717             : 
    3718         496 :   if (options_validate_relay_bandwidth(old_options, options, msg) < 0)
    3719             :     return -1;
    3720             : 
    3721         477 :   if (options->BandwidthRate > options->BandwidthBurst)
    3722           1 :     REJECT("BandwidthBurst must be at least equal to BandwidthRate.");
    3723             : 
    3724         476 :   if (options_validate_relay_accounting(old_options, options, msg) < 0)
    3725             :     return -1;
    3726             : 
    3727         474 :   if (options_validate_relay_mode(old_options, options, msg) < 0)
    3728             :     return -1;
    3729             : 
    3730         471 :   if (options->HTTPProxy) { /* parse it now */
    3731           7 :     if (tor_addr_port_lookup(options->HTTPProxy,
    3732           7 :                         &options->HTTPProxyAddr, &options->HTTPProxyPort) < 0)
    3733           1 :       REJECT("HTTPProxy failed to parse or resolve. Please fix.");
    3734           6 :     if (options->HTTPProxyPort == 0) { /* give it a default */
    3735           5 :       options->HTTPProxyPort = 80;
    3736             :     }
    3737             :   }
    3738             : 
    3739         470 :   if (options->HTTPProxyAuthenticator) {
    3740           2 :     if (strlen(options->HTTPProxyAuthenticator) >= 512)
    3741           1 :       REJECT("HTTPProxyAuthenticator is too long (>= 512 chars).");
    3742             :   }
    3743             : 
    3744         469 :   if (options->HTTPSProxy) { /* parse it now */
    3745           4 :     if (tor_addr_port_lookup(options->HTTPSProxy,
    3746           4 :                         &options->HTTPSProxyAddr, &options->HTTPSProxyPort) <0)
    3747           1 :       REJECT("HTTPSProxy failed to parse or resolve. Please fix.");
    3748           3 :     if (options->HTTPSProxyPort == 0) { /* give it a default */
    3749           2 :       options->HTTPSProxyPort = 443;
    3750             :     }
    3751             :   }
    3752             : 
    3753         468 :   if (options->HTTPSProxyAuthenticator) {
    3754           2 :     if (strlen(options->HTTPSProxyAuthenticator) >= 512)
    3755           1 :       REJECT("HTTPSProxyAuthenticator is too long (>= 512 chars).");
    3756             :   }
    3757             : 
    3758         467 :   if (options->Socks4Proxy) { /* parse it now */
    3759           5 :     if (tor_addr_port_lookup(options->Socks4Proxy,
    3760           5 :                         &options->Socks4ProxyAddr,
    3761             :                         &options->Socks4ProxyPort) <0)
    3762           1 :       REJECT("Socks4Proxy failed to parse or resolve. Please fix.");
    3763           4 :     if (options->Socks4ProxyPort == 0) { /* give it a default */
    3764           3 :       options->Socks4ProxyPort = 1080;
    3765             :     }
    3766             :   }
    3767             : 
    3768         466 :   if (options->Socks5Proxy) { /* parse it now */
    3769           8 :     if (tor_addr_port_lookup(options->Socks5Proxy,
    3770           8 :                             &options->Socks5ProxyAddr,
    3771             :                             &options->Socks5ProxyPort) <0)
    3772           1 :       REJECT("Socks5Proxy failed to parse or resolve. Please fix.");
    3773           7 :     if (options->Socks5ProxyPort == 0) { /* give it a default */
    3774           3 :       options->Socks5ProxyPort = 1080;
    3775             :     }
    3776             :   }
    3777             : 
    3778         465 :   if (options->TCPProxy) {
    3779           0 :     int res = parse_tcp_proxy_line(options->TCPProxy, options, msg);
    3780           0 :     if (res < 0) {
    3781             :       return res;
    3782             :     }
    3783             :   }
    3784             : 
    3785             :   /* Check if more than one exclusive proxy type has been enabled. */
    3786         465 :   if (!!options->Socks4Proxy + !!options->Socks5Proxy +
    3787         465 :       !!options->HTTPSProxy + !!options->TCPProxy > 1)
    3788           1 :     REJECT("You have configured more than one proxy type. "
    3789             :            "(Socks4Proxy|Socks5Proxy|HTTPSProxy|TCPProxy)");
    3790             : 
    3791             :   /* Check if the proxies will give surprising behavior. */
    3792         467 :   if (options->HTTPProxy && !(options->Socks4Proxy ||
    3793           4 :                               options->Socks5Proxy ||
    3794             :                               options->HTTPSProxy ||
    3795             :                               options->TCPProxy)) {
    3796           3 :     log_warn(LD_CONFIG, "HTTPProxy configured, but no SOCKS proxy, "
    3797             :              "HTTPS proxy, or any other TCP proxy configured. Watch out: "
    3798             :              "this configuration will proxy unencrypted directory "
    3799             :              "connections only.");
    3800             :   }
    3801             : 
    3802         464 :   if (options->Socks5ProxyUsername) {
    3803           9 :     size_t len;
    3804             : 
    3805           9 :     len = strlen(options->Socks5ProxyUsername);
    3806           9 :     if (len < 1 || len > MAX_SOCKS5_AUTH_FIELD_SIZE)
    3807           2 :       REJECT("Socks5ProxyUsername must be between 1 and 255 characters.");
    3808             : 
    3809           7 :     if (!options->Socks5ProxyPassword)
    3810           1 :       REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
    3811             : 
    3812           6 :     len = strlen(options->Socks5ProxyPassword);
    3813           6 :     if (len < 1 || len > MAX_SOCKS5_AUTH_FIELD_SIZE)
    3814           2 :       REJECT("Socks5ProxyPassword must be between 1 and 255 characters.");
    3815         455 :   } else if (options->Socks5ProxyPassword)
    3816           1 :     REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
    3817             : 
    3818         458 :   if (options->HashedControlPassword) {
    3819           4 :     smartlist_t *sl = decode_hashed_passwords(options->HashedControlPassword);
    3820           4 :     if (!sl) {
    3821           1 :       REJECT("Bad HashedControlPassword: wrong length or bad encoding");
    3822             :     } else {
    3823           6 :       SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
    3824           3 :       smartlist_free(sl);
    3825             :     }
    3826             :   }
    3827             : 
    3828         457 :   if (options->HashedControlSessionPassword) {
    3829           4 :     smartlist_t *sl = decode_hashed_passwords(
    3830             :                                   options->HashedControlSessionPassword);
    3831           4 :     if (!sl) {
    3832           1 :       REJECT("Bad HashedControlSessionPassword: wrong length or bad encoding");
    3833             :     } else {
    3834           6 :       SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
    3835           3 :       smartlist_free(sl);
    3836             :     }
    3837             :   }
    3838             : 
    3839         456 :   if (options->OwningControllerProcess) {
    3840           2 :     const char *validate_pspec_msg = NULL;
    3841           2 :     if (tor_validate_process_specifier(options->OwningControllerProcess,
    3842             :                                        &validate_pspec_msg)) {
    3843           1 :       tor_asprintf(msg, "Bad OwningControllerProcess: %s",
    3844             :                    validate_pspec_msg);
    3845           1 :       return -1;
    3846             :     }
    3847             :   }
    3848             : 
    3849         455 :   if ((options->ControlPort_set || world_writable_control_socket) &&
    3850          11 :       !options->HashedControlPassword &&
    3851           9 :       !options->HashedControlSessionPassword &&
    3852           7 :       !options->CookieAuthentication) {
    3853           4 :     log_warn(LD_CONFIG, "Control%s is %s, but no authentication method "
    3854             :              "has been configured.  This means that any program on your "
    3855             :              "computer can reconfigure your Tor.  That's bad!  You should "
    3856             :              "upgrade your Tor controller as soon as possible.",
    3857             :              options->ControlPort_set ? "Port" : "Socket",
    3858             :              options->ControlPort_set ? "open" : "world writable");
    3859             :   }
    3860             : 
    3861         455 :   if (options->CookieAuthFileGroupReadable && !options->CookieAuthFile) {
    3862           1 :     log_warn(LD_CONFIG, "CookieAuthFileGroupReadable is set, but will have "
    3863             :              "no effect: you must specify an explicit CookieAuthFile to "
    3864             :              "have it group-readable.");
    3865             :   }
    3866             : 
    3867         461 :   for (cl = options->NodeFamilies; cl; cl = cl->next) {
    3868           8 :     routerset_t *rs = routerset_new();
    3869           8 :     if (routerset_parse(rs, cl->value, cl->key)) {
    3870           2 :       routerset_free(rs);
    3871           2 :       return -1;
    3872             :     }
    3873           6 :     routerset_free(rs);
    3874             :   }
    3875             : 
    3876         453 :   if (validate_addr_policies(options, msg) < 0)
    3877             :     return -1;
    3878             : 
    3879             :   /* If FallbackDir is set, we don't UseDefaultFallbackDirs */
    3880         452 :   if (options->UseDefaultFallbackDirs && options->FallbackDir) {
    3881           0 :     log_info(LD_CONFIG, "You have set UseDefaultFallbackDirs 1 and "
    3882             :              "FallbackDir(s). Ignoring UseDefaultFallbackDirs, and "
    3883             :              "using the FallbackDir(s) you have set.");
    3884             :   }
    3885             : 
    3886         452 :   if (validate_dir_servers(options, old_options) < 0)
    3887           1 :     REJECT("Directory authority/fallback line did not parse. See logs "
    3888             :            "for details.");
    3889             : 
    3890         451 :   if (options->UseBridges && !options->Bridges)
    3891           2 :     REJECT("If you set UseBridges, you must specify at least one bridge.");
    3892             : 
    3893         460 :   for (cl = options->Bridges; cl; cl = cl->next) {
    3894          12 :       bridge_line_t *bridge_line = parse_bridge_line(cl->value);
    3895          12 :       if (!bridge_line)
    3896           1 :         REJECT("Bridge line did not parse. See logs for details.");
    3897          11 :       bridge_line_free(bridge_line);
    3898             :   }
    3899             : 
    3900         449 :   for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
    3901           2 :     if (pt_parse_transport_line(options, cl->value, 1, 0) < 0)
    3902           1 :       REJECT("Invalid client transport line. See logs for details.");
    3903             :   }
    3904             : 
    3905         447 :   if (options_validate_server_transport(old_options, options, msg) < 0)
    3906             :     return -1;
    3907             : 
    3908         442 :   if (options->ConstrainedSockets) {
    3909             :     /* If the user wants to constrain socket buffer use, make sure the desired
    3910             :      * limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */
    3911           6 :     if (options->ConstrainedSockSize < MIN_CONSTRAINED_TCP_BUFFER ||
    3912           3 :         options->ConstrainedSockSize > MAX_CONSTRAINED_TCP_BUFFER ||
    3913           3 :         options->ConstrainedSockSize % 1024) {
    3914           3 :       tor_asprintf(msg,
    3915             :           "ConstrainedSockSize is invalid.  Must be a value between %d and %d "
    3916             :           "in 1024 byte increments.",
    3917             :           MIN_CONSTRAINED_TCP_BUFFER, MAX_CONSTRAINED_TCP_BUFFER);
    3918           3 :       return -1;
    3919             :     }
    3920             :   }
    3921             : 
    3922         439 :   if (options_validate_dirauth_schedule(old_options, options, msg) < 0)
    3923             :     return -1;
    3924             : 
    3925         430 :   if (hs_config_service_all(options, 1) < 0)
    3926           1 :     REJECT("Failed to configure rendezvous options. See logs for details.");
    3927             : 
    3928             :   /* Parse client-side authorization for hidden services. */
    3929         429 :   if (hs_config_client_auth_all(options, 1) < 0)
    3930           0 :     REJECT("Failed to configure client authorization for hidden services. "
    3931             :            "See logs for details.");
    3932             : 
    3933         429 :   if (parse_virtual_addr_network(options->VirtualAddrNetworkIPv4,
    3934             :                                  AF_INET, 1, msg)<0)
    3935             :     return -1;
    3936         428 :   if (parse_virtual_addr_network(options->VirtualAddrNetworkIPv6,
    3937             :                                  AF_INET6, 1, msg)<0)
    3938             :     return -1;
    3939             : 
    3940         427 :   if (options->TestingTorNetwork &&
    3941          49 :       !(options->DirAuthorities ||
    3942           4 :         (options->AlternateDirAuthority &&
    3943           2 :          options->AlternateBridgeAuthority))) {
    3944           3 :     REJECT("TestingTorNetwork may only be configured in combination with "
    3945             :            "a non-default set of DirAuthority or both of "
    3946             :            "AlternateDirAuthority and AlternateBridgeAuthority configured.");
    3947             :   }
    3948             : 
    3949             : #define CHECK_DEFAULT(arg)                                              \
    3950             :   STMT_BEGIN                                                            \
    3951             :     if (!config_is_same(get_options_mgr(),options,                      \
    3952             :                         dflt_options,#arg)) {                           \
    3953             :       or_options_free(dflt_options);                                    \
    3954             :       REJECT(#arg " may only be changed in testing Tor "                \
    3955             :              "networks!");                                              \
    3956             :     }                                                                   \
    3957             :   STMT_END
    3958             : 
    3959             :   /* Check for options that can only be changed from the defaults in testing
    3960             :      networks.  */
    3961         424 :   if (! options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
    3962         357 :     or_options_t *dflt_options = options_new();
    3963         357 :     options_init(dflt_options);
    3964             :     /* 31851: some of these options are dirauth or relay only */
    3965         357 :     CHECK_DEFAULT(TestingV3AuthInitialVotingInterval);
    3966         356 :     CHECK_DEFAULT(TestingV3AuthInitialVoteDelay);
    3967         355 :     CHECK_DEFAULT(TestingV3AuthInitialDistDelay);
    3968         354 :     CHECK_DEFAULT(TestingV3AuthVotingStartOffset);
    3969         353 :     CHECK_DEFAULT(TestingAuthDirTimeToLearnReachability);
    3970         352 :     CHECK_DEFAULT(TestingServerDownloadInitialDelay);
    3971         351 :     CHECK_DEFAULT(TestingClientDownloadInitialDelay);
    3972         350 :     CHECK_DEFAULT(TestingServerConsensusDownloadInitialDelay);
    3973         349 :     CHECK_DEFAULT(TestingClientConsensusDownloadInitialDelay);
    3974         348 :     CHECK_DEFAULT(TestingBridgeDownloadInitialDelay);
    3975         347 :     CHECK_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay);
    3976         346 :     CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest);
    3977         345 :     CHECK_DEFAULT(TestingDirConnectionMaxStall);
    3978         344 :     CHECK_DEFAULT(TestingAuthKeyLifetime);
    3979         343 :     CHECK_DEFAULT(TestingLinkCertLifetime);
    3980         342 :     CHECK_DEFAULT(TestingSigningKeySlop);
    3981         341 :     CHECK_DEFAULT(TestingAuthKeySlop);
    3982         340 :     CHECK_DEFAULT(TestingLinkKeySlop);
    3983         339 :     or_options_free(dflt_options);
    3984             :   }
    3985             : #undef CHECK_DEFAULT
    3986             : 
    3987         406 :   if (!options->ClientDNSRejectInternalAddresses &&
    3988           0 :       !(options->DirAuthorities ||
    3989           0 :         (options->AlternateDirAuthority && options->AlternateBridgeAuthority)))
    3990           0 :     REJECT("ClientDNSRejectInternalAddresses used for default network.");
    3991             : 
    3992         406 :   if (options_validate_relay_testing(old_options, options, msg) < 0)
    3993             :     return -1;
    3994         401 :   if (options_validate_dirauth_testing(old_options, options, msg) < 0)
    3995             :     return -1;
    3996             : 
    3997         394 :   if (options->TestingClientMaxIntervalWithoutRequest < 1) {
    3998           3 :     REJECT("TestingClientMaxIntervalWithoutRequest is way too low.");
    3999         391 :   } else if (options->TestingClientMaxIntervalWithoutRequest > 3600) {
    4000           3 :     COMPLAIN("TestingClientMaxIntervalWithoutRequest is insanely high.");
    4001             :   }
    4002             : 
    4003         391 :   if (options->TestingDirConnectionMaxStall < 5) {
    4004           3 :     REJECT("TestingDirConnectionMaxStall is way too low.");
    4005         388 :   } else if (options->TestingDirConnectionMaxStall > 3600) {
    4006           3 :     COMPLAIN("TestingDirConnectionMaxStall is insanely high.");
    4007             :   }
    4008             : 
    4009         388 :   if (options->ClientBootstrapConsensusMaxInProgressTries < 1) {
    4010           0 :     REJECT("ClientBootstrapConsensusMaxInProgressTries must be greater "
    4011             :            "than 0.");
    4012         388 :   } else if (options->ClientBootstrapConsensusMaxInProgressTries
    4013             :              > 100) {
    4014           0 :     COMPLAIN("ClientBootstrapConsensusMaxInProgressTries is insanely "
    4015             :              "high.");
    4016             :   }
    4017             : 
    4018         388 :   if (options->TestingEnableConnBwEvent &&
    4019           3 :       !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
    4020           1 :     REJECT("TestingEnableConnBwEvent may only be changed in testing "
    4021             :            "Tor networks!");
    4022             :   }
    4023             : 
    4024         387 :   if (options->TestingEnableCellStatsEvent &&
    4025           3 :       !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
    4026           1 :     REJECT("TestingEnableCellStatsEvent may only be changed in testing "
    4027             :            "Tor networks!");
    4028             :   }
    4029             : 
    4030         386 :   if (options->TestingTorNetwork) {
    4031          31 :     log_warn(LD_CONFIG, "TestingTorNetwork is set. This will make your node "
    4032             :                         "almost unusable in the public Tor network, and is "
    4033             :                         "therefore only advised if you are building a "
    4034             :                         "testing Tor network!");
    4035             :   }
    4036             : 
    4037         386 :   if (options_validate_scheduler(options, msg) < 0) {
    4038           0 :     return -1;
    4039             :   }
    4040             : 
    4041             :   return 0;
    4042             : }
    4043             : 
    4044             : #undef REJECT
    4045             : #undef COMPLAIN
    4046             : 
    4047             : /* Given the value that the user has set for MaxMemInQueues, compute the
    4048             :  * actual maximum value.  We clip this value if it's too low, and autodetect
    4049             :  * it if it's set to 0. */
    4050             : STATIC uint64_t
    4051         531 : compute_real_max_mem_in_queues(const uint64_t val, bool is_server)
    4052             : {
    4053             : #define MIN_SERVER_MB 64
    4054             : #define MIN_UNWARNED_SERVER_MB 256
    4055             : #define MIN_UNWARNED_CLIENT_MB 64
    4056         531 :   uint64_t result;
    4057             : 
    4058         531 :   if (val == 0) {
    4059             : #define ONE_GIGABYTE (UINT64_C(1) << 30)
    4060             : #define ONE_MEGABYTE (UINT64_C(1) << 20)
    4061             :     /* The user didn't pick a memory limit.  Choose a very large one
    4062             :      * that is still smaller than the system memory */
    4063         528 :     static int notice_sent = 0;
    4064         528 :     size_t ram = 0;
    4065         528 :     if (get_total_system_memory(&ram) < 0) {
    4066             :       /* We couldn't determine our total system memory!  */
    4067             : #if SIZEOF_VOID_P >= 8
    4068             :       /* 64-bit system.  Let's hope for 8 GB. */
    4069             :       result = 8 * ONE_GIGABYTE;
    4070             : #else
    4071             :       /* (presumably) 32-bit system. Let's hope for 1 GB. */
    4072             :       result = ONE_GIGABYTE;
    4073             : #endif /* SIZEOF_VOID_P >= 8 */
    4074             :     } else {
    4075             :       /* We detected the amount of memory available. */
    4076         527 :       uint64_t avail = 0;
    4077             : 
    4078             : #if SIZEOF_SIZE_T > 4
    4079             : /* On a 64-bit platform, we consider 8GB "very large". */
    4080             : #define RAM_IS_VERY_LARGE(x) ((x) >= (8 * ONE_GIGABYTE))
    4081             : #else
    4082             : /* On a 32-bit platform, we can't have 8GB of ram. */
    4083             : #define RAM_IS_VERY_LARGE(x) (0)
    4084             : #endif /* SIZEOF_SIZE_T > 4 */
    4085             : 
    4086         527 :       if (RAM_IS_VERY_LARGE(ram)) {
    4087             :         /* If we have 8 GB, or more, RAM available, we set the MaxMemInQueues
    4088             :          * to 0.4 * RAM. The idea behind this value is that the amount of RAM
    4089             :          * is more than enough for a single relay and should allow the relay
    4090             :          * operator to run two relays if they have additional bandwidth
    4091             :          * available.
    4092             :          */
    4093         525 :         avail = (ram / 5) * 2;
    4094             :       } else {
    4095             :         /* If we have less than 8 GB of RAM available, we use the "old" default
    4096             :          * for MaxMemInQueues of 0.75 * RAM.
    4097             :          */
    4098           2 :         avail = (ram / 4) * 3;
    4099             :       }
    4100             : 
    4101             :       /* Make sure it's in range from 0.25 GB to 8 GB for 64-bit and 0.25 to 2
    4102             :        * GB for 32-bit. */
    4103         527 :       if (avail > MAX_DEFAULT_MEMORY_QUEUE_SIZE) {
    4104             :         /* If you want to use more than this much RAM, you need to configure
    4105             :            it yourself */
    4106             :         result = MAX_DEFAULT_MEMORY_QUEUE_SIZE;
    4107             :       } else if (avail < ONE_GIGABYTE / 4) {
    4108             :         result = ONE_GIGABYTE / 4;
    4109             :       } else {
    4110             :         result = avail;
    4111             :       }
    4112             :     }
    4113         528 :     if (is_server && ! notice_sent) {
    4114         135 :       log_notice(LD_CONFIG, "%sMaxMemInQueues is set to %"PRIu64" MB. "
    4115             :                  "You can override this by setting MaxMemInQueues by hand.",
    4116             :                  ram ? "Based on detected system memory, " : "",
    4117             :                  (result / ONE_MEGABYTE));
    4118         135 :       notice_sent = 1;
    4119             :     }
    4120         528 :     return result;
    4121           3 :   } else if (is_server && val < ONE_MEGABYTE * MIN_SERVER_MB) {
    4122             :     /* We can't configure less than this much on a server.  */
    4123           0 :     log_warn(LD_CONFIG, "MaxMemInQueues must be at least %d MB on servers "
    4124             :              "for now. Ideally, have it as large as you can afford.",
    4125             :              MIN_SERVER_MB);
    4126           0 :     return MIN_SERVER_MB * ONE_MEGABYTE;
    4127           3 :   } else if (is_server && val < ONE_MEGABYTE * MIN_UNWARNED_SERVER_MB) {
    4128             :     /* On a server, if it's less than this much, we warn that things
    4129             :      * may go badly. */
    4130           0 :     log_warn(LD_CONFIG, "MaxMemInQueues is set to a low value; if your "
    4131             :              "relay doesn't work, this may be the reason why.");
    4132           0 :     return val;
    4133           3 :   } else if (! is_server && val < ONE_MEGABYTE * MIN_UNWARNED_CLIENT_MB) {
    4134             :     /* On a client, if it's less than this much, we warn that things
    4135             :      * may go badly. */
    4136           0 :     log_warn(LD_CONFIG, "MaxMemInQueues is set to a low value; if your "
    4137             :              "client doesn't work, this may be the reason why.");
    4138           0 :     return val;
    4139             :   } else {
    4140             :     /* The value was fine all along */
    4141             :     return val;
    4142             :   }
    4143             : }
    4144             : 
    4145             : /** Helper: return true iff s1 and s2 are both NULL, or both non-NULL
    4146             :  * equal strings. */
    4147             : static int
    4148           0 : opt_streq(const char *s1, const char *s2)
    4149             : {
    4150           0 :   return 0 == strcmp_opt(s1, s2);
    4151             : }
    4152             : 
    4153             : /** Check if any config options have changed but aren't allowed to. */
    4154             : static int
    4155           5 : options_check_transition_cb(const void *old_,
    4156             :                             const void *new_val_,
    4157             :                             char **msg)
    4158             : {
    4159           5 :   CHECK_OPTIONS_MAGIC(old_);
    4160           5 :   CHECK_OPTIONS_MAGIC(new_val_);
    4161             : 
    4162           5 :   const or_options_t *old = old_;
    4163           5 :   const or_options_t *new_val = new_val_;
    4164             : 
    4165           5 :   if (BUG(!old))
    4166           0 :     return 0;
    4167             : 
    4168             : #define BAD_CHANGE_TO(opt, how) do {                                    \
    4169             :     *msg = tor_strdup("While Tor is running"how", changing " #opt       \
    4170             :                       " is not allowed");                               \
    4171             :     return -1;                                                          \
    4172             :   } while (0)
    4173             : 
    4174           5 :   if (sandbox_is_active()) {
    4175             : #define SB_NOCHANGE_STR(opt)                      \
    4176             :     if (! CFG_EQ_STRING(old, new_val, opt))       \
    4177             :       BAD_CHANGE_TO(opt," with Sandbox active")
    4178             : #define SB_NOCHANGE_LINELIST(opt)                  \
    4179             :     if (! CFG_EQ_LINELIST(old, new_val, opt))      \
    4180             :       BAD_CHANGE_TO(opt," with Sandbox active")
    4181             : #define SB_NOCHANGE_INT(opt)                       \
    4182             :     if (! CFG_EQ_INT(old, new_val, opt))           \
    4183             :       BAD_CHANGE_TO(opt," with Sandbox active")
    4184             : 
    4185           0 :     SB_NOCHANGE_LINELIST(Address);
    4186           0 :     SB_NOCHANGE_STR(ServerDNSResolvConfFile);
    4187           0 :     SB_NOCHANGE_STR(DirPortFrontPage);
    4188           0 :     SB_NOCHANGE_STR(CookieAuthFile);
    4189           0 :     SB_NOCHANGE_STR(ExtORPortCookieAuthFile);
    4190           0 :     SB_NOCHANGE_LINELIST(Logs);
    4191           0 :     SB_NOCHANGE_INT(ConnLimit);
    4192             : 
    4193           0 :     if (server_mode(old) != server_mode(new_val)) {
    4194           0 :       *msg = tor_strdup("Can't start/stop being a server while "
    4195             :                         "Sandbox is active");
    4196           0 :       return -1;
    4197             :     }
    4198             :   }
    4199             : 
    4200             : #undef SB_NOCHANGE_LINELIST
    4201             : #undef SB_NOCHANGE_STR
    4202             : #undef SB_NOCHANGE_INT
    4203             : #undef BAD_CHANGE_TO
    4204             : #undef NO_CHANGE_BOOL
    4205             : #undef NO_CHANGE_INT
    4206             : #undef NO_CHANGE_STRING
    4207             :   return 0;
    4208             : }
    4209             : 
    4210             : #ifdef _WIN32
    4211             : /** Return the directory on windows where we expect to find our application
    4212             :  * data. */
    4213             : static char *
    4214             : get_windows_conf_root(void)
    4215             : {
    4216             :   static int is_set = 0;
    4217             :   static char path[MAX_PATH*2+1];
    4218             :   TCHAR tpath[MAX_PATH] = {0};
    4219             : 
    4220             :   LPITEMIDLIST idl;
    4221             :   IMalloc *m;
    4222             :   HRESULT result;
    4223             : 
    4224             :   if (is_set)
    4225             :     return path;
    4226             : 
    4227             :   /* Find X:\documents and settings\username\application data\ .
    4228             :    * We would use SHGetSpecialFolder path, but that wasn't added until IE4.
    4229             :    */
    4230             : #ifdef ENABLE_LOCAL_APPDATA
    4231             : #define APPDATA_PATH CSIDL_LOCAL_APPDATA
    4232             : #else
    4233             : #define APPDATA_PATH CSIDL_APPDATA
    4234             : #endif
    4235             :   if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, APPDATA_PATH, &idl))) {
    4236             :     getcwd(path,MAX_PATH);
    4237             :     is_set = 1;
    4238             :     log_warn(LD_CONFIG,
    4239             :              "I couldn't find your application data folder: are you "
    4240             :              "running an ancient version of Windows 95? Defaulting to \"%s\"",
    4241             :              path);
    4242             :     return path;
    4243             :   }
    4244             :   /* Convert the path from an "ID List" (whatever that is!) to a path. */
    4245             :   result = SHGetPathFromIDList(idl, tpath);
    4246             : #ifdef UNICODE
    4247             :   wcstombs(path,tpath,sizeof(path));
    4248             :   path[sizeof(path)-1] = '\0';
    4249             : #else
    4250             :   strlcpy(path,tpath,sizeof(path));
    4251             : #endif /* defined(UNICODE) */
    4252             : 
    4253             :   /* Now we need to free the memory that the path-idl was stored in.  In
    4254             :    * typical Windows fashion, we can't just call 'free()' on it. */
    4255             :   SHGetMalloc(&m);
    4256             :   if (m) {
    4257             :     m->lpVtbl->Free(m, idl);
    4258             :     m->lpVtbl->Release(m);
    4259             :   }
    4260             :   if (!SUCCEEDED(result)) {
    4261             :     return NULL;
    4262             :   }
    4263             :   strlcat(path,"\\tor",MAX_PATH);
    4264             :   is_set = 1;
    4265             :   return path;
    4266             : }
    4267             : #endif /* defined(_WIN32) */
    4268             : 
    4269             : /** Return the default location for our torrc file (if <b>defaults_file</b> is
    4270             :  * false), or for the torrc-defaults file (if <b>defaults_file</b> is true). */
    4271             : static const char *
    4272           0 : get_default_conf_file(int defaults_file)
    4273             : {
    4274             : #ifdef DISABLE_SYSTEM_TORRC
    4275             :   (void) defaults_file;
    4276             :   return NULL;
    4277             : #elif defined(_WIN32)
    4278             :   if (defaults_file) {
    4279             :     static char defaults_path[MAX_PATH+1];
    4280             :     tor_snprintf(defaults_path, MAX_PATH, "%s\\torrc-defaults",
    4281             :                  get_windows_conf_root());
    4282             :     return defaults_path;
    4283             :   } else {
    4284             :     static char path[MAX_PATH+1];
    4285             :     tor_snprintf(path, MAX_PATH, "%s\\torrc",
    4286             :                  get_windows_conf_root());
    4287             :     return path;
    4288             :   }
    4289             : #else
    4290           0 :   return defaults_file ? CONFDIR "/torrc-defaults" : CONFDIR "/torrc";
    4291             : #endif /* defined(DISABLE_SYSTEM_TORRC) || ... */
    4292             : }
    4293             : 
    4294             : /** Learn config file name from command line arguments, or use the default.
    4295             :  *
    4296             :  * If <b>defaults_file</b> is true, we're looking for torrc-defaults;
    4297             :  * otherwise, we're looking for the regular torrc_file.
    4298             :  *
    4299             :  * Set *<b>using_default_fname</b> to true if we're using the default
    4300             :  * configuration file name; or false if we've set it from the command line.
    4301             :  *
    4302             :  * Set *<b>ignore_missing_torrc</b> to true if we should ignore the resulting
    4303             :  * filename if it doesn't exist.
    4304             :  */
    4305             : static char *
    4306         456 : find_torrc_filename(const config_line_t *cmd_arg,
    4307             :                     int defaults_file,
    4308             :                     int *using_default_fname, int *ignore_missing_torrc)
    4309             : {
    4310         456 :   char *fname=NULL;
    4311         456 :   const config_line_t *p_index;
    4312         456 :   const char *fname_opt = defaults_file ? "--defaults-torrc" : "-f";
    4313         456 :   const char *fname_long_opt = defaults_file ? "--defaults-torrc" :
    4314             :                                                "--torrc-file";
    4315         456 :   const char *ignore_opt = defaults_file ? NULL : "--ignore-missing-torrc";
    4316         456 :   const char *keygen_opt = "--keygen";
    4317             : 
    4318         456 :   if (defaults_file)
    4319         228 :     *ignore_missing_torrc = 1;
    4320             : 
    4321        1920 :   for (p_index = cmd_arg; p_index; p_index = p_index->next) {
    4322             :     // options_init_from_torrc ensures only the short or long name is present
    4323        1464 :     if (!strcmp(p_index->key, fname_opt) ||
    4324        1008 :         !strcmp(p_index->key, fname_long_opt)) {
    4325         456 :       if (fname) {
    4326           0 :         log_warn(LD_CONFIG, "Duplicate %s options on command line.",
    4327             :             p_index->key);
    4328           0 :         tor_free(fname);
    4329             :       }
    4330         456 :       fname = expand_filename(p_index->value);
    4331             : 
    4332             :       {
    4333         456 :         char *absfname;
    4334         456 :         absfname = make_path_absolute(fname);
    4335         456 :         tor_free(fname);
    4336         456 :         fname = absfname;
    4337             :       }
    4338             : 
    4339         456 :       *using_default_fname = 0;
    4340        1008 :     } else if ((ignore_opt && !strcmp(p_index->key, ignore_opt)) ||
    4341        1008 :                (keygen_opt && !strcmp(p_index->key, keygen_opt))) {
    4342          12 :       *ignore_missing_torrc = 1;
    4343             :     }
    4344             :   }
    4345             : 
    4346         456 :   if (*using_default_fname) {
    4347             :     /* didn't find one, try CONFDIR */
    4348           0 :     const char *dflt = get_default_conf_file(defaults_file);
    4349           0 :     file_status_t st = file_status(dflt);
    4350           0 :     if (dflt && (st == FN_FILE || st == FN_EMPTY)) {
    4351           0 :       fname = tor_strdup(dflt);
    4352             :     } else {
    4353             : #ifndef _WIN32
    4354           0 :       char *fn = NULL;
    4355           0 :       if (!defaults_file) {
    4356           0 :         fn = expand_filename("~/.torrc");
    4357             :       }
    4358           0 :       if (fn) {
    4359           0 :         file_status_t hmst = file_status(fn);
    4360           0 :         if (hmst == FN_FILE || hmst == FN_EMPTY || dflt == NULL) {
    4361             :           fname = fn;
    4362             :         } else {
    4363           0 :           tor_free(fn);
    4364           0 :           fname = tor_strdup(dflt);
    4365             :         }
    4366             :       } else {
    4367           0 :         fname = dflt ? tor_strdup(dflt) : NULL;
    4368             :       }
    4369             : #else /* defined(_WIN32) */
    4370             :       fname = dflt ? tor_strdup(dflt) : NULL;
    4371             : #endif /* !defined(_WIN32) */
    4372             :     }
    4373             :   }
    4374         456 :   return fname;
    4375             : }
    4376             : 
    4377             : /** Read the torrc from standard input and return it as a string.
    4378             :  * Upon failure, return NULL.
    4379             :  */
    4380             : static char *
    4381           0 : load_torrc_from_stdin(void)
    4382             : {
    4383           0 :    size_t sz_out;
    4384             : 
    4385           0 :    return read_file_to_str_until_eof(STDIN_FILENO,SIZE_MAX,&sz_out);
    4386             : }
    4387             : 
    4388             : /** Load a configuration file from disk, setting torrc_fname or
    4389             :  * torrc_defaults_fname if successful.
    4390             :  *
    4391             :  * If <b>defaults_file</b> is true, load torrc-defaults; otherwise load torrc.
    4392             :  *
    4393             :  * Return the contents of the file on success, and NULL on failure.
    4394             :  */
    4395             : static char *
    4396         456 : load_torrc_from_disk(const config_line_t *cmd_arg, int defaults_file)
    4397             : {
    4398         456 :   char *fname=NULL;
    4399         456 :   char *cf = NULL;
    4400         456 :   int using_default_torrc = 1;
    4401         456 :   int ignore_missing_torrc = 0;
    4402         456 :   char **fname_var = defaults_file ? &torrc_defaults_fname : &torrc_fname;
    4403             : 
    4404         456 :   if (*fname_var == NULL) {
    4405         456 :     fname = find_torrc_filename(cmd_arg, defaults_file,
    4406             :                                 &using_default_torrc, &ignore_missing_torrc);
    4407         456 :     tor_free(*fname_var);
    4408         456 :     *fname_var = fname;
    4409             :   } else {
    4410             :     fname = *fname_var;
    4411             :   }
    4412         912 :   log_debug(LD_CONFIG, "Opening config file \"%s\"", fname?fname:"<NULL>");
    4413             : 
    4414             :   /* Open config file */
    4415         456 :   file_status_t st = fname ? file_status(fname) : FN_EMPTY;
    4416         456 :   if (fname == NULL ||
    4417         456 :       !(st == FN_FILE || st == FN_EMPTY) ||
    4418         455 :       !(cf = read_file_to_str(fname,0,NULL))) {
    4419           1 :     if (using_default_torrc == 1 || ignore_missing_torrc) {
    4420           0 :       if (!defaults_file)
    4421           0 :         log_notice(LD_CONFIG, "Configuration file \"%s\" not present, "
    4422             :             "using reasonable defaults.", fname);
    4423           0 :       tor_free(fname); /* sets fname to NULL */
    4424           0 :       *fname_var = NULL;
    4425           0 :       cf = tor_strdup("");
    4426             :     } else {
    4427           1 :       log_warn(LD_CONFIG,
    4428             :           "Unable to open configuration file \"%s\".", fname);
    4429           1 :       goto err;
    4430             :     }
    4431             :   } else {
    4432         455 :     log_notice(LD_CONFIG, "Read configuration file \"%s\".", fname);
    4433             :   }
    4434             : 
    4435             :   return cf;
    4436           1 :  err:
    4437           1 :   tor_free(fname);
    4438           1 :   *fname_var = NULL;
    4439           1 :   return NULL;
    4440             : }
    4441             : 
    4442             : /** Read a configuration file into <b>options</b>, finding the configuration
    4443             :  * file location based on the command line.  After loading the file
    4444             :  * call options_init_from_string() to load the config.
    4445             :  * Return 0 if success, -1 if failure, and 1 if we succeeded but should exit
    4446             :  * anyway. */
    4447             : int
    4448         235 : options_init_from_torrc(int argc, char **argv)
    4449             : {
    4450         235 :   char *cf=NULL, *cf_defaults=NULL;
    4451         235 :   int retval = -1;
    4452         235 :   char *errmsg=NULL;
    4453         235 :   const config_line_t *cmdline_only_options;
    4454             : 
    4455             :   /* Go through command-line variables */
    4456         235 :   if (global_cmdline == NULL) {
    4457             :     /* Or we could redo the list every time we pass this place.
    4458             :      * It does not really matter */
    4459         235 :     global_cmdline = config_parse_commandline(argc, argv, 0);
    4460         235 :     if (global_cmdline == NULL) {
    4461           2 :       goto err;
    4462             :     }
    4463             :   }
    4464         233 :   cmdline_only_options = global_cmdline->cmdline_opts;
    4465             : 
    4466         466 :   if (config_line_find(cmdline_only_options, "-h") ||
    4467         233 :       config_line_find(cmdline_only_options, "--help")) {
    4468           0 :     print_usage();
    4469           0 :     return 1;
    4470             :   }
    4471         233 :   if (config_line_find(cmdline_only_options, "--list-torrc-options")) {
    4472             :     /* For validating whether we've documented everything. */
    4473           1 :     list_torrc_options();
    4474           1 :     return 1;
    4475             :   }
    4476         232 :   if (config_line_find(cmdline_only_options, "--list-deprecated-options")) {
    4477             :     /* For validating whether what we have deprecated really exists. */
    4478           0 :     list_deprecated_options();
    4479           0 :     return 1;
    4480             :   }
    4481         232 :   if (config_line_find(cmdline_only_options, "--dbg-dump-subsystem-list")) {
    4482           0 :     subsystems_dump_list();
    4483           0 :     return 1;
    4484             :   }
    4485             : 
    4486         232 :   if (config_line_find(cmdline_only_options, "--version")) {
    4487           0 :     printf("Tor version %s.\n",get_version());
    4488           0 :     printf("Tor is running on %s with Libevent %s, "
    4489             :             "%s %s, Zlib %s, Liblzma %s, Libzstd %s and %s %s as libc.\n",
    4490             :             get_uname(),
    4491             :             tor_libevent_get_version_str(),
    4492             :             crypto_get_library_name(),
    4493             :             crypto_get_library_version_string(),
    4494           0 :             tor_compress_supports_method(ZLIB_METHOD) ?
    4495           0 :             tor_compress_version_str(ZLIB_METHOD) : "N/A",
    4496           0 :             tor_compress_supports_method(LZMA_METHOD) ?
    4497           0 :             tor_compress_version_str(LZMA_METHOD) : "N/A",
    4498           0 :             tor_compress_supports_method(ZSTD_METHOD) ?
    4499           0 :             tor_compress_version_str(ZSTD_METHOD) : "N/A",
    4500           0 :             tor_libc_get_name() ?
    4501           0 :             tor_libc_get_name() : "Unknown",
    4502             :             tor_libc_get_version_str());
    4503           0 :     printf("Tor compiled with %s version %s\n",
    4504             :             strcmp(COMPILER_VENDOR, "gnu") == 0?
    4505             :             COMPILER:COMPILER_VENDOR, COMPILER_VERSION);
    4506             : 
    4507           0 :     return 1;
    4508             :   }
    4509             : 
    4510         232 :   if (config_line_find(cmdline_only_options, "--list-modules")) {
    4511           4 :     list_enabled_modules();
    4512           4 :     return 1;
    4513             :   }
    4514             : 
    4515         228 :   if (config_line_find(cmdline_only_options, "--library-versions")) {
    4516           0 :     print_library_versions();
    4517           0 :     return 1;
    4518             :   }
    4519             : 
    4520         228 :   int command = global_cmdline->command;
    4521         228 :   const char *command_arg = global_cmdline->command_arg;
    4522             :   /* "immediate" has already been handled by this point. */
    4523         228 :   tor_assert(command != CMD_IMMEDIATE);
    4524             : 
    4525         228 :   if (command == CMD_HASH_PASSWORD) {
    4526           0 :     cf_defaults = tor_strdup("");
    4527           0 :     cf = tor_strdup("");
    4528             :   } else {
    4529         228 :     cf_defaults = load_torrc_from_disk(cmdline_only_options, 1);
    4530         228 :     const config_line_t *f_line = config_line_find(cmdline_only_options, "-f");
    4531         228 :     const config_line_t *f_line_long = config_line_find(cmdline_only_options,
    4532             :                                                         "--torrc-file");
    4533         228 :     if (f_line && f_line_long) {
    4534           0 :       log_err(LD_CONFIG, "-f and --torrc-file cannot be used together.");
    4535           0 :       retval = -1;
    4536           0 :       goto err;
    4537         228 :     } else if (f_line_long) {
    4538           0 :       f_line = f_line_long;
    4539             :     }
    4540             : 
    4541         456 :     const int read_torrc_from_stdin =
    4542         228 :     (f_line != NULL && strcmp(f_line->value, "-") == 0);
    4543             : 
    4544         228 :     if (read_torrc_from_stdin) {
    4545           0 :       cf = load_torrc_from_stdin();
    4546             :     } else {
    4547         228 :       cf = load_torrc_from_disk(cmdline_only_options, 0);
    4548             :     }
    4549             : 
    4550         228 :     if (!cf) {
    4551           1 :       if (config_line_find(cmdline_only_options, "--allow-missing-torrc")) {
    4552           0 :         cf = tor_strdup("");
    4553             :       } else {
    4554           1 :         goto err;
    4555             :       }
    4556             :     }
    4557             :   }
    4558             : 
    4559         227 :   retval = options_init_from_string(cf_defaults, cf, command, command_arg,
    4560             :                                     &errmsg);
    4561         227 :   if (retval < 0)
    4562          26 :     goto err;
    4563             : 
    4564         201 :   if (config_line_find(cmdline_only_options, "--no-passphrase")) {
    4565           3 :     if (handle_cmdline_no_passphrase(command) < 0) {
    4566           1 :       retval = -1;
    4567           1 :       goto err;
    4568             :     }
    4569             :   }
    4570             : 
    4571         200 :   const config_line_t *format_line = config_line_find(cmdline_only_options,
    4572             :                                                       "--format");
    4573         200 :   if (format_line) {
    4574           4 :     if (handle_cmdline_format(command, format_line->value) < 0) {
    4575           2 :       retval = -1;
    4576           2 :       goto err;
    4577             :     }
    4578             :   } else {
    4579         196 :     get_options_mutable()->key_expiration_format =
    4580             :       KEY_EXPIRATION_FORMAT_ISO8601;
    4581             :   }
    4582             : 
    4583         198 :   if (config_line_find(cmdline_only_options, "--newpass")) {
    4584           1 :     if (handle_cmdline_newpass(command) < 0) {
    4585           1 :       retval = -1;
    4586           1 :       goto err;
    4587             :     }
    4588             :   }
    4589             : 
    4590         197 :   const config_line_t *fd_line = config_line_find(cmdline_only_options,
    4591             :                                                   "--passphrase-fd");
    4592         197 :   if (fd_line) {
    4593           5 :     if (handle_cmdline_passphrase_fd(command, fd_line->value) < 0) {
    4594           3 :       retval = -1;
    4595           3 :       goto err;
    4596             :     }
    4597             :   }
    4598             : 
    4599         194 :   const config_line_t *key_line = config_line_find(cmdline_only_options,
    4600             :                                                    "--master-key");
    4601         194 :   if (key_line) {
    4602           0 :     if (handle_cmdline_master_key(command, key_line->value) < 0) {
    4603           0 :       retval = -1;
    4604           0 :       goto err;
    4605             :     }
    4606             :   }
    4607             : 
    4608         194 :  err:
    4609         230 :   tor_free(cf);
    4610         230 :   tor_free(cf_defaults);
    4611         230 :   if (errmsg) {
    4612          25 :     log_warn(LD_CONFIG,"%s", errmsg);
    4613          25 :     tor_free(errmsg);
    4614             :   }
    4615         230 :   return retval < 0 ? -1 : 0;
    4616             : }
    4617             : 
    4618             : /** Load the options from the configuration in <b>cf</b>, validate
    4619             :  * them for consistency and take actions based on them.
    4620             :  *
    4621             :  * Return 0 if success, negative on error:
    4622             :  *  * -1 for general errors.
    4623             :  *  * -2 for failure to parse/validate,
    4624             :  *  * -3 for transition not allowed
    4625             :  *  * -4 for error while setting the new options
    4626             :  */
    4627             : setopt_err_t
    4628         230 : options_init_from_string(const char *cf_defaults, const char *cf,
    4629             :                          int command, const char *command_arg,
    4630             :                          char **msg)
    4631             : {
    4632         230 :   bool retry = false;
    4633         230 :   or_options_t *oldoptions, *newoptions, *newdefaultoptions=NULL;
    4634         230 :   config_line_t *cl;
    4635         230 :   int retval;
    4636         230 :   setopt_err_t err = SETOPT_ERR_MISC;
    4637         230 :   int cf_has_include = 0;
    4638         230 :   tor_assert(msg);
    4639             : 
    4640         230 :   oldoptions = global_options; /* get_options unfortunately asserts if
    4641             :                                   this is the first time we run*/
    4642             : 
    4643         230 :   newoptions = options_new();
    4644         230 :   options_init(newoptions);
    4645         230 :   newoptions->command = command;
    4646         230 :   newoptions->command_arg = command_arg ? tor_strdup(command_arg) : NULL;
    4647             : 
    4648         230 :   smartlist_t *opened_files = smartlist_new();
    4649         688 :   for (int i = 0; i < 2; ++i) {
    4650         460 :     const char *body = i==0 ? cf_defaults : cf;
    4651         460 :     if (!body)
    4652           0 :       continue;
    4653             : 
    4654             :     /* get config lines, assign them */
    4655         689 :     retval = config_get_lines_include(body, &cl, 1,
    4656             :                                       body == cf ? &cf_has_include : NULL,
    4657             :                                       opened_files);
    4658         460 :     if (retval < 0) {
    4659           0 :       err = SETOPT_ERR_PARSE;
    4660           0 :       goto err;
    4661             :     }
    4662         460 :     retval = config_assign(get_options_mgr(), newoptions, cl,
    4663             :                            CAL_WARN_DEPRECATIONS, msg);
    4664         460 :     config_free_lines(cl);
    4665         460 :     if (retval < 0) {
    4666           2 :       err = SETOPT_ERR_PARSE;
    4667           2 :       goto err;
    4668             :     }
    4669         458 :     if (i==0)
    4670         230 :       newdefaultoptions = config_dup(get_options_mgr(), newoptions);
    4671             :   }
    4672             : 
    4673         228 :   if (newdefaultoptions == NULL) {
    4674           0 :     newdefaultoptions = config_dup(get_options_mgr(), global_default_options);
    4675             :   }
    4676             : 
    4677             :   /* Go through command-line variables too */
    4678             :   {
    4679         228 :     config_line_t *other_opts = NULL;
    4680         228 :     if (global_cmdline) {
    4681         225 :       other_opts = global_cmdline->other_opts;
    4682             :     }
    4683         228 :     retval = config_assign(get_options_mgr(), newoptions,
    4684             :                            other_opts,
    4685             :                            CAL_WARN_DEPRECATIONS, msg);
    4686             :   }
    4687         228 :   if (retval < 0) {
    4688           0 :     err = SETOPT_ERR_PARSE;
    4689           0 :     goto err;
    4690             :   }
    4691             : 
    4692         228 :   newoptions->IncludeUsed = cf_has_include;
    4693         228 :   newoptions->FilesOpenedByIncludes = opened_files;
    4694         228 :   opened_files = NULL; // prevent double-free.
    4695             : 
    4696             :   /* If this is a testing network configuration, change defaults
    4697             :    * for a list of dependent config options, and try this function again. */
    4698         228 :   if (newoptions->TestingTorNetwork && ! testing_network_configured) {
    4699             :     // retry with the testing defaults.
    4700           0 :     testing_network_configured = true;
    4701           0 :     retry = true;
    4702           0 :     goto err;
    4703             :   }
    4704             : 
    4705         228 :   err = options_validate_and_set(oldoptions, newoptions, msg);
    4706         228 :   if (err < 0) {
    4707          24 :     newoptions = NULL; // This was already freed in options_validate_and_set.
    4708          24 :     goto err;
    4709             :   }
    4710             : 
    4711         204 :   or_options_free(global_default_options);
    4712         204 :   global_default_options = newdefaultoptions;
    4713             : 
    4714         204 :   return SETOPT_OK;
    4715             : 
    4716          26 :  err:
    4717          26 :   in_option_validation = 0;
    4718          26 :   if (opened_files) {
    4719           2 :     SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f));
    4720           2 :     smartlist_free(opened_files);
    4721             :   }
    4722          26 :   or_options_free(newdefaultoptions);
    4723          26 :   or_options_free(newoptions);
    4724          26 :   if (*msg) {
    4725          25 :     char *old_msg = *msg;
    4726          25 :     tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg);
    4727          25 :     tor_free(old_msg);
    4728             :   }
    4729          26 :   if (retry)
    4730           0 :     return options_init_from_string(cf_defaults, cf, command, command_arg,
    4731             :                                     msg);
    4732             :   return err;
    4733             : }
    4734             : 
    4735             : /** Return the location for our configuration file.  May return NULL.
    4736             :  */
    4737             : const char *
    4738           0 : get_torrc_fname(int defaults_fname)
    4739             : {
    4740           0 :   const char *fname = defaults_fname ? torrc_defaults_fname : torrc_fname;
    4741             : 
    4742           0 :   if (fname)
    4743             :     return fname;
    4744             :   else
    4745           0 :     return get_default_conf_file(defaults_fname);
    4746             : }
    4747             : 
    4748             : /** Adjust the address map based on the MapAddress elements in the
    4749             :  * configuration <b>options</b>
    4750             :  */
    4751             : void
    4752          28 : config_register_addressmaps(const or_options_t *options)
    4753             : {
    4754          28 :   smartlist_t *elts;
    4755          28 :   config_line_t *opt;
    4756          28 :   const char *from, *to, *msg;
    4757             : 
    4758          28 :   addressmap_clear_configured();
    4759          28 :   elts = smartlist_new();
    4760          54 :   for (opt = options->AddressMap; opt; opt = opt->next) {
    4761          26 :     smartlist_split_string(elts, opt->value, NULL,
    4762             :                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
    4763          26 :     if (smartlist_len(elts) < 2) {
    4764           0 :       log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.",
    4765             :                opt->value);
    4766           0 :       goto cleanup;
    4767             :     }
    4768             : 
    4769          26 :     from = smartlist_get(elts,0);
    4770          26 :     to = smartlist_get(elts,1);
    4771             : 
    4772          26 :     if (to[0] == '.' || from[0] == '.') {
    4773           1 :       log_warn(LD_CONFIG,"MapAddress '%s' is ambiguous - address starts with a"
    4774             :               "'.'. Ignoring.",opt->value);
    4775           1 :       goto cleanup;
    4776             :     }
    4777             : 
    4778          25 :     if (addressmap_register_auto(from, to, 0, ADDRMAPSRC_TORRC, &msg) < 0) {
    4779           3 :       log_warn(LD_CONFIG,"MapAddress '%s' failed: %s. Ignoring.", opt->value,
    4780             :                msg);
    4781           3 :       goto cleanup;
    4782             :     }
    4783             : 
    4784          22 :     if (smartlist_len(elts) > 2)
    4785           0 :       log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress.");
    4786             : 
    4787          22 :   cleanup:
    4788          78 :     SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
    4789          26 :     smartlist_clear(elts);
    4790             :   }
    4791          28 :   smartlist_free(elts);
    4792          28 : }
    4793             : 
    4794             : /** As addressmap_register(), but detect the wildcarded status of "from" and
    4795             :  * "to", and do not steal a reference to <b>to</b>. */
    4796             : /* XXXX move to connection_edge.c */
    4797             : int
    4798          25 : addressmap_register_auto(const char *from, const char *to,
    4799             :                          time_t expires,
    4800             :                          addressmap_entry_source_t addrmap_source,
    4801             :                          const char **msg)
    4802             : {
    4803          25 :   int from_wildcard = 0, to_wildcard = 0;
    4804             : 
    4805          25 :   *msg = "whoops, forgot the error message";
    4806             : 
    4807          25 :   if (!strcmp(to, "*") || !strcmp(from, "*")) {
    4808           1 :     *msg = "can't remap from or to *";
    4809           1 :     return -1;
    4810             :   }
    4811             :   /* Detect asterisks in expressions of type: '*.example.com' */
    4812          24 :   if (!strncmp(from,"*.",2)) {
    4813           8 :     from += 2;
    4814           8 :     from_wildcard = 1;
    4815             :   }
    4816          24 :   if (!strncmp(to,"*.",2)) {
    4817           6 :     to += 2;
    4818           6 :     to_wildcard = 1;
    4819             :   }
    4820             : 
    4821          24 :   if (to_wildcard && !from_wildcard) {
    4822           2 :     *msg =  "can only use wildcard (i.e. '*.') if 'from' address "
    4823             :       "uses wildcard also";
    4824           2 :     return -1;
    4825             :   }
    4826             : 
    4827          22 :   if (address_is_invalid_destination(to, 1)) {
    4828           0 :     *msg = "destination is invalid";
    4829           0 :     return -1;
    4830             :   }
    4831             : 
    4832          22 :   addressmap_register(from, tor_strdup(to), expires, addrmap_source,
    4833             :                       from_wildcard, to_wildcard, 0);
    4834             : 
    4835          22 :   return 0;
    4836             : }
    4837             : 
    4838             : /**
    4839             :  * As add_file_log, but open the file as appropriate.
    4840             :  */
    4841             : STATIC int
    4842           2 : open_and_add_file_log(const log_severity_list_t *severity,
    4843             :                       const char *filename, int truncate_log)
    4844             : {
    4845           2 :   int open_flags = O_WRONLY|O_CREAT;
    4846           2 :   open_flags |= truncate_log ? O_TRUNC : O_APPEND;
    4847             : 
    4848           2 :   int fd = tor_open_cloexec(filename, open_flags, 0640);
    4849           2 :   if (fd < 0)
    4850             :     return -1;
    4851             : 
    4852           2 :   return add_file_log(severity, filename, fd);
    4853             : }
    4854             : 
    4855             : /**
    4856             :  * Try to set our global log granularity from `options->LogGranularity`,
    4857             :  * adjusting it as needed so that we are an even divisor of a second, or an
    4858             :  * even multiple of seconds. Return 0 on success, -1 on failure.
    4859             :  **/
    4860             : static int
    4861         578 : options_init_log_granularity(const or_options_t *options,
    4862             :                              int validate_only)
    4863             : {
    4864         578 :   if (options->LogTimeGranularity <= 0) {
    4865           1 :     log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.",
    4866             :              options->LogTimeGranularity);
    4867           1 :     return -1;
    4868         577 :   } else if (1000 % options->LogTimeGranularity != 0 &&
    4869           8 :              options->LogTimeGranularity % 1000 != 0) {
    4870           3 :     int granularity = options->LogTimeGranularity;
    4871           3 :     if (granularity < 40) {
    4872           1 :       do granularity++;
    4873           1 :       while (1000 % granularity != 0);
    4874           2 :     } else if (granularity < 1000) {
    4875           1 :       granularity = 1000 / granularity;
    4876           1 :       while (1000 % granularity != 0)
    4877           0 :         granularity--;
    4878           1 :       granularity = 1000 / granularity;
    4879             :     } else {
    4880           1 :       granularity = 1000 * ((granularity / 1000) + 1);
    4881             :     }
    4882           3 :     log_warn(LD_CONFIG, "Log time granularity '%d' has to be either a "
    4883             :                         "divisor or a multiple of 1 second. Changing to "
    4884             :                         "'%d'.",
    4885             :              options->LogTimeGranularity, granularity);
    4886           3 :     if (!validate_only)
    4887           3 :       set_log_time_granularity(granularity);
    4888             :   } else {
    4889         574 :     if (!validate_only)
    4890          16 :       set_log_time_granularity(options->LogTimeGranularity);
    4891             :   }
    4892             : 
    4893             :   return 0;
    4894             : }
    4895             : 
    4896             : /**
    4897             :  * Initialize the logs based on the configuration file.
    4898             :  */
    4899             : STATIC int
    4900         578 : options_init_logs(const or_options_t *old_options, const or_options_t *options,
    4901             :                   int validate_only)
    4902             : {
    4903         578 :   config_line_t *opt;
    4904         578 :   int ok;
    4905         578 :   smartlist_t *elts;
    4906         578 :   int run_as_daemon =
    4907             : #ifdef _WIN32
    4908             :                0;
    4909             : #else
    4910             :                options->RunAsDaemon;
    4911             : #endif
    4912             : 
    4913         578 :   if (options_init_log_granularity(options, validate_only) < 0)
    4914             :     return -1;
    4915             : 
    4916         577 :   ok = 1;
    4917         577 :   elts = smartlist_new();
    4918             : 
    4919         577 :   if (options->Logs == NULL && !run_as_daemon && !validate_only) {
    4920             :     /* When no logs are given, the default behavior is to log nothing (if
    4921             :        RunAsDaemon is set) or to log based on the quiet level otherwise. */
    4922          13 :     add_default_log_for_quiet_level(quiet_level);
    4923             :   }
    4924             : 
    4925         590 :   for (opt = options->Logs; opt; opt = opt->next) {
    4926          13 :     log_severity_list_t *severity;
    4927          13 :     const char *cfg = opt->value;
    4928          13 :     severity = tor_malloc_zero(sizeof(log_severity_list_t));
    4929          13 :     if (parse_log_severity_config(&cfg, severity) < 0) {
    4930           2 :       log_warn(LD_CONFIG, "Couldn't parse log levels in Log option 'Log %s'",
    4931             :                opt->value);
    4932           2 :       ok = 0; goto cleanup;
    4933             :     }
    4934             : 
    4935          11 :     smartlist_split_string(elts, cfg, NULL,
    4936             :                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
    4937             : 
    4938          11 :     if (smartlist_len(elts) == 0)
    4939           0 :       smartlist_add_strdup(elts, "stdout");
    4940             : 
    4941          11 :     if (smartlist_len(elts) == 1 &&
    4942           4 :         (!strcasecmp(smartlist_get(elts,0), "stdout") ||
    4943           0 :          !strcasecmp(smartlist_get(elts,0), "stderr"))) {
    4944           8 :       int err = smartlist_len(elts) &&
    4945           4 :         !strcasecmp(smartlist_get(elts,0), "stderr");
    4946           4 :       if (!validate_only) {
    4947           4 :         if (run_as_daemon) {
    4948           0 :           log_warn(LD_CONFIG,
    4949             :                    "Can't log to %s with RunAsDaemon set; skipping stdout",
    4950             :                    err?"stderr":"stdout");
    4951             :         } else {
    4952           8 :           add_stream_log(severity, err?"<stderr>":"<stdout>",
    4953             :                          fileno(err?stderr:stdout));
    4954             :         }
    4955             :       }
    4956           4 :       goto cleanup;
    4957             :     }
    4958           7 :     if (smartlist_len(elts) == 1) {
    4959           0 :       if (!strcasecmp(smartlist_get(elts,0), "syslog")) {
    4960             : #ifdef HAVE_SYSLOG_H
    4961           0 :         if (!validate_only) {
    4962           0 :           add_syslog_log(severity, options->SyslogIdentityTag);
    4963             :         }
    4964             : #else
    4965             :         log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry.");
    4966             : #endif /* defined(HAVE_SYSLOG_H) */
    4967           0 :         goto cleanup;
    4968             :       }
    4969             : 
    4970             :       /* We added this workaround in 0.4.5.x; we can remove it in 0.4.6 or
    4971             :        * later */
    4972           0 :       if (!strcasecmp(smartlist_get(elts, 0), "android")) {
    4973             : #ifdef HAVE_SYSLOG_H
    4974           0 :         log_warn(LD_CONFIG, "The android logging API is no longer supported;"
    4975             :                             " adding a syslog instead. The 'android' logging "
    4976             :                             " type will no longer work in the future.");
    4977           0 :         if (!validate_only) {
    4978           0 :           add_syslog_log(severity, options->SyslogIdentityTag);
    4979             :         }
    4980             : #else /* !defined(HAVE_SYSLOG_H) */
    4981             :         log_warn(LD_CONFIG, "The android logging API is no longer supported.");
    4982             : #endif /* defined(HAVE_SYSLOG_H) */
    4983           0 :         goto cleanup;
    4984             :       }
    4985             :     }
    4986             : 
    4987           7 :     if (smartlist_len(elts) == 2 &&
    4988           7 :         !strcasecmp(smartlist_get(elts,0), "file")) {
    4989           7 :       if (!validate_only) {
    4990           1 :         char *fname = expand_filename(smartlist_get(elts, 1));
    4991             :         /* Truncate if TruncateLogFile is set and we haven't seen this option
    4992             :            line before. */
    4993           1 :         int truncate_log = 0;
    4994           1 :         if (options->TruncateLogFile) {
    4995           0 :           truncate_log = 1;
    4996           0 :           if (old_options) {
    4997           0 :             config_line_t *opt2;
    4998           0 :             for (opt2 = old_options->Logs; opt2; opt2 = opt2->next)
    4999           0 :               if (!strcmp(opt->value, opt2->value)) {
    5000             :                 truncate_log = 0;
    5001             :                 break;
    5002             :               }
    5003             :           }
    5004             :         }
    5005           1 :         if (open_and_add_file_log(severity, fname, truncate_log) < 0) {
    5006           0 :           log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s",
    5007             :                    opt->value, strerror(errno));
    5008           0 :           ok = 0;
    5009             :         }
    5010           1 :         tor_free(fname);
    5011             :       }
    5012           7 :       goto cleanup;
    5013             :     }
    5014             : 
    5015           0 :     log_warn(LD_CONFIG, "Bad syntax on file Log option 'Log %s'",
    5016             :              opt->value);
    5017           0 :     ok = 0; goto cleanup;
    5018             : 
    5019          13 :   cleanup:
    5020          31 :     SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
    5021          13 :     smartlist_clear(elts);
    5022          13 :     tor_free(severity);
    5023             :   }
    5024         577 :   smartlist_free(elts);
    5025             : 
    5026         577 :   if (ok && !validate_only)
    5027          18 :     logs_set_domain_logging(options->LogMessageDomains);
    5028             : 
    5029         577 :   return ok?0:-1;
    5030             : }
    5031             : 
    5032             : /** Given a smartlist of SOCKS arguments to be passed to a transport
    5033             :  *  proxy in <b>args</b>, validate them and return -1 if they are
    5034             :  *  corrupted. Return 0 if they seem OK. */
    5035             : static int
    5036          53 : validate_transport_socks_arguments(const smartlist_t *args)
    5037             : {
    5038          53 :   char *socks_string = NULL;
    5039          53 :   size_t socks_string_len;
    5040             : 
    5041          53 :   tor_assert(args);
    5042          53 :   tor_assert(smartlist_len(args) > 0);
    5043             : 
    5044         123 :   SMARTLIST_FOREACH_BEGIN(args, const char *, s) {
    5045          71 :     if (!string_is_key_value(LOG_WARN, s)) { /* items should be k=v items */
    5046           1 :       log_warn(LD_CONFIG, "'%s' is not a k=v item.", s);
    5047           1 :       return -1;
    5048             :     }
    5049          70 :   } SMARTLIST_FOREACH_END(s);
    5050             : 
    5051          52 :   socks_string = pt_stringify_socks_args(args);
    5052          52 :   if (!socks_string)
    5053             :     return -1;
    5054             : 
    5055          52 :   socks_string_len = strlen(socks_string);
    5056          52 :   tor_free(socks_string);
    5057             : 
    5058          52 :   if (socks_string_len > MAX_SOCKS5_AUTH_SIZE_TOTAL) {
    5059           1 :     log_warn(LD_CONFIG, "SOCKS arguments can't be more than %u bytes (%lu).",
    5060             :              MAX_SOCKS5_AUTH_SIZE_TOTAL,
    5061             :              (unsigned long) socks_string_len);
    5062           1 :     return -1;
    5063             :   }
    5064             : 
    5065             :   return 0;
    5066             : }
    5067             : 
    5068             : /** Deallocate a bridge_line_t structure. */
    5069             : /* private */ void
    5070          34 : bridge_line_free_(bridge_line_t *bridge_line)
    5071             : {
    5072          34 :   if (!bridge_line)
    5073             :     return;
    5074             : 
    5075          27 :   if (bridge_line->socks_args) {
    5076          12 :     SMARTLIST_FOREACH(bridge_line->socks_args, char*, s, tor_free(s));
    5077           5 :     smartlist_free(bridge_line->socks_args);
    5078             :   }
    5079          27 :   tor_free(bridge_line->transport_name);
    5080          27 :   tor_free(bridge_line);
    5081             : }
    5082             : 
    5083             : /** Parse the contents of a string, <b>line</b>, containing a Bridge line,
    5084             :  * into a bridge_line_t.
    5085             :  *
    5086             :  * Validates that the IP:PORT, fingerprint, and SOCKS arguments (given to the
    5087             :  * Pluggable Transport, if a one was specified) are well-formed.
    5088             :  *
    5089             :  * Returns NULL If the Bridge line could not be validated, and returns a
    5090             :  * bridge_line_t containing the parsed information otherwise.
    5091             :  *
    5092             :  * Bridge line format:
    5093             :  * Bridge [transport] IP:PORT [id-fingerprint] [k=v] [k=v] ...
    5094             :  */
    5095             : /* private */ bridge_line_t *
    5096         148 : parse_bridge_line(const char *line)
    5097             : {
    5098         148 :   smartlist_t *items = NULL;
    5099         148 :   char *addrport=NULL, *fingerprint=NULL;
    5100         148 :   char *field=NULL;
    5101         148 :   bridge_line_t *bridge_line = tor_malloc_zero(sizeof(bridge_line_t));
    5102             : 
    5103         148 :   items = smartlist_new();
    5104         148 :   smartlist_split_string(items, line, NULL,
    5105             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
    5106         148 :   if (smartlist_len(items) < 1) {
    5107           1 :     log_warn(LD_CONFIG, "Too few arguments to Bridge line.");
    5108           1 :     goto err;
    5109             :   }
    5110             : 
    5111             :   /* first field is either a transport name or addrport */
    5112         147 :   field = smartlist_get(items, 0);
    5113         147 :   smartlist_del_keeporder(items, 0);
    5114             : 
    5115         147 :   if (string_is_C_identifier(field)) {
    5116             :     /* It's a transport name. */
    5117          72 :     bridge_line->transport_name = field;
    5118          72 :     if (smartlist_len(items) < 1) {
    5119           1 :       log_warn(LD_CONFIG, "Too few items to Bridge line.");
    5120           1 :       goto err;
    5121             :     }
    5122          71 :     addrport = smartlist_get(items, 0); /* Next field is addrport then. */
    5123          71 :     smartlist_del_keeporder(items, 0);
    5124             :   } else {
    5125             :     addrport = field;
    5126             :   }
    5127             : 
    5128         146 :   if (tor_addr_port_parse(LOG_INFO, addrport,
    5129             :                           &bridge_line->addr, &bridge_line->port, 443)<0) {
    5130           3 :     log_warn(LD_CONFIG, "Error parsing Bridge address '%s'", addrport);
    5131           3 :     goto err;
    5132             :   }
    5133             : 
    5134             :   /* If transports are enabled, next field could be a fingerprint or a
    5135             :      socks argument. If transports are disabled, next field must be
    5136             :      a fingerprint. */
    5137         143 :   if (smartlist_len(items)) {
    5138          88 :     if (bridge_line->transport_name) { /* transports enabled: */
    5139          70 :       field = smartlist_get(items, 0);
    5140          70 :       smartlist_del_keeporder(items, 0);
    5141             : 
    5142             :       /* If it's a key=value pair, then it's a SOCKS argument for the
    5143             :          transport proxy... */
    5144          70 :       if (string_is_key_value(LOG_DEBUG, field)) {
    5145          18 :         bridge_line->socks_args = smartlist_new();
    5146          18 :         smartlist_add(bridge_line->socks_args, field);
    5147             :       } else { /* ...otherwise, it's the bridge fingerprint. */
    5148             :         fingerprint = field;
    5149             :       }
    5150             : 
    5151             :     } else { /* transports disabled: */
    5152          18 :       fingerprint = smartlist_join_strings(items, "", 0, NULL);
    5153             :     }
    5154             :   }
    5155             : 
    5156             :   /* Handle fingerprint, if it was provided. */
    5157          88 :   if (fingerprint) {
    5158          70 :     if (strlen(fingerprint) != HEX_DIGEST_LEN) {
    5159           1 :       log_warn(LD_CONFIG, "Key digest for Bridge is wrong length.");
    5160           1 :       goto err;
    5161             :     }
    5162          69 :     if (base16_decode(bridge_line->digest, DIGEST_LEN,
    5163             :                       fingerprint, HEX_DIGEST_LEN) != DIGEST_LEN) {
    5164           0 :       log_warn(LD_CONFIG, "Unable to decode Bridge key digest.");
    5165           0 :       goto err;
    5166             :     }
    5167             :   }
    5168             : 
    5169             :   /* If we are using transports, any remaining items in the smartlist
    5170             :      should be k=v values. */
    5171         142 :   if (bridge_line->transport_name && smartlist_len(items)) {
    5172          36 :     if (!bridge_line->socks_args)
    5173          35 :       bridge_line->socks_args = smartlist_new();
    5174             : 
    5175             :     /* append remaining items of 'items' to 'socks_args' */
    5176          36 :     smartlist_add_all(bridge_line->socks_args, items);
    5177          36 :     smartlist_clear(items);
    5178             : 
    5179          36 :     tor_assert(smartlist_len(bridge_line->socks_args) > 0);
    5180             :   }
    5181             : 
    5182         142 :   if (bridge_line->socks_args) {
    5183          53 :     if (validate_transport_socks_arguments(bridge_line->socks_args) < 0)
    5184           2 :       goto err;
    5185             :   }
    5186             : 
    5187         140 :   goto done;
    5188             : 
    5189           8 :  err:
    5190           8 :   bridge_line_free(bridge_line);
    5191           8 :   bridge_line = NULL;
    5192             : 
    5193         148 :  done:
    5194         167 :   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    5195         148 :   smartlist_free(items);
    5196         148 :   tor_free(addrport);
    5197         148 :   tor_free(fingerprint);
    5198             : 
    5199         148 :   return bridge_line;
    5200             : }
    5201             : 
    5202             : /** Parse the contents of a TCPProxy line from <b>line</b> and put it
    5203             :  * in <b>options</b>. Return 0 if the line is well-formed, and -1 if it
    5204             :  * isn't.
    5205             :  *
    5206             :  * This will mutate only options->TCPProxyProtocol, options->TCPProxyAddr,
    5207             :  * and options->TCPProxyPort.
    5208             :  *
    5209             :  * On error, tor_strdup an error explanation into *<b>msg</b>.
    5210             :  */
    5211             : STATIC int
    5212           4 : parse_tcp_proxy_line(const char *line, or_options_t *options, char **msg)
    5213             : {
    5214           4 :   int ret = 0;
    5215           4 :   tor_assert(line);
    5216           4 :   tor_assert(options);
    5217           4 :   tor_assert(msg);
    5218             : 
    5219           4 :   smartlist_t *sl = smartlist_new();
    5220             :   /* Split between the protocol and the address/port. */
    5221           4 :   smartlist_split_string(sl, line, " ",
    5222             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
    5223             : 
    5224             :   /* The address/port is not specified. */
    5225           4 :   if (smartlist_len(sl) < 2) {
    5226           1 :     *msg = tor_strdup("TCPProxy has no address/port. Please fix.");
    5227           1 :     goto err;
    5228             :   }
    5229             : 
    5230           3 :   char *protocol_string = smartlist_get(sl, 0);
    5231           3 :   char *addrport_string = smartlist_get(sl, 1);
    5232             : 
    5233             :   /* The only currently supported protocol is 'haproxy'. */
    5234           3 :   if (strcasecmp(protocol_string, "haproxy")) {
    5235           1 :     *msg = tor_strdup("TCPProxy protocol is not supported. Currently "
    5236             :                       "the only supported protocol is 'haproxy'. "
    5237             :                       "Please fix.");
    5238           1 :     goto err;
    5239             :   } else {
    5240             :     /* Otherwise, set the correct protocol. */
    5241           2 :     options->TCPProxyProtocol = TCP_PROXY_PROTOCOL_HAPROXY;
    5242             :   }
    5243             : 
    5244             :   /* Parse the address/port. */
    5245           2 :   if (tor_addr_port_lookup(addrport_string, &options->TCPProxyAddr,
    5246             :                            &options->TCPProxyPort) < 0) {
    5247           1 :     *msg = tor_strdup("TCPProxy address/port failed to parse or resolve. "
    5248             :                       "Please fix.");
    5249           1 :     goto err;
    5250             :   }
    5251             : 
    5252             :   /* Success. */
    5253           1 :   ret = 0;
    5254           1 :   goto end;
    5255             : 
    5256             :  err:
    5257             :   ret = -1;
    5258           4 :  end:
    5259          11 :   SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
    5260           4 :   smartlist_free(sl);
    5261           4 :   return ret;
    5262             : }
    5263             : 
    5264             : /** Read the contents of a ClientTransportPlugin or ServerTransportPlugin
    5265             :  * line from <b>line</b>, depending on the value of <b>server</b>. Return 0
    5266             :  * if the line is well-formed, and -1 if it isn't.
    5267             :  *
    5268             :  * If <b>validate_only</b> is 0, the line is well-formed, and the transport is
    5269             :  * needed by some bridge:
    5270             :  * - If it's an external proxy line, add the transport described in the line to
    5271             :  * our internal transport list.
    5272             :  * - If it's a managed proxy line, launch the managed proxy.
    5273             :  */
    5274             : int
    5275          65 : pt_parse_transport_line(const or_options_t *options,
    5276             :                      const char *line, int validate_only,
    5277             :                      int server)
    5278             : {
    5279             : 
    5280          65 :   smartlist_t *items = NULL;
    5281          65 :   int r;
    5282          65 :   const char *transports = NULL;
    5283          65 :   smartlist_t *transport_list = NULL;
    5284          65 :   char *type = NULL;
    5285          65 :   char *addrport = NULL;
    5286          65 :   tor_addr_t addr;
    5287          65 :   uint16_t port = 0;
    5288          65 :   int socks_ver = PROXY_NONE;
    5289             : 
    5290             :   /* managed proxy options */
    5291          65 :   int is_managed = 0;
    5292          65 :   char **proxy_argv = NULL;
    5293          65 :   char **tmp = NULL;
    5294          65 :   int proxy_argc, i;
    5295          65 :   int is_useless_proxy = 1;
    5296             : 
    5297          65 :   int line_length;
    5298             : 
    5299             :   /* Split the line into space-separated tokens */
    5300          65 :   items = smartlist_new();
    5301          65 :   smartlist_split_string(items, line, NULL,
    5302             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
    5303          65 :   line_length = smartlist_len(items);
    5304             : 
    5305          65 :   if (line_length < 3) {
    5306           9 :     log_warn(LD_CONFIG,
    5307             :              "Too few arguments on %sTransportPlugin line.",
    5308             :              server ? "Server" : "Client");
    5309           6 :     goto err;
    5310             :   }
    5311             : 
    5312             :   /* Get the first line element, split it to commas into
    5313             :      transport_list (in case it's multiple transports) and validate
    5314             :      the transport names. */
    5315          59 :   transports = smartlist_get(items, 0);
    5316          59 :   transport_list = smartlist_new();
    5317          59 :   smartlist_split_string(transport_list, transports, ",",
    5318             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    5319         120 :   SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) {
    5320             :     /* validate transport names */
    5321          63 :     if (!string_is_C_identifier(transport_name)) {
    5322           2 :       log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
    5323             :                transport_name);
    5324           2 :       goto err;
    5325             :     }
    5326             : 
    5327             :     /* see if we actually need the transports provided by this proxy */
    5328          61 :     if (!validate_only && transport_is_needed(transport_name))
    5329           2 :       is_useless_proxy = 0;
    5330          61 :   } SMARTLIST_FOREACH_END(transport_name);
    5331             : 
    5332          57 :   type = smartlist_get(items, 1);
    5333          57 :   if (!strcmp(type, "exec")) {
    5334             :     is_managed = 1;
    5335          13 :   } else if (server && !strcmp(type, "proxy")) {
    5336             :     /* 'proxy' syntax only with ServerTransportPlugin */
    5337             :     is_managed = 0;
    5338           8 :   } else if (!server && !strcmp(type, "socks4")) {
    5339             :     /* 'socks4' syntax only with ClientTransportPlugin */
    5340             :     is_managed = 0;
    5341             :     socks_ver = PROXY_SOCKS4;
    5342           7 :   } else if (!server && !strcmp(type, "socks5")) {
    5343             :     /* 'socks5' syntax only with ClientTransportPlugin */
    5344             :     is_managed = 0;
    5345             :     socks_ver = PROXY_SOCKS5;
    5346             :   } else {
    5347           3 :     log_warn(LD_CONFIG,
    5348             :              "Strange %sTransportPlugin type '%s'",
    5349             :              server ? "Server" : "Client", type);
    5350           2 :     goto err;
    5351             :   }
    5352             : 
    5353          44 :   if (is_managed && options->Sandbox) {
    5354           3 :     log_warn(LD_CONFIG,
    5355             :              "Managed proxies are not compatible with Sandbox mode."
    5356             :              "(%sTransportPlugin line was %s)",
    5357             :              server ? "Server" : "Client", escaped(line));
    5358           2 :     goto err;
    5359             :   }
    5360             : 
    5361          53 :   if (is_managed && options->NoExec) {
    5362           0 :     log_warn(LD_CONFIG,
    5363             :              "Managed proxies are not compatible with NoExec mode; ignoring."
    5364             :              "(%sTransportPlugin line was %s)",
    5365             :              server ? "Server" : "Client", escaped(line));
    5366           0 :     r = 0;
    5367           0 :     goto done;
    5368             :   }
    5369             : 
    5370          53 :   if (is_managed) {
    5371             :     /* managed */
    5372             : 
    5373          42 :     if (!server && !validate_only && is_useless_proxy) {
    5374           1 :       log_info(LD_GENERAL,
    5375             :                "Pluggable transport proxy (%s) does not provide "
    5376             :                "any needed transports and will not be launched.",
    5377             :                line);
    5378             :     }
    5379             : 
    5380             :     /*
    5381             :      * If we are not just validating, use the rest of the line as the
    5382             :      * argv of the proxy to be launched. Also, make sure that we are
    5383             :      * only launching proxies that contribute useful transports.
    5384             :      */
    5385             : 
    5386          42 :     if (!validate_only && (server || !is_useless_proxy)) {
    5387          17 :       proxy_argc = line_length - 2;
    5388          17 :       tor_assert(proxy_argc > 0);
    5389          17 :       proxy_argv = tor_calloc((proxy_argc + 1), sizeof(char *));
    5390          17 :       tmp = proxy_argv;
    5391             : 
    5392          51 :       for (i = 0; i < proxy_argc; i++) {
    5393             :         /* store arguments */
    5394          17 :         *tmp++ = smartlist_get(items, 2);
    5395          17 :         smartlist_del_keeporder(items, 2);
    5396             :       }
    5397          17 :       *tmp = NULL; /* terminated with NULL, just like execve() likes it */
    5398             : 
    5399             :       /* kickstart the thing */
    5400          17 :       if (server) {
    5401          16 :         pt_kickstart_server_proxy(transport_list, proxy_argv);
    5402             :       } else {
    5403           1 :         pt_kickstart_client_proxy(transport_list, proxy_argv);
    5404             :       }
    5405             :     }
    5406             :   } else {
    5407             :     /* external */
    5408             : 
    5409             :     /* ClientTransportPlugins connecting through a proxy is managed only. */
    5410          11 :     if (!server && (options->Socks4Proxy || options->Socks5Proxy ||
    5411           6 :                     options->HTTPSProxy || options->TCPProxy)) {
    5412           0 :       log_warn(LD_CONFIG, "You have configured an external proxy with another "
    5413             :                           "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy|"
    5414             :                           "TCPProxy)");
    5415           0 :       goto err;
    5416             :     }
    5417             : 
    5418          11 :     if (smartlist_len(transport_list) != 1) {
    5419           2 :       log_warn(LD_CONFIG,
    5420             :                "You can't have an external proxy with more than "
    5421             :                "one transport.");
    5422           2 :       goto err;
    5423             :     }
    5424             : 
    5425           9 :     addrport = smartlist_get(items, 2);
    5426             : 
    5427           9 :     if (tor_addr_port_lookup(addrport, &addr, &port) < 0) {
    5428           2 :       log_warn(LD_CONFIG,
    5429             :                "Error parsing transport address '%s'", addrport);
    5430           2 :       goto err;
    5431             :     }
    5432             : 
    5433           7 :     if (!port) {
    5434           2 :       log_warn(LD_CONFIG,
    5435             :                "Transport address '%s' has no port.", addrport);
    5436           2 :       goto err;
    5437             :     }
    5438             : 
    5439           5 :     if (!validate_only) {
    5440           3 :       log_info(LD_DIR, "%s '%s' at %s.",
    5441             :                server ? "Server transport" : "Transport",
    5442             :                transports, fmt_addrport(&addr, port));
    5443             : 
    5444           2 :       if (!server) {
    5445           1 :         transport_add_from_config(&addr, port,
    5446           1 :                                   smartlist_get(transport_list, 0),
    5447             :                                   socks_ver);
    5448             :       }
    5449             :     }
    5450             :   }
    5451             : 
    5452          47 :   r = 0;
    5453          47 :   goto done;
    5454             : 
    5455             :  err:
    5456             :   r = -1;
    5457             : 
    5458          65 :  done:
    5459         233 :   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    5460          65 :   smartlist_free(items);
    5461          65 :   if (transport_list) {
    5462         122 :     SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s));
    5463          59 :     smartlist_free(transport_list);
    5464             :   }
    5465             : 
    5466          65 :   return r;
    5467             : }
    5468             : 
    5469             : /**
    5470             :  * Parse a flag describing an extra dirport for a directory authority.
    5471             :  *
    5472             :  * Right now, the supported format is exactly:
    5473             :  * `{upload,download,voting}=http://[IP:PORT]/`.
    5474             :  * Other URL schemes, and other suffixes, might be supported in the future.
    5475             :  *
    5476             :  * Only call this function if `flag` starts with one of the above strings.
    5477             :  *
    5478             :  * Return 0 on success, and -1 on failure.
    5479             :  *
    5480             :  * If `ds` is provided, then add any parsed dirport to `ds`.  If `ds` is NULL,
    5481             :  * take no action other than parsing.
    5482             :  **/
    5483             : static int
    5484          11 : parse_dirauth_dirport(dir_server_t *ds, const char *flag)
    5485             : {
    5486          11 :   tor_assert(flag);
    5487             : 
    5488          11 :   auth_dirport_usage_t usage;
    5489             : 
    5490          11 :   if (!strcasecmpstart(flag, "upload=")) {
    5491             :     usage = AUTH_USAGE_UPLOAD;
    5492           4 :   } else if (!strcasecmpstart(flag, "download=")) {
    5493             :     usage = AUTH_USAGE_DOWNLOAD;
    5494           2 :   } else if (!strcasecmpstart(flag, "vote=")) {
    5495             :     usage = AUTH_USAGE_VOTING;
    5496             :   } else {
    5497             :     // We shouldn't get called with a flag that we don't recognize.
    5498           0 :     tor_assert_nonfatal_unreached();
    5499           0 :     return -1;
    5500             :   }
    5501             : 
    5502          11 :   const char *eq = strchr(flag, '=');
    5503          11 :   tor_assert(eq);
    5504          11 :   const char *target = eq + 1;
    5505             : 
    5506             :   // Find the part inside the http://{....}/
    5507          11 :   if (strcmpstart(target, "http://")) {
    5508           1 :     log_warn(LD_CONFIG, "Unsupported URL scheme in authority flag %s", flag);
    5509           1 :     return -1;
    5510             :   }
    5511          10 :   const char *addr = target + strlen("http://");
    5512             : 
    5513          10 :   const char *eos = strchr(addr, '/');
    5514          10 :   size_t addr_len;
    5515          10 :   if (eos && strcmp(eos, "/")) {
    5516           1 :     log_warn(LD_CONFIG, "Unsupported URL prefix in authority flag %s", flag);
    5517           1 :     return -1;
    5518           9 :   } else if (eos) {
    5519           7 :     addr_len = eos - addr;
    5520             :   } else {
    5521           2 :     addr_len = strlen(addr);
    5522             :   }
    5523             : 
    5524             :   // Finally, parse the addr:port part.
    5525           9 :   char *addr_string = tor_strndup(addr, addr_len);
    5526           9 :   tor_addr_port_t dirport;
    5527           9 :   memset(&dirport, 0, sizeof(dirport));
    5528           9 :   int rv = tor_addr_port_parse(LOG_WARN, addr_string,
    5529             :                                &dirport.addr, &dirport.port, -1);
    5530           9 :   if (ds != NULL && rv == 0) {
    5531           4 :     trusted_dir_server_add_dirport(ds, usage, &dirport);
    5532           5 :   } else if (rv == -1) {
    5533           2 :     log_warn(LD_CONFIG, "Unable to parse address in authority flag %s",flag);
    5534             :   }
    5535             : 
    5536           9 :   tor_free(addr_string);
    5537           9 :   return rv;
    5538             : }
    5539             : 
    5540             : /** Read the contents of a DirAuthority line from <b>line</b>. If
    5541             :  * <b>validate_only</b> is 0, and the line is well-formed, and it
    5542             :  * shares any bits with <b>required_type</b> or <b>required_type</b>
    5543             :  * is NO_DIRINFO (zero), then add the dirserver described in the line
    5544             :  * (minus whatever bits it's missing) as a valid authority.
    5545             :  * Return 0 on success or filtering out by type,
    5546             :  * or -1 if the line isn't well-formed or if we can't add it. */
    5547             : STATIC int
    5548        2315 : parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
    5549             :                          int validate_only)
    5550             : {
    5551        2315 :   smartlist_t *items = NULL;
    5552        2315 :   int r;
    5553        2315 :   char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
    5554        2315 :   tor_addr_port_t ipv6_addrport, *ipv6_addrport_ptr = NULL;
    5555        2315 :   uint16_t dir_port = 0, or_port = 0;
    5556        2315 :   char digest[DIGEST_LEN];
    5557        2315 :   char v3_digest[DIGEST_LEN];
    5558        2315 :   dirinfo_type_t type = 0;
    5559        2315 :   double weight = 1.0;
    5560        2315 :   smartlist_t *extra_dirports = smartlist_new();
    5561             : 
    5562        2315 :   memset(v3_digest, 0, sizeof(v3_digest));
    5563             : 
    5564        2315 :   items = smartlist_new();
    5565        2315 :   smartlist_split_string(items, line, NULL,
    5566             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
    5567        2315 :   if (smartlist_len(items) < 1) {
    5568           0 :     log_warn(LD_CONFIG, "No arguments on DirAuthority line.");
    5569           0 :     goto err;
    5570             :   }
    5571             : 
    5572        2315 :   if (is_legal_nickname(smartlist_get(items, 0))) {
    5573        2315 :     nickname = smartlist_get(items, 0);
    5574        2315 :     smartlist_del_keeporder(items, 0);
    5575             :   }
    5576             : 
    5577        8082 :   while (smartlist_len(items)) {
    5578        8082 :     char *flag = smartlist_get(items, 0);
    5579        8082 :     if (TOR_ISDIGIT(flag[0]))
    5580             :       break;
    5581        5767 :     if (!strcasecmp(flag, "hs") ||
    5582        5767 :                !strcasecmp(flag, "no-hs")) {
    5583           0 :       log_warn(LD_CONFIG, "The DirAuthority options 'hs' and 'no-hs' are "
    5584             :                "obsolete; you don't need them any more.");
    5585        5767 :     } else if (!strcasecmp(flag, "bridge")) {
    5586         228 :       type |= BRIDGE_DIRINFO;
    5587        5539 :     } else if (!strcasecmp(flag, "no-v2")) {
    5588             :       /* obsolete, but may still be contained in DirAuthority lines generated
    5589             :          by various tools */;
    5590        5539 :     } else if (!strcasecmpstart(flag, "orport=")) {
    5591        2315 :       int ok;
    5592        2315 :       char *portstring = flag + strlen("orport=");
    5593        2315 :       or_port = (uint16_t) tor_parse_long(portstring, 10, 1, 65535, &ok, NULL);
    5594        2315 :       if (!ok)
    5595           0 :         log_warn(LD_CONFIG, "Invalid orport '%s' on DirAuthority line.",
    5596             :                  portstring);
    5597        3224 :     } else if (!strcmpstart(flag, "weight=")) {
    5598           0 :       int ok;
    5599           0 :       const char *wstring = flag + strlen("weight=");
    5600           0 :       weight = tor_parse_double(wstring, 0, (double)UINT64_MAX, &ok, NULL);
    5601           0 :       if (!ok) {
    5602           0 :         log_warn(LD_CONFIG, "Invalid weight '%s' on DirAuthority line.",flag);
    5603           0 :         weight=1.0;
    5604             :       }
    5605        3224 :     } else if (!strcasecmpstart(flag, "v3ident=")) {
    5606        2087 :       char *idstr = flag + strlen("v3ident=");
    5607        4174 :       if (strlen(idstr) != HEX_DIGEST_LEN ||
    5608        2087 :           base16_decode(v3_digest, DIGEST_LEN,
    5609             :                         idstr, HEX_DIGEST_LEN) != DIGEST_LEN) {
    5610           0 :         log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirAuthority line",
    5611             :                  flag);
    5612             :       } else {
    5613        2087 :         type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO;
    5614             :       }
    5615        1137 :     } else if (!strcasecmpstart(flag, "ipv6=")) {
    5616        1121 :       if (ipv6_addrport_ptr) {
    5617           0 :         log_warn(LD_CONFIG, "Redundant ipv6 addr/port on DirAuthority line");
    5618             :       } else {
    5619        1121 :         if (tor_addr_port_parse(LOG_WARN, flag+strlen("ipv6="),
    5620             :                                 &ipv6_addrport.addr, &ipv6_addrport.port,
    5621             :                                 -1) < 0
    5622        1121 :             || tor_addr_family(&ipv6_addrport.addr) != AF_INET6) {
    5623           0 :           log_warn(LD_CONFIG, "Bad ipv6 addr/port %s on DirAuthority line",
    5624             :                    escaped(flag));
    5625           0 :           goto err;
    5626             :         }
    5627             :         ipv6_addrport_ptr = &ipv6_addrport;
    5628             :       }
    5629          25 :     } else if (!strcasecmpstart(flag, "upload=") ||
    5630          16 :                !strcasecmpstart(flag, "download=") ||
    5631           7 :                !strcasecmpstart(flag, "vote=")) {
    5632             :       // We'll handle these after creating the authority object.
    5633          11 :       smartlist_add(extra_dirports, flag);
    5634          11 :       flag =  NULL; // prevent double-free.
    5635             :     } else {
    5636           5 :       log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirAuthority line",
    5637             :                flag);
    5638             :     }
    5639        5767 :     tor_free(flag);
    5640        5767 :     smartlist_del_keeporder(items, 0);
    5641             :   }
    5642             : 
    5643        2315 :   if (smartlist_len(items) < 2) {
    5644           0 :     log_warn(LD_CONFIG, "Too few arguments to DirAuthority line.");
    5645           0 :     goto err;
    5646             :   }
    5647        2315 :   addrport = smartlist_get(items, 0);
    5648        2315 :   smartlist_del_keeporder(items, 0);
    5649             : 
    5650        2315 :   if (tor_addr_port_split(LOG_WARN, addrport, &address, &dir_port) < 0) {
    5651           0 :     log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s'.", addrport);
    5652           0 :     goto err;
    5653             :   }
    5654             : 
    5655        2315 :   if (!string_is_valid_ipv4_address(address)) {
    5656           2 :     log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' "
    5657             :                         "(invalid IPv4 address)", address);
    5658           2 :     goto err;
    5659             :   }
    5660             : 
    5661        2313 :   if (!dir_port) {
    5662           0 :     log_warn(LD_CONFIG, "Missing port in DirAuthority address '%s'",addrport);
    5663           0 :     goto err;
    5664             :   }
    5665             : 
    5666        2313 :   fingerprint = smartlist_join_strings(items, "", 0, NULL);
    5667        2313 :   if (strlen(fingerprint) != HEX_DIGEST_LEN) {
    5668           0 :     log_warn(LD_CONFIG, "Key digest '%s' for DirAuthority is wrong length %d.",
    5669             :              fingerprint, (int)strlen(fingerprint));
    5670           0 :     goto err;
    5671             :   }
    5672        2313 :   if (base16_decode(digest, DIGEST_LEN,
    5673             :                     fingerprint, HEX_DIGEST_LEN) != DIGEST_LEN) {
    5674           0 :     log_warn(LD_CONFIG, "Unable to decode DirAuthority key digest.");
    5675           0 :     goto err;
    5676             :   }
    5677             : 
    5678        2313 :   if (validate_only) {
    5679          64 :     SMARTLIST_FOREACH_BEGIN(extra_dirports, const char *, cp) {
    5680           7 :       if (parse_dirauth_dirport(NULL, cp) < 0)
    5681           4 :         goto err;
    5682           3 :     } SMARTLIST_FOREACH_END(cp);
    5683             :   }
    5684             : 
    5685        2309 :   if (!validate_only && (!required_type || required_type & type)) {
    5686        2221 :     dir_server_t *ds;
    5687        2221 :     if (required_type)
    5688        2209 :       type &= required_type; /* pare down what we think of them as an
    5689             :                               * authority for. */
    5690        2221 :     log_debug(LD_DIR, "Trusted %d dirserver at %s:%d (%s)", (int)type,
    5691             :               address, (int)dir_port, (char*)smartlist_get(items,0));
    5692        2221 :     if (!(ds = trusted_dir_server_new(nickname, address, dir_port, or_port,
    5693             :                                       ipv6_addrport_ptr,
    5694             :                                       digest, v3_digest, type, weight)))
    5695           0 :       goto err;
    5696             : 
    5697        2225 :     SMARTLIST_FOREACH_BEGIN(extra_dirports, const char *, cp) {
    5698           4 :       if (parse_dirauth_dirport(ds, cp) < 0)
    5699           0 :         goto err;
    5700           4 :     } SMARTLIST_FOREACH_END(cp);
    5701        2221 :     dir_server_add(ds);
    5702             :   }
    5703             : 
    5704        2309 :   r = 0;
    5705        2309 :   goto done;
    5706             : 
    5707             :  err:
    5708             :   r = -1;
    5709             : 
    5710        2315 :  done:
    5711        2326 :   SMARTLIST_FOREACH(extra_dirports, char*, s, tor_free(s));
    5712        2315 :   smartlist_free(extra_dirports);
    5713       25461 :   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    5714        2315 :   smartlist_free(items);
    5715        2315 :   tor_free(addrport);
    5716        2315 :   tor_free(address);
    5717        2315 :   tor_free(nickname);
    5718        2315 :   tor_free(fingerprint);
    5719        2315 :   return r;
    5720             : }
    5721             : 
    5722             : /** Read the contents of a FallbackDir line from <b>line</b>. If
    5723             :  * <b>validate_only</b> is 0, and the line is well-formed, then add the
    5724             :  * dirserver described in the line as a fallback directory. Return 0 on
    5725             :  * success, or -1 if the line isn't well-formed or if we can't add it. */
    5726             : int
    5727       42210 : parse_dir_fallback_line(const char *line,
    5728             :                         int validate_only)
    5729             : {
    5730       42210 :   int r = -1;
    5731       42210 :   smartlist_t *items = smartlist_new(), *positional = smartlist_new();
    5732       42210 :   int orport = -1;
    5733       42210 :   uint16_t dirport;
    5734       42210 :   tor_addr_t addr;
    5735       42210 :   int ok;
    5736       42210 :   char id[DIGEST_LEN];
    5737       42210 :   char *address=NULL;
    5738       42210 :   tor_addr_port_t ipv6_addrport, *ipv6_addrport_ptr = NULL;
    5739       42210 :   double weight=1.0;
    5740             : 
    5741       42210 :   memset(id, 0, sizeof(id));
    5742       42210 :   smartlist_split_string(items, line, NULL,
    5743             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
    5744      183822 :   SMARTLIST_FOREACH_BEGIN(items, const char *, cp) {
    5745      141612 :     const char *eq = strchr(cp, '=');
    5746      141612 :     ok = 1;
    5747      141612 :     if (! eq) {
    5748       42210 :       smartlist_add(positional, (char*)cp);
    5749       42210 :       continue;
    5750             :     }
    5751       99402 :     if (!strcmpstart(cp, "orport=")) {
    5752       42210 :       orport = (int)tor_parse_long(cp+strlen("orport="), 10,
    5753             :                                    1, 65535, &ok, NULL);
    5754       57192 :     } else if (!strcmpstart(cp, "id=")) {
    5755       84420 :       ok = base16_decode(id, DIGEST_LEN, cp+strlen("id="),
    5756       42210 :                          strlen(cp)-strlen("id=")) == DIGEST_LEN;
    5757       14982 :     } else if (!strcasecmpstart(cp, "ipv6=")) {
    5758       14982 :       if (ipv6_addrport_ptr) {
    5759           0 :         log_warn(LD_CONFIG, "Redundant ipv6 addr/port on FallbackDir line");
    5760             :       } else {
    5761       14982 :         if (tor_addr_port_parse(LOG_WARN, cp+strlen("ipv6="),
    5762             :                                 &ipv6_addrport.addr, &ipv6_addrport.port,
    5763             :                                 -1) < 0
    5764       14982 :             || tor_addr_family(&ipv6_addrport.addr) != AF_INET6) {
    5765           0 :           log_warn(LD_CONFIG, "Bad ipv6 addr/port %s on FallbackDir line",
    5766             :                    escaped(cp));
    5767           0 :           goto end;
    5768             :         }
    5769             :         ipv6_addrport_ptr = &ipv6_addrport;
    5770             :       }
    5771           0 :     } else if (!strcmpstart(cp, "weight=")) {
    5772           0 :       int num_ok;
    5773           0 :       const char *wstring = cp + strlen("weight=");
    5774           0 :       weight = tor_parse_double(wstring, 0, (double)UINT64_MAX, &num_ok, NULL);
    5775           0 :       if (!num_ok) {
    5776           0 :         log_warn(LD_CONFIG, "Invalid weight '%s' on FallbackDir line.", cp);
    5777           0 :         weight=1.0;
    5778             :       }
    5779             :     }
    5780             : 
    5781       99402 :     if (!ok) {
    5782           0 :       log_warn(LD_CONFIG, "Bad FallbackDir option %s", escaped(cp));
    5783           0 :       goto end;
    5784             :     }
    5785      141612 :   } SMARTLIST_FOREACH_END(cp);
    5786             : 
    5787       42210 :   if (smartlist_len(positional) != 1) {
    5788           0 :     log_warn(LD_CONFIG, "Couldn't parse FallbackDir line %s", escaped(line));
    5789           0 :     goto end;
    5790             :   }
    5791             : 
    5792       42210 :   if (tor_digest_is_zero(id)) {
    5793           0 :     log_warn(LD_CONFIG, "Missing identity on FallbackDir line");
    5794           0 :     goto end;
    5795             :   }
    5796             : 
    5797       42210 :   if (orport <= 0) {
    5798           0 :     log_warn(LD_CONFIG, "Missing orport on FallbackDir line");
    5799           0 :     goto end;
    5800             :   }
    5801             : 
    5802       42210 :   if (tor_addr_port_split(LOG_INFO, smartlist_get(positional, 0),
    5803       42210 :                           &address, &dirport) < 0 ||
    5804       42210 :       tor_addr_parse(&addr, address)<0) {
    5805           0 :     log_warn(LD_CONFIG, "Couldn't parse address:port %s on FallbackDir line",
    5806             :              (const char*)smartlist_get(positional, 0));
    5807           0 :     goto end;
    5808             :   }
    5809             : 
    5810       42210 :   if (!validate_only) {
    5811       42208 :     dir_server_t *ds;
    5812       42208 :     ds = fallback_dir_server_new(&addr, dirport, orport, ipv6_addrport_ptr,
    5813             :                                  id, weight);
    5814       42208 :     if (!ds) {
    5815           0 :       log_warn(LD_CONFIG, "Couldn't create FallbackDir %s", escaped(line));
    5816           0 :       goto end;
    5817             :     }
    5818       42208 :     dir_server_add(ds);
    5819             :   }
    5820             : 
    5821             :   r = 0;
    5822             : 
    5823       42210 :  end:
    5824      183822 :   SMARTLIST_FOREACH(items, char *, cp, tor_free(cp));
    5825       42210 :   smartlist_free(items);
    5826       42210 :   smartlist_free(positional);
    5827       42210 :   tor_free(address);
    5828       42210 :   return r;
    5829             : }
    5830             : 
    5831             : /** Allocate and return a new port_cfg_t with reasonable defaults.
    5832             :  *
    5833             :  * <b>namelen</b> is the length of the unix socket name
    5834             :  * (typically the filesystem path), not including the trailing NUL.
    5835             :  * It should be 0 for ports that are not zunix sockets. */
    5836             : port_cfg_t *
    5837        1272 : port_cfg_new(size_t namelen)
    5838             : {
    5839        1272 :   tor_assert(namelen <= SIZE_T_CEILING - sizeof(port_cfg_t) - 1);
    5840        1272 :   port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t) + namelen + 1);
    5841             : 
    5842             :   /* entry_cfg flags */
    5843        1272 :   cfg->entry_cfg.ipv4_traffic = 1;
    5844        1272 :   cfg->entry_cfg.ipv6_traffic = 1;
    5845        1272 :   cfg->entry_cfg.prefer_ipv6 = 0;
    5846        1272 :   cfg->entry_cfg.dns_request = 1;
    5847        1272 :   cfg->entry_cfg.onion_traffic = 1;
    5848        1272 :   cfg->entry_cfg.prefer_ipv6_virtaddr = 1;
    5849        1272 :   cfg->entry_cfg.session_group = SESSION_GROUP_UNSET;
    5850        1272 :   cfg->entry_cfg.isolation_flags = ISO_DEFAULT;
    5851             : 
    5852             :   /* Other flags default to 0 due to tor_malloc_zero */
    5853        1272 :   return cfg;
    5854             : }
    5855             : 
    5856             : /** Free all storage held in <b>port</b> */
    5857             : void
    5858        1231 : port_cfg_free_(port_cfg_t *port)
    5859             : {
    5860        1231 :   tor_free(port);
    5861        1231 : }
    5862             : 
    5863             : /** Warn for every port in <b>ports</b> of type <b>listener_type</b> that is
    5864             :  * on a publicly routable address. */
    5865             : static void
    5866           5 : warn_nonlocal_client_ports(const smartlist_t *ports,
    5867             :                            const char *portname,
    5868             :                            const int listener_type)
    5869             : {
    5870          14 :   SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
    5871           9 :     if (port->type != listener_type)
    5872           4 :       continue;
    5873           5 :     if (port->is_unix_addr) {
    5874             :       /* Unix sockets aren't accessible over a network. */
    5875           5 :     } else if (!tor_addr_is_internal(&port->addr, 1)) {
    5876           0 :       log_warn(LD_CONFIG, "You specified a public address '%s' for %sPort. "
    5877             :                "Other people on the Internet might find your computer and "
    5878             :                "use it as an open proxy. Please don't allow this unless you "
    5879             :                "have a good reason.",
    5880             :                fmt_addrport(&port->addr, port->port), portname);
    5881           5 :     } else if (!tor_addr_is_loopback(&port->addr)) {
    5882           0 :       log_notice(LD_CONFIG, "You configured a non-loopback address '%s' "
    5883             :                  "for %sPort. This allows everybody on your local network to "
    5884             :                  "use your machine as a proxy. Make sure this is what you "
    5885             :                  "wanted.",
    5886             :                  fmt_addrport(&port->addr, port->port), portname);
    5887             :     }
    5888           9 :   } SMARTLIST_FOREACH_END(port);
    5889           5 : }
    5890             : 
    5891             : /** Given a list of port_cfg_t in <b>ports</b>, warn if any controller port
    5892             :  * there is listening on any non-loopback address.  If <b>forbid_nonlocal</b>
    5893             :  * is true, then emit a stronger warning and remove the port from the list.
    5894             :  */
    5895             : static void
    5896          15 : warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid_nonlocal)
    5897             : {
    5898          15 :   int warned = 0;
    5899          47 :   SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) {
    5900          32 :     if (port->type != CONN_TYPE_CONTROL_LISTENER)
    5901          17 :       continue;
    5902          15 :     if (port->is_unix_addr)
    5903           7 :       continue;
    5904           8 :     if (!tor_addr_is_loopback(&port->addr)) {
    5905           0 :       if (forbid_nonlocal) {
    5906           0 :         if (!warned)
    5907           0 :           log_warn(LD_CONFIG,
    5908             :                  "You have a ControlPort set to accept "
    5909             :                  "unauthenticated connections from a non-local address.  "
    5910             :                  "This means that programs not running on your computer "
    5911             :                  "can reconfigure your Tor, without even having to guess a "
    5912             :                  "password.  That's so bad that I'm closing your ControlPort "
    5913             :                  "for you.  If you need to control your Tor remotely, try "
    5914             :                  "enabling authentication and using a tool like stunnel or "
    5915             :                  "ssh to encrypt remote access.");
    5916           0 :         warned = 1;
    5917           0 :         port_cfg_free(port);
    5918           0 :         SMARTLIST_DEL_CURRENT(ports, port);
    5919             :       } else {
    5920           0 :         log_warn(LD_CONFIG, "You have a ControlPort set to accept "
    5921             :                  "connections from a non-local address.  This means that "
    5922             :                  "programs not running on your computer can reconfigure your "
    5923             :                  "Tor.  That's pretty bad, since the controller "
    5924             :                  "protocol isn't encrypted!  Maybe you should just listen on "
    5925             :                  "127.0.0.1 and use a tool like stunnel or ssh to encrypt "
    5926             :                  "remote connections to your control port.");
    5927           0 :         return; /* No point in checking the rest */
    5928             :       }
    5929             :     }
    5930          32 :   } SMARTLIST_FOREACH_END(port);
    5931             : }
    5932             : 
    5933             : /**
    5934             :  * Take a string (<b>line</b>) that begins with either an address:port, a
    5935             :  * port, or an AF_UNIX address, optionally quoted, prefixed with
    5936             :  * "unix:". Parse that line, and on success, set <b>addrport_out</b> to a new
    5937             :  * string containing the beginning portion (without prefix).  Iff there was a
    5938             :  * unix: prefix, set <b>is_unix_out</b> to true.  On success, also set
    5939             :  * <b>rest_out</b> to point to the part of the line after the address portion.
    5940             :  *
    5941             :  * Return 0 on success, -1 on failure.
    5942             :  */
    5943             : int
    5944         759 : port_cfg_line_extract_addrport(const char *line,
    5945             :                                char **addrport_out,
    5946             :                                int *is_unix_out,
    5947             :                                const char **rest_out)
    5948             : {
    5949         759 :   tor_assert(line);
    5950         759 :   tor_assert(addrport_out);
    5951         759 :   tor_assert(is_unix_out);
    5952         759 :   tor_assert(rest_out);
    5953             : 
    5954         759 :   line = eat_whitespace(line);
    5955             : 
    5956         759 :   if (!strcmpstart(line, unix_q_socket_prefix)) {
    5957             :     // It starts with unix:"
    5958          14 :     size_t sz;
    5959          14 :     *is_unix_out = 1;
    5960          14 :     *addrport_out = NULL;
    5961          14 :     line += strlen(unix_socket_prefix); /* No 'unix:', but keep the quote */
    5962          14 :     *rest_out = unescape_string(line, addrport_out, &sz);
    5963          14 :     if (!*rest_out || (*addrport_out && sz != strlen(*addrport_out))) {
    5964           4 :       tor_free(*addrport_out);
    5965           4 :       return -1;
    5966             :     }
    5967          10 :     *rest_out = eat_whitespace(*rest_out);
    5968          10 :     return 0;
    5969             :   } else {
    5970             :     // Is there a unix: prefix?
    5971         745 :     if (!strcmpstart(line, unix_socket_prefix)) {
    5972          21 :       line += strlen(unix_socket_prefix);
    5973          21 :       *is_unix_out = 1;
    5974             :     } else {
    5975         724 :       *is_unix_out = 0;
    5976             :     }
    5977             : 
    5978         745 :     const char *end = find_whitespace(line);
    5979         745 :     if (BUG(!end)) {
    5980             :       end = strchr(line, '\0'); // LCOV_EXCL_LINE -- this can't be NULL
    5981             :     }
    5982         745 :     tor_assert(end && end >= line);
    5983         745 :     *addrport_out = tor_strndup(line, end - line);
    5984         745 :     *rest_out = eat_whitespace(end);
    5985         745 :     return 0;
    5986             :   }
    5987             : }
    5988             : 
    5989             : static void
    5990           7 : warn_client_dns_cache(const char *option, int disabling)
    5991             : {
    5992           7 :   if (disabling)
    5993             :     return;
    5994             : 
    5995           6 :   warn_deprecated_option(option,
    5996             :       "Client-side DNS caching enables a wide variety of route-"
    5997             :       "capture attacks. If a single bad exit node lies to you about "
    5998             :       "an IP address, caching that address would make you visit "
    5999             :       "an address of the attacker's choice every time you connected "
    6000             :       "to your destination.");
    6001             : }
    6002             : 
    6003             : /**
    6004             :  * Parse port configuration for a single port type.
    6005             :  *
    6006             :  * Read entries of the "FooPort" type from the list <b>ports</b>.  Syntax is
    6007             :  * that FooPort can have any number of entries of the format
    6008             :  *  "[Address:][Port] IsolationOptions".
    6009             :  *
    6010             :  * In log messages, describe the port type as <b>portname</b>.
    6011             :  *
    6012             :  * If no address is specified, default to <b>defaultaddr</b>.  If no
    6013             :  * FooPort is given, default to defaultport (if 0, there is no default).
    6014             :  *
    6015             :  * If CL_PORT_NO_STREAM_OPTIONS is set in <b>flags</b>, do not allow stream
    6016             :  * isolation options in the FooPort entries.
    6017             :  *
    6018             :  * If CL_PORT_WARN_NONLOCAL is set in <b>flags</b>, warn if any of the
    6019             :  * ports are not on a local address.  If CL_PORT_FORBID_NONLOCAL is set,
    6020             :  * this is a control port with no password set: don't even allow it.
    6021             :  *
    6022             :  * If CL_PORT_SERVER_OPTIONS is set in <b>flags</b>, do not allow stream
    6023             :  * isolation options in the FooPort entries; instead allow the
    6024             :  * server-port option set.
    6025             :  *
    6026             :  * If CL_PORT_TAKES_HOSTNAMES is set in <b>flags</b>, allow the options
    6027             :  * {No,}IPv{4,6}Traffic.
    6028             :  *
    6029             :  * On success, if <b>out</b> is given, add a new port_cfg_t entry to
    6030             :  * <b>out</b> for every port that the client should listen on.  Return 0
    6031             :  * on success, -1 on failure.
    6032             :  */
    6033             : int
    6034        6537 : port_parse_config(smartlist_t *out,
    6035             :                   const config_line_t *ports,
    6036             :                   const char *portname,
    6037             :                   int listener_type,
    6038             :                   const char *defaultaddr,
    6039             :                   int defaultport,
    6040             :                   const unsigned flags)
    6041             : {
    6042        6537 :   smartlist_t *elts;
    6043        6537 :   int retval = -1;
    6044        6537 :   const unsigned is_control = (listener_type == CONN_TYPE_CONTROL_LISTENER);
    6045        6537 :   const unsigned is_ext_orport = (listener_type == CONN_TYPE_EXT_OR_LISTENER);
    6046        6537 :   const unsigned allow_no_stream_options = flags & CL_PORT_NO_STREAM_OPTIONS;
    6047        6537 :   const unsigned use_server_options = flags & CL_PORT_SERVER_OPTIONS;
    6048        6537 :   const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL;
    6049        6537 :   const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL;
    6050        6537 :   const unsigned default_to_group_writable =
    6051             :     flags & CL_PORT_DFLT_GROUP_WRITABLE;
    6052        6537 :   const unsigned takes_hostnames = flags & CL_PORT_TAKES_HOSTNAMES;
    6053        6537 :   const unsigned is_unix_socket = flags & CL_PORT_IS_UNIXSOCKET;
    6054        6537 :   int got_zero_port=0, got_nonzero_port=0;
    6055        6537 :   char *unix_socket_path = NULL;
    6056        6537 :   port_cfg_t *cfg = NULL;
    6057        6537 :   bool addr_is_explicit = false;
    6058        6537 :   tor_addr_t default_addr = TOR_ADDR_NULL;
    6059             : 
    6060             :   /* Parse default address. This can fail for Unix socket so the default_addr
    6061             :    * will simply be made UNSPEC. */
    6062        6537 :   if (defaultaddr) {
    6063        5920 :     tor_addr_parse(&default_addr, defaultaddr);
    6064             :   }
    6065             : 
    6066             :   /* If there's no FooPort, then maybe make a default one. */
    6067        6537 :   if (! ports) {
    6068        5887 :     if (defaultport && defaultaddr && out) {
    6069         573 :        cfg = port_cfg_new(is_unix_socket ? strlen(defaultaddr) : 0);
    6070         573 :        cfg->type = listener_type;
    6071         573 :        if (is_unix_socket) {
    6072           1 :          tor_addr_make_unspec(&cfg->addr);
    6073           1 :          memcpy(cfg->unix_addr, defaultaddr, strlen(defaultaddr) + 1);
    6074           1 :          cfg->is_unix_addr = 1;
    6075             :        } else {
    6076         572 :          cfg->port = defaultport;
    6077         572 :          tor_addr_parse(&cfg->addr, defaultaddr);
    6078             :        }
    6079         573 :        smartlist_add(out, cfg);
    6080             :     }
    6081        5887 :     return 0;
    6082             :   }
    6083             : 
    6084             :   /* At last we can actually parse the FooPort lines.  The syntax is:
    6085             :    * [Addr:](Port|auto) [Options].*/
    6086         650 :   elts = smartlist_new();
    6087         650 :   char *addrport = NULL;
    6088             : 
    6089        1332 :   for (; ports; ports = ports->next) {
    6090         711 :     tor_addr_t addr;
    6091         711 :     tor_addr_make_unspec(&addr);
    6092         711 :     int port, ok,
    6093         711 :         has_used_unix_socket_only_option = 0,
    6094         711 :         is_unix_tagged_addr = 0;
    6095         711 :     uint16_t ptmp=0;
    6096         711 :     const char *rest_of_line = NULL;
    6097             : 
    6098         711 :     if (port_cfg_line_extract_addrport(ports->value,
    6099             :                           &addrport, &is_unix_tagged_addr, &rest_of_line)<0) {
    6100           1 :       log_warn(LD_CONFIG, "Invalid %sPort line with unparsable address",
    6101             :                portname);
    6102          29 :       goto err;
    6103             :     }
    6104         710 :     if (strlen(addrport) == 0) {
    6105           4 :       log_warn(LD_CONFIG, "Invalid %sPort line with no address", portname);
    6106           4 :       goto err;
    6107             :     }
    6108             : 
    6109             :     /* Split the remainder... */
    6110         706 :     smartlist_split_string(elts, rest_of_line, NULL,
    6111             :                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    6112             : 
    6113             :     /* Let's start to check if it's a Unix socket path. */
    6114         706 :     if (is_unix_tagged_addr) {
    6115             : #ifndef HAVE_SYS_UN_H
    6116             :       log_warn(LD_CONFIG, "Unix sockets not supported on this system.");
    6117             :       goto err;
    6118             : #endif
    6119          14 :       unix_socket_path = addrport;
    6120          14 :       addrport = NULL;
    6121             :     }
    6122             : 
    6123         720 :     if (unix_socket_path &&
    6124          14 :         ! conn_listener_type_supports_af_unix(listener_type)) {
    6125           2 :       log_warn(LD_CONFIG, "%sPort does not support unix sockets", portname);
    6126           2 :       goto err;
    6127             :     }
    6128             : 
    6129         704 :     if (unix_socket_path) {
    6130             :       port = 1;
    6131         692 :     } else if (is_unix_socket) {
    6132           5 :       if (BUG(!addrport))
    6133             :         goto err; // LCOV_EXCL_LINE unreachable, but coverity can't tell that
    6134           5 :       unix_socket_path = tor_strdup(addrport);
    6135           5 :       if (!strcmp(addrport, "0"))
    6136             :         port = 0;
    6137             :       else
    6138           4 :         port = 1;
    6139         687 :     } else if (!strcasecmp(addrport, "auto")) {
    6140          23 :       port = CFG_AUTO_PORT;
    6141          23 :       tor_addr_copy(&addr, &default_addr);
    6142         664 :     } else if (!strcasecmpend(addrport, ":auto")) {
    6143          38 :       char *addrtmp = tor_strndup(addrport, strlen(addrport)-5);
    6144          38 :       port = CFG_AUTO_PORT;
    6145          38 :       if (tor_addr_port_lookup(addrtmp, &addr, &ptmp)<0 || ptmp) {
    6146           2 :         log_warn(LD_CONFIG, "Invalid address '%s' for %sPort",
    6147             :                  escaped(addrport), portname);
    6148           2 :         tor_free(addrtmp);
    6149           2 :         goto err;
    6150             :       }
    6151          36 :       tor_free(addrtmp);
    6152             :     } else {
    6153             :       /* Try parsing integer port before address, because, who knows?
    6154             :        * "9050" might be a valid address. */
    6155         626 :       port = (int) tor_parse_long(addrport, 10, 0, 65535, &ok, NULL);
    6156         626 :       if (ok) {
    6157         506 :         tor_addr_copy(&addr, &default_addr);
    6158         506 :         addr_is_explicit = false;
    6159         120 :       } else if (tor_addr_port_lookup(addrport, &addr, &ptmp) == 0) {
    6160         114 :         if (ptmp == 0) {
    6161           0 :           log_warn(LD_CONFIG, "%sPort line has address but no port", portname);
    6162           0 :           goto err;
    6163             :         }
    6164         114 :         port = ptmp;
    6165         114 :         addr_is_explicit = true;
    6166             :       } else {
    6167           6 :         log_warn(LD_CONFIG, "Couldn't parse address %s for %sPort",
    6168             :                  escaped(addrport), portname);
    6169           6 :         goto err;
    6170             :       }
    6171             :     }
    6172             : 
    6173             :     /* Default port_cfg_t object initialization */
    6174         696 :     cfg = port_cfg_new(unix_socket_path ? strlen(unix_socket_path) : 0);
    6175             : 
    6176         696 :     cfg->explicit_addr = addr_is_explicit;
    6177         696 :     if (unix_socket_path && default_to_group_writable)
    6178           1 :       cfg->is_group_writable = 1;
    6179             : 
    6180             :     /* Now parse the rest of the options, if any. */
    6181         696 :     if (use_server_options) {
    6182             :       /* This is a server port; parse advertising options */
    6183         637 :       SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
    6184          27 :         if (!strcasecmp(elt, "NoAdvertise")) {
    6185           9 :           cfg->server_cfg.no_advertise = 1;
    6186          18 :         } else if (!strcasecmp(elt, "NoListen")) {
    6187           7 :           cfg->server_cfg.no_listen = 1;
    6188             : #if 0
    6189             :         /* not implemented yet. */
    6190             :         } else if (!strcasecmp(elt, "AllAddrs")) {
    6191             : 
    6192             :           all_addrs = 1;
    6193             : #endif /* 0 */
    6194          11 :         } else if (!strcasecmp(elt, "IPv4Only")) {
    6195           5 :           cfg->server_cfg.bind_ipv4_only = 1;
    6196           6 :         } else if (!strcasecmp(elt, "IPv6Only")) {
    6197           5 :           cfg->server_cfg.bind_ipv6_only = 1;
    6198             :         } else {
    6199           1 :           log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
    6200             :                    portname, escaped(elt));
    6201             :         }
    6202          27 :       } SMARTLIST_FOREACH_END(elt);
    6203             : 
    6204         610 :       if (cfg->server_cfg.no_advertise && cfg->server_cfg.no_listen) {
    6205           1 :         log_warn(LD_CONFIG, "Tried to set both NoListen and NoAdvertise "
    6206             :                  "on %sPort line '%s'",
    6207             :                  portname, escaped(ports->value));
    6208           1 :         goto err;
    6209             :       }
    6210         609 :       if (cfg->server_cfg.bind_ipv4_only &&
    6211             :           cfg->server_cfg.bind_ipv6_only) {
    6212           1 :         log_warn(LD_CONFIG, "Tried to set both IPv4Only and IPv6Only "
    6213             :                  "on %sPort line '%s'",
    6214             :                  portname, escaped(ports->value));
    6215           1 :         goto err;
    6216             :       }
    6217         608 :       if (cfg->server_cfg.bind_ipv4_only &&
    6218           4 :           tor_addr_family(&addr) != AF_INET) {
    6219           3 :         if (cfg->explicit_addr) {
    6220           2 :           log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
    6221             :                    portname);
    6222           2 :           goto err;
    6223             :         }
    6224             :         /* This ORPort is IPv4Only but the default address is IPv6, ignore it
    6225             :          * since this will be configured with an IPv4 default address. */
    6226           1 :         goto ignore;
    6227             :       }
    6228         605 :       if (cfg->server_cfg.bind_ipv6_only &&
    6229           4 :           tor_addr_family(&addr) != AF_INET6) {
    6230           3 :         if (cfg->explicit_addr) {
    6231           2 :           log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
    6232             :                    portname);
    6233           2 :           goto err;
    6234             :         }
    6235             :         /* This ORPort is IPv6Only but the default address is IPv4, ignore it
    6236             :          * since this will be configured with an IPv6 default address. */
    6237           1 :         goto ignore;
    6238             :       }
    6239             :     } else {
    6240             :       /* This is a client port; parse isolation options */
    6241         134 :       SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
    6242          51 :         int no = 0, isoflag = 0;
    6243          51 :         const char *elt_orig = elt;
    6244             : 
    6245          51 :         if (!strcasecmpstart(elt, "SessionGroup=")) {
    6246           5 :           int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
    6247             :                                           10, 0, INT_MAX, &ok, NULL);
    6248           5 :           if (!ok || allow_no_stream_options) {
    6249           2 :             log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
    6250             :                      portname, escaped(elt));
    6251           2 :             goto err;
    6252             :           }
    6253           3 :           if (cfg->entry_cfg.session_group >= 0) {
    6254           1 :             log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort",
    6255             :                      portname);
    6256           1 :             goto err;
    6257             :           }
    6258           2 :           cfg->entry_cfg.session_group = group;
    6259           2 :           continue;
    6260             :         }
    6261             : 
    6262          46 :         if (!strcasecmpstart(elt, "No")) {
    6263          18 :           no = 1;
    6264          18 :           elt += 2;
    6265             :         }
    6266             : 
    6267          46 :         if (!strcasecmp(elt, "GroupWritable")) {
    6268           1 :           cfg->is_group_writable = !no;
    6269           1 :           has_used_unix_socket_only_option = 1;
    6270           1 :           continue;
    6271          45 :         } else if (!strcasecmp(elt, "WorldWritable")) {
    6272           5 :           cfg->is_world_writable = !no;
    6273           5 :           has_used_unix_socket_only_option = 1;
    6274           5 :           continue;
    6275          40 :         } else if (!strcasecmp(elt, "RelaxDirModeCheck")) {
    6276           1 :           cfg->relax_dirmode_check = !no;
    6277           1 :           has_used_unix_socket_only_option = 1;
    6278           1 :           continue;
    6279             :         }
    6280             : 
    6281          39 :         if (allow_no_stream_options) {
    6282           2 :           log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
    6283             :                    portname, escaped(elt));
    6284           2 :           continue;
    6285             :         }
    6286             : 
    6287          37 :         if (takes_hostnames) {
    6288          21 :           if (!strcasecmp(elt, "IPv4Traffic")) {
    6289           6 :             cfg->entry_cfg.ipv4_traffic = ! no;
    6290           6 :             continue;
    6291          15 :           } else if (!strcasecmp(elt, "IPv6Traffic")) {
    6292           7 :             cfg->entry_cfg.ipv6_traffic = ! no;
    6293           7 :             continue;
    6294           8 :           } else if (!strcasecmp(elt, "PreferIPv6")) {
    6295           1 :             cfg->entry_cfg.prefer_ipv6 = ! no;
    6296           1 :             continue;
    6297           7 :           } else if (!strcasecmp(elt, "DNSRequest")) {
    6298           3 :             cfg->entry_cfg.dns_request = ! no;
    6299           3 :             continue;
    6300           4 :           } else if (!strcasecmp(elt, "OnionTraffic")) {
    6301           2 :             cfg->entry_cfg.onion_traffic = ! no;
    6302           2 :             continue;
    6303           2 :           } else if (!strcasecmp(elt, "OnionTrafficOnly")) {
    6304             :             /* Only connect to .onion addresses.  Equivalent to
    6305             :              * NoDNSRequest, NoIPv4Traffic, NoIPv6Traffic. The option
    6306             :              * NoOnionTrafficOnly is not supported, it's too confusing. */
    6307           1 :             if (no) {
    6308           0 :               log_warn(LD_CONFIG, "Unsupported %sPort option 'No%s'. Use "
    6309             :                        "DNSRequest, IPv4Traffic, and/or IPv6Traffic instead.",
    6310             :                        portname, escaped(elt));
    6311             :             } else {
    6312           1 :               cfg->entry_cfg.ipv4_traffic = 0;
    6313           1 :               cfg->entry_cfg.ipv6_traffic = 0;
    6314           1 :               cfg->entry_cfg.dns_request = 0;
    6315             :             }
    6316           1 :             continue;
    6317             :           }
    6318             :         }
    6319          17 :         if (!strcasecmp(elt, "CacheIPv4DNS")) {
    6320           2 :           warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
    6321           2 :           cfg->entry_cfg.cache_ipv4_answers = ! no;
    6322           2 :           continue;
    6323          15 :         } else if (!strcasecmp(elt, "CacheIPv6DNS")) {
    6324           1 :           warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
    6325           1 :           cfg->entry_cfg.cache_ipv6_answers = ! no;
    6326           1 :           continue;
    6327          14 :         } else if (!strcasecmp(elt, "CacheDNS")) {
    6328           1 :           warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
    6329           1 :           cfg->entry_cfg.cache_ipv4_answers = ! no;
    6330           1 :           cfg->entry_cfg.cache_ipv6_answers = ! no;
    6331           1 :           continue;
    6332          13 :         } else if (!strcasecmp(elt, "UseIPv4Cache")) {
    6333           1 :           warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
    6334           1 :           cfg->entry_cfg.use_cached_ipv4_answers = ! no;
    6335           1 :           continue;
    6336          12 :         } else if (!strcasecmp(elt, "UseIPv6Cache")) {
    6337           1 :           warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
    6338           1 :           cfg->entry_cfg.use_cached_ipv6_answers = ! no;
    6339           1 :           continue;
    6340          11 :         } else if (!strcasecmp(elt, "UseDNSCache")) {
    6341           1 :           warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha
    6342           1 :           cfg->entry_cfg.use_cached_ipv4_answers = ! no;
    6343           1 :           cfg->entry_cfg.use_cached_ipv6_answers = ! no;
    6344           1 :           continue;
    6345          10 :         } else if (!strcasecmp(elt, "PreferIPv6Automap")) {
    6346           1 :           cfg->entry_cfg.prefer_ipv6_virtaddr = ! no;
    6347           1 :           continue;
    6348           9 :         } else if (!strcasecmp(elt, "PreferSOCKSNoAuth")) {
    6349           1 :           cfg->entry_cfg.socks_prefer_no_auth = ! no;
    6350           1 :           continue;
    6351           8 :         } else if (!strcasecmp(elt, "KeepAliveIsolateSOCKSAuth")) {
    6352           0 :           cfg->entry_cfg.socks_iso_keep_alive = ! no;
    6353           0 :           continue;
    6354           8 :         } else if (!strcasecmp(elt, "ExtendedErrors")) {
    6355           0 :           cfg->entry_cfg.extended_socks5_codes = ! no;
    6356           0 :           continue;
    6357             :         }
    6358             : 
    6359           8 :         if (!strcasecmpend(elt, "s"))
    6360           1 :           elt[strlen(elt)-1] = '\0'; /* kill plurals. */
    6361             : 
    6362           8 :         if (!strcasecmp(elt, "IsolateDestPort")) {
    6363             :           isoflag = ISO_DESTPORT;
    6364           6 :         } else if (!strcasecmp(elt, "IsolateDestAddr")) {
    6365             :           isoflag = ISO_DESTADDR;
    6366           5 :         } else if (!strcasecmp(elt, "IsolateSOCKSAuth")) {
    6367             :           isoflag = ISO_SOCKSAUTH;
    6368           3 :         } else if (!strcasecmp(elt, "IsolateClientProtocol")) {
    6369             :           isoflag = ISO_CLIENTPROTO;
    6370           2 :         } else if (!strcasecmp(elt, "IsolateClientAddr")) {
    6371             :           isoflag = ISO_CLIENTADDR;
    6372             :         } else {
    6373           1 :           log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
    6374             :                    portname, escaped(elt_orig));
    6375             :         }
    6376             : 
    6377           8 :         if (no) {
    6378           2 :           cfg->entry_cfg.isolation_flags &= ~isoflag;
    6379             :         } else {
    6380           6 :           cfg->entry_cfg.isolation_flags |= isoflag;
    6381             :         }
    6382          48 :       } SMARTLIST_FOREACH_END(elt);
    6383             :     }
    6384             : 
    6385         685 :     if (port)
    6386             :       got_nonzero_port = 1;
    6387             :     else
    6388          14 :       got_zero_port = 1;
    6389             : 
    6390         685 :     if (cfg->entry_cfg.dns_request == 0 &&
    6391             :         listener_type == CONN_TYPE_AP_DNS_LISTENER) {
    6392           1 :       log_warn(LD_CONFIG, "You have a %sPort entry with DNS disabled; that "
    6393             :                "won't work.", portname);
    6394           1 :       goto err;
    6395             :     }
    6396         684 :     if (cfg->entry_cfg.ipv4_traffic == 0 &&
    6397         684 :         cfg->entry_cfg.ipv6_traffic == 0 &&
    6398           2 :         cfg->entry_cfg.onion_traffic == 0 &&
    6399             :         listener_type != CONN_TYPE_AP_DNS_LISTENER) {
    6400           1 :       log_warn(LD_CONFIG, "You have a %sPort entry with all of IPv4 and "
    6401             :                "IPv6 and .onion disabled; that won't work.", portname);
    6402           1 :       goto err;
    6403             :     }
    6404         683 :     if (cfg->entry_cfg.dns_request == 1 &&
    6405         683 :         cfg->entry_cfg.ipv4_traffic == 0 &&
    6406           1 :         cfg->entry_cfg.ipv6_traffic == 0 &&
    6407             :         listener_type != CONN_TYPE_AP_DNS_LISTENER) {
    6408           0 :       log_warn(LD_CONFIG, "You have a %sPort entry with DNSRequest enabled, "
    6409             :                "but IPv4 and IPv6 disabled; DNS-based sites won't work.",
    6410             :                portname);
    6411           0 :       goto err;
    6412             :     }
    6413         683 :     if (has_used_unix_socket_only_option && !unix_socket_path) {
    6414           3 :       log_warn(LD_CONFIG, "You have a %sPort entry with GroupWritable, "
    6415             :                "WorldWritable, or RelaxDirModeCheck, but it is not a "
    6416             :                "unix socket.", portname);
    6417           3 :       goto err;
    6418             :     }
    6419         680 :     if (!(cfg->entry_cfg.isolation_flags & ISO_SOCKSAUTH) &&
    6420             :         cfg->entry_cfg.socks_iso_keep_alive) {
    6421           0 :       log_warn(LD_CONFIG, "You have a %sPort entry with both "
    6422             :                "NoIsolateSOCKSAuth and KeepAliveIsolateSOCKSAuth set.",
    6423             :                portname);
    6424           0 :       goto err;
    6425             :     }
    6426         680 :     if (unix_socket_path &&
    6427             :         (cfg->entry_cfg.isolation_flags & ISO_CLIENTADDR)) {
    6428             :       /* `IsolateClientAddr` is nonsensical in the context of AF_LOCAL.
    6429             :        * just silently remove the isolation flag.
    6430             :        */
    6431          16 :       cfg->entry_cfg.isolation_flags &= ~ISO_CLIENTADDR;
    6432             :     }
    6433         680 :     if (out && port) {
    6434         663 :       size_t namelen = unix_socket_path ? strlen(unix_socket_path) : 0;
    6435         663 :       if (unix_socket_path) {
    6436          15 :         tor_addr_make_unspec(&cfg->addr);
    6437          15 :         memcpy(cfg->unix_addr, unix_socket_path, namelen + 1);
    6438          15 :         cfg->is_unix_addr = 1;
    6439          15 :         tor_free(unix_socket_path);
    6440             :       } else {
    6441         648 :         tor_addr_copy(&cfg->addr, &addr);
    6442         648 :         cfg->port = port;
    6443             :       }
    6444         663 :       cfg->type = listener_type;
    6445         663 :       if (! (cfg->entry_cfg.isolation_flags & ISO_SOCKSAUTH))
    6446           1 :         cfg->entry_cfg.socks_prefer_no_auth = 1;
    6447         663 :       smartlist_add(out, cfg);
    6448             :       /* out owns cfg now, don't re-use or free it */
    6449         663 :       cfg = NULL;
    6450             :     }
    6451             : 
    6452          17 :  ignore:
    6453         682 :     tor_free(cfg);
    6454         741 :     SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
    6455         682 :     smartlist_clear(elts);
    6456         682 :     tor_free(addrport);
    6457         682 :     tor_free(unix_socket_path);
    6458             :   }
    6459             : 
    6460         621 :   if (warn_nonlocal && out) {
    6461          34 :     if (is_control)
    6462          15 :       warn_nonlocal_controller_ports(out, forbid_nonlocal);
    6463          19 :     else if (is_ext_orport)
    6464          14 :       port_warn_nonlocal_ext_orports(out, portname);
    6465             :     else
    6466           5 :       warn_nonlocal_client_ports(out, portname, listener_type);
    6467             :   }
    6468             : 
    6469         621 :   if (got_zero_port && got_nonzero_port) {
    6470           1 :     log_warn(LD_CONFIG, "You specified a nonzero %sPort along with '%sPort 0' "
    6471             :              "in the same configuration. Did you mean to disable %sPort or "
    6472             :              "not?", portname, portname, portname);
    6473           1 :     goto err;
    6474             :   }
    6475             : 
    6476             :   retval = 0;
    6477         650 :  err:
    6478             :   /* There are two ways we can error out:
    6479             :    *  1. part way through the loop: cfg needs to be freed;
    6480             :    *  2. ending the loop normally: cfg is always NULL.
    6481             :    *     In this case, cfg has either been:
    6482             :    *     - added to out, then set to NULL, or
    6483             :    *     - freed and set to NULL (because out is NULL, or port is 0).
    6484             :    */
    6485         650 :   tor_free(cfg);
    6486             : 
    6487             :   /* Free the other variables from the loop.
    6488             :    * elts is always non-NULL here, but it may or may not be empty. */
    6489         673 :   SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
    6490         650 :   smartlist_free(elts);
    6491         650 :   tor_free(unix_socket_path);
    6492         650 :   tor_free(addrport);
    6493             : 
    6494         650 :   return retval;
    6495             : }
    6496             : 
    6497             : /** Return the number of ports which are actually going to listen with type
    6498             :  * <b>listenertype</b>.  Do not count no_listen ports.  Only count unix
    6499             :  * sockets if count_sockets is true. */
    6500             : int
    6501        5193 : port_count_real_listeners(const smartlist_t *ports, int listenertype,
    6502             :                      int count_sockets)
    6503             : {
    6504        5193 :   int n = 0;
    6505       15057 :   SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) {
    6506        9864 :     if (port->server_cfg.no_listen)
    6507           9 :       continue;
    6508        9855 :     if (!count_sockets && port->is_unix_addr)
    6509          28 :       continue;
    6510        9827 :     if (port->type != listenertype)
    6511        8736 :       continue;
    6512        1091 :     ++n;
    6513        9864 :   } SMARTLIST_FOREACH_END(port);
    6514        5193 :   return n;
    6515             : }
    6516             : 
    6517             : /** Parse all ports from <b>options</b>. On success, set *<b>n_ports_out</b>
    6518             :  * to the number of ports that are listed, update the *Port_set values in
    6519             :  * <b>options</b>, and return 0.  On failure, set *<b>msg</b> to a
    6520             :  * description of the problem and return -1.
    6521             :  *
    6522             :  * If <b>validate_only</b> is false, set configured_client_ports to the
    6523             :  * new list of ports parsed from <b>options</b>.
    6524             :  **/
    6525             : STATIC int
    6526         588 : parse_ports(or_options_t *options, int validate_only,
    6527             :             char **msg, int *n_ports_out,
    6528             :             int *world_writable_control_socket)
    6529             : {
    6530         588 :   smartlist_t *ports;
    6531         588 :   int retval = -1;
    6532             : 
    6533         588 :   ports = smartlist_new();
    6534             : 
    6535         588 :   *n_ports_out = 0;
    6536             : 
    6537        1176 :   const unsigned gw_flag = options->UnixSocksGroupWritable ?
    6538         588 :     CL_PORT_DFLT_GROUP_WRITABLE : 0;
    6539         588 :   if (port_parse_config(ports,
    6540         588 :              options->SocksPort_lines,
    6541             :              "Socks", CONN_TYPE_AP_LISTENER,
    6542             :              "127.0.0.1", 9050,
    6543             :              ((validate_only ? 0 : CL_PORT_WARN_NONLOCAL)
    6544         588 :               | CL_PORT_TAKES_HOSTNAMES | gw_flag)) < 0) {
    6545           0 :     *msg = tor_strdup("Invalid SocksPort configuration");
    6546           0 :     goto err;
    6547             :   }
    6548         588 :   if (port_parse_config(ports,
    6549         588 :                         options->DNSPort_lines,
    6550             :                         "DNS", CONN_TYPE_AP_DNS_LISTENER,
    6551             :                         "127.0.0.1", 0,
    6552             :                         CL_PORT_WARN_NONLOCAL|CL_PORT_TAKES_HOSTNAMES) < 0) {
    6553           0 :     *msg = tor_strdup("Invalid DNSPort configuration");
    6554           0 :     goto err;
    6555             :   }
    6556         588 :   if (port_parse_config(ports,
    6557         588 :                         options->TransPort_lines,
    6558             :                         "Trans", CONN_TYPE_AP_TRANS_LISTENER,
    6559             :                         "127.0.0.1", 0,
    6560             :                         CL_PORT_WARN_NONLOCAL) < 0) {
    6561           0 :     *msg = tor_strdup("Invalid TransPort configuration");
    6562           0 :     goto err;
    6563             :   }
    6564         588 :   if (port_parse_config(ports,
    6565         588 :                         options->NATDPort_lines,
    6566             :                         "NATD", CONN_TYPE_AP_NATD_LISTENER,
    6567             :                         "127.0.0.1", 0,
    6568             :                         CL_PORT_WARN_NONLOCAL) < 0) {
    6569           0 :     *msg = tor_strdup("Invalid NatdPort configuration");
    6570           0 :     goto err;
    6571             :   }
    6572         588 :   if (port_parse_config(ports,
    6573         588 :                         options->HTTPTunnelPort_lines,
    6574             :                         "HTTP Tunnel", CONN_TYPE_AP_HTTP_CONNECT_LISTENER,
    6575             :                         "127.0.0.1", 0,
    6576             :                         ((validate_only ? 0 : CL_PORT_WARN_NONLOCAL)
    6577             :                          | CL_PORT_TAKES_HOSTNAMES | gw_flag)) < 0) {
    6578           0 :     *msg = tor_strdup("Invalid HTTPTunnelPort configuration");
    6579           0 :     goto err;
    6580             :   }
    6581         588 :   if (metrics_parse_ports(options, ports, msg) < 0) {
    6582           0 :     goto err;
    6583             :   }
    6584             : 
    6585             :   {
    6586         588 :     unsigned control_port_flags = CL_PORT_NO_STREAM_OPTIONS |
    6587             :       CL_PORT_WARN_NONLOCAL;
    6588        2335 :     const int any_passwords = (options->HashedControlPassword ||
    6589         588 :                                options->HashedControlSessionPassword ||
    6590         580 :                                options->CookieAuthentication);
    6591         575 :     if (! any_passwords)
    6592             :       control_port_flags |= CL_PORT_FORBID_NONLOCAL;
    6593         588 :     if (options->ControlSocketsGroupWritable)
    6594           1 :       control_port_flags |= CL_PORT_DFLT_GROUP_WRITABLE;
    6595             : 
    6596         588 :     if (port_parse_config(ports,
    6597         588 :                           options->ControlPort_lines,
    6598             :                           "Control", CONN_TYPE_CONTROL_LISTENER,
    6599             :                           "127.0.0.1", 0,
    6600             :                           control_port_flags) < 0) {
    6601           0 :       *msg = tor_strdup("Invalid ControlPort configuration");
    6602           0 :       goto err;
    6603             :     }
    6604             : 
    6605         588 :     if (port_parse_config(ports, options->ControlSocket,
    6606             :                           "ControlSocket",
    6607             :                           CONN_TYPE_CONTROL_LISTENER, NULL, 0,
    6608             :                           control_port_flags | CL_PORT_IS_UNIXSOCKET) < 0) {
    6609           0 :       *msg = tor_strdup("Invalid ControlSocket configuration");
    6610           0 :       goto err;
    6611             :     }
    6612             :   }
    6613             : 
    6614         588 :   if (port_parse_ports_relay(options, msg, ports, &have_low_ports) < 0)
    6615          10 :     goto err;
    6616             : 
    6617         578 :   *n_ports_out = smartlist_len(ports);
    6618             : 
    6619         578 :   retval = 0;
    6620             : 
    6621             :   /* Update the *Port_set options.  The !! here is to force a boolean out of
    6622             :      an integer. */
    6623         578 :   port_update_port_set_relay(options, ports);
    6624         578 :   options->SocksPort_set =
    6625         578 :     !! port_count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1);
    6626         578 :   options->TransPort_set =
    6627         578 :     !! port_count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1);
    6628         578 :   options->NATDPort_set =
    6629         578 :     !! port_count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1);
    6630         578 :   options->HTTPTunnelPort_set =
    6631         578 :     !! port_count_real_listeners(ports, CONN_TYPE_AP_HTTP_CONNECT_LISTENER, 1);
    6632             :   /* Use options->ControlSocket to test if a control socket is set */
    6633         578 :   options->ControlPort_set =
    6634         578 :     !! port_count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0);
    6635         578 :   options->DNSPort_set =
    6636         578 :     !! port_count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER, 1);
    6637             : 
    6638         578 :   if (world_writable_control_socket) {
    6639        1657 :     SMARTLIST_FOREACH(ports, port_cfg_t *, p,
    6640             :       if (p->type == CONN_TYPE_CONTROL_LISTENER &&
    6641             :           p->is_unix_addr &&
    6642             :           p->is_world_writable) {
    6643             :         *world_writable_control_socket = 1;
    6644             :         break;
    6645             :       });
    6646             :   }
    6647             : 
    6648         578 :   if (!validate_only) {
    6649          12 :     if (configured_ports) {
    6650           9 :       SMARTLIST_FOREACH(configured_ports,
    6651             :                         port_cfg_t *, p, port_cfg_free(p));
    6652           4 :       smartlist_free(configured_ports);
    6653             :     }
    6654          12 :     configured_ports = ports;
    6655          12 :     ports = NULL; /* prevent free below. */
    6656             :   }
    6657             : 
    6658         566 :  err:
    6659         588 :   if (ports) {
    6660        1650 :     SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p));
    6661         576 :     smartlist_free(ports);
    6662             :   }
    6663         588 :   return retval;
    6664             : }
    6665             : 
    6666             : /* Does port bind to IPv4? */
    6667             : int
    6668         471 : port_binds_ipv4(const port_cfg_t *port)
    6669             : {
    6670         471 :   return tor_addr_family(&port->addr) == AF_INET ||
    6671             :          (tor_addr_family(&port->addr) == AF_UNSPEC
    6672           0 :           && !port->server_cfg.bind_ipv6_only);
    6673             : }
    6674             : 
    6675             : /* Does port bind to IPv6? */
    6676             : int
    6677          56 : port_binds_ipv6(const port_cfg_t *port)
    6678             : {
    6679          56 :   return tor_addr_family(&port->addr) == AF_INET6 ||
    6680             :          (tor_addr_family(&port->addr) == AF_UNSPEC
    6681           0 :           && !port->server_cfg.bind_ipv4_only);
    6682             : }
    6683             : 
    6684             : /** Return a list of port_cfg_t for client ports parsed from the
    6685             :  * options. */
    6686          76 : MOCK_IMPL(const smartlist_t *,
    6687             : get_configured_ports,(void))
    6688             : {
    6689          76 :   if (!configured_ports)
    6690           7 :     configured_ports = smartlist_new();
    6691          76 :   return configured_ports;
    6692             : }
    6693             : 
    6694             : /** Return an address:port string representation of the address
    6695             :  *  where the first <b>listener_type</b> listener waits for
    6696             :  *  connections. Return NULL if we couldn't find a listener. The
    6697             :  *  string is allocated on the heap and it's the responsibility of the
    6698             :  *  caller to free it after use.
    6699             :  *
    6700             :  *  This function is meant to be used by the pluggable transport proxy
    6701             :  *  spawning code, please make sure that it fits your purposes before
    6702             :  *  using it. */
    6703             : char *
    6704           0 : get_first_listener_addrport_string(int listener_type)
    6705             : {
    6706           0 :   static const char *ipv4_localhost = "127.0.0.1";
    6707           0 :   static const char *ipv6_localhost = "[::1]";
    6708           0 :   const char *address;
    6709           0 :   uint16_t port;
    6710           0 :   char *string = NULL;
    6711             : 
    6712           0 :   if (!configured_ports)
    6713             :     return NULL;
    6714             : 
    6715           0 :   SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
    6716           0 :     if (cfg->server_cfg.no_listen)
    6717           0 :       continue;
    6718             : 
    6719           0 :     if (cfg->type == listener_type &&
    6720           0 :         tor_addr_family(&cfg->addr) != AF_UNSPEC) {
    6721             : 
    6722             :       /* We found the first listener of the type we are interested in! */
    6723             : 
    6724             :       /* If a listener is listening on INADDR_ANY, assume that it's
    6725             :          also listening on 127.0.0.1, and point the transport proxy
    6726             :          there: */
    6727           0 :       if (tor_addr_is_null(&cfg->addr))
    6728           0 :         address = tor_addr_is_v4(&cfg->addr) ? ipv4_localhost : ipv6_localhost;
    6729             :       else
    6730           0 :         address = fmt_and_decorate_addr(&cfg->addr);
    6731             : 
    6732             :       /* If a listener is configured with port 'auto', we are forced
    6733             :          to iterate all listener connections and find out in which
    6734             :          port it ended up listening: */
    6735           0 :       if (cfg->port == CFG_AUTO_PORT) {
    6736           0 :         port = router_get_active_listener_port_by_type_af(listener_type,
    6737           0 :                                                   tor_addr_family(&cfg->addr));
    6738           0 :         if (!port)
    6739             :           return NULL;
    6740             :       } else {
    6741           0 :         port = cfg->port;
    6742             :       }
    6743             : 
    6744           0 :       tor_asprintf(&string, "%s:%u", address, port);
    6745             : 
    6746           0 :       return string;
    6747             :     }
    6748             : 
    6749           0 :   } SMARTLIST_FOREACH_END(cfg);
    6750             : 
    6751             :   return NULL;
    6752             : }
    6753             : 
    6754             : /** Find and return the first configured advertised `port_cfg_t` of type @a
    6755             :  * listener_type in @a address_family. */
    6756             : static const port_cfg_t *
    6757          87 : portconf_get_first_advertised(int listener_type, int address_family)
    6758             : {
    6759          87 :   const port_cfg_t *first_port = NULL;
    6760          87 :   const port_cfg_t *first_port_explicit_addr = NULL;
    6761             : 
    6762          87 :   if (address_family == AF_UNSPEC)
    6763             :     return NULL;
    6764             : 
    6765          85 :   const smartlist_t *conf_ports = get_configured_ports();
    6766         273 :   SMARTLIST_FOREACH_BEGIN(conf_ports, const port_cfg_t *, cfg) {
    6767         188 :     if (cfg->type == listener_type && !cfg->server_cfg.no_advertise) {
    6768         112 :       if ((address_family == AF_INET && port_binds_ipv4(cfg)) ||
    6769          56 :           (address_family == AF_INET6 && port_binds_ipv6(cfg))) {
    6770          66 :         if (cfg->explicit_addr && !first_port_explicit_addr) {
    6771             :           first_port_explicit_addr = cfg;
    6772          48 :         } else if (!first_port) {
    6773          48 :           first_port = cfg;
    6774             :         }
    6775             :       }
    6776             :     }
    6777         188 :   } SMARTLIST_FOREACH_END(cfg);
    6778             : 
    6779             :   /* Prefer the port with the explicit address if any. */
    6780          85 :   return (first_port_explicit_addr) ? first_port_explicit_addr : first_port;
    6781             : }
    6782             : 
    6783             : /** Return the first advertised port of type <b>listener_type</b> in
    6784             :  * <b>address_family</b>. Returns 0 when no port is found, and when passed
    6785             :  * AF_UNSPEC. */
    6786             : int
    6787          71 : portconf_get_first_advertised_port(int listener_type, int address_family)
    6788             : {
    6789          71 :   const port_cfg_t *cfg;
    6790          71 :   cfg = portconf_get_first_advertised(listener_type, address_family);
    6791             : 
    6792          71 :   return cfg ? cfg->port : 0;
    6793             : }
    6794             : 
    6795             : /** Return the first advertised address of type <b>listener_type</b> in
    6796             :  * <b>address_family</b>. Returns NULL if there is no advertised address,
    6797             :  * and when passed AF_UNSPEC. */
    6798             : const tor_addr_t *
    6799          16 : portconf_get_first_advertised_addr(int listener_type, int address_family)
    6800             : {
    6801          16 :   const port_cfg_t *cfg;
    6802          16 :   cfg = portconf_get_first_advertised(listener_type, address_family);
    6803             : 
    6804          16 :   return cfg ? &cfg->addr : NULL;
    6805             : }
    6806             : 
    6807             : /** Return 1 if a port exists of type <b>listener_type</b> on <b>addr</b> and
    6808             :  * <b>port</b>. If <b>check_wildcard</b> is true, INADDR[6]_ANY and AF_UNSPEC
    6809             :  * addresses match any address of the appropriate family; and port -1 matches
    6810             :  * any port.
    6811             :  * To match auto ports, pass CFG_PORT_AUTO. (Does not match on the actual
    6812             :  * automatically chosen listener ports.) */
    6813             : int
    6814           0 : port_exists_by_type_addr_port(int listener_type, const tor_addr_t *addr,
    6815             :                               int port, int check_wildcard)
    6816             : {
    6817           0 :   if (!configured_ports || !addr)
    6818             :     return 0;
    6819           0 :   SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
    6820           0 :     if (cfg->type == listener_type) {
    6821           0 :       if (cfg->port == port || (check_wildcard && port == -1)) {
    6822             :         /* Exact match */
    6823           0 :         if (tor_addr_eq(&cfg->addr, addr)) {
    6824             :           return 1;
    6825             :         }
    6826             :         /* Skip wildcard matches if we're not doing them */
    6827           0 :         if (!check_wildcard) {
    6828           0 :           continue;
    6829             :         }
    6830             :         /* Wildcard matches IPv4 */
    6831           0 :         const int cfg_v4 = port_binds_ipv4(cfg);
    6832           0 :         const int cfg_any_v4 = tor_addr_is_null(&cfg->addr) && cfg_v4;
    6833           0 :         const int addr_v4 = tor_addr_family(addr) == AF_INET ||
    6834             :                             tor_addr_family(addr) == AF_UNSPEC;
    6835           0 :         const int addr_any_v4 = tor_addr_is_null(&cfg->addr) && addr_v4;
    6836           0 :         if ((cfg_any_v4 && addr_v4) || (cfg_v4 && addr_any_v4)) {
    6837             :           return 1;
    6838             :         }
    6839             :         /* Wildcard matches IPv6 */
    6840           0 :         const int cfg_v6 = port_binds_ipv6(cfg);
    6841           0 :         const int cfg_any_v6 = tor_addr_is_null(&cfg->addr) && cfg_v6;
    6842           0 :         const int addr_v6 = tor_addr_family(addr) == AF_INET6 ||
    6843             :                             tor_addr_family(addr) == AF_UNSPEC;
    6844           0 :         const int addr_any_v6 = tor_addr_is_null(&cfg->addr) && addr_v6;
    6845           0 :         if ((cfg_any_v6 && addr_v6) || (cfg_v6 && addr_any_v6)) {
    6846             :           return 1;
    6847             :         }
    6848             :       }
    6849             :     }
    6850           0 :   } SMARTLIST_FOREACH_END(cfg);
    6851             :   return 0;
    6852             : }
    6853             : 
    6854             : /* Like port_exists_by_type_addr_port, but accepts a host-order IPv4 address
    6855             :  * instead. */
    6856             : int
    6857           0 : port_exists_by_type_addr32h_port(int listener_type, uint32_t addr_ipv4h,
    6858             :                                  int port, int check_wildcard)
    6859             : {
    6860           0 :   tor_addr_t ipv4;
    6861           0 :   tor_addr_from_ipv4h(&ipv4, addr_ipv4h);
    6862           0 :   return port_exists_by_type_addr_port(listener_type, &ipv4, port,
    6863             :                                        check_wildcard);
    6864             : }
    6865             : 
    6866             : /** Allocate and return a good value for the DataDirectory based on
    6867             :  *  <b>val</b>, which may be NULL.  Return NULL on failure. */
    6868             : static char *
    6869         570 : get_data_directory(const char *val)
    6870             : {
    6871             : #ifdef _WIN32
    6872             :   if (val) {
    6873             :     return tor_strdup(val);
    6874             :   } else {
    6875             :     return tor_strdup(get_windows_conf_root());
    6876             :   }
    6877             : #else /* !defined(_WIN32) */
    6878         570 :   const char *d = val;
    6879         570 :   if (!d)
    6880         516 :     d = "~/.tor";
    6881             : 
    6882         570 :   if (!strcmpstart(d, "~/")) {
    6883         516 :     char *fn = expand_filename(d);
    6884         516 :     if (!fn) {
    6885           0 :       log_warn(LD_CONFIG,"Failed to expand filename \"%s\".", d);
    6886           0 :       return NULL;
    6887             :     }
    6888         516 :     if (!val && !strcmp(fn,"/.tor")) {
    6889             :       /* If our homedir is /, we probably don't want to use it. */
    6890             :       /* Default to LOCALSTATEDIR/tor which is probably closer to what we
    6891             :        * want. */
    6892           0 :       log_warn(LD_CONFIG,
    6893             :                "Default DataDirectory is \"~/.tor\".  This expands to "
    6894             :                "\"%s\", which is probably not what you want.  Using "
    6895             :                "\"%s"PATH_SEPARATOR"tor\" instead", fn, LOCALSTATEDIR);
    6896           0 :       tor_free(fn);
    6897           0 :       fn = tor_strdup(LOCALSTATEDIR PATH_SEPARATOR "tor");
    6898             :     }
    6899         516 :     return fn;
    6900             :   }
    6901          54 :   return tor_strdup(d);
    6902             : #endif /* defined(_WIN32) */
    6903             : }
    6904             : 
    6905             : /** Check and normalize the values of options->{Key,Data,Cache}Directory;
    6906             :  * return 0 if it is sane, -1 otherwise. */
    6907             : static int
    6908         564 : validate_data_directories(or_options_t *options)
    6909             : {
    6910         564 :   tor_free(options->DataDirectory);
    6911         564 :   options->DataDirectory = get_data_directory(options->DataDirectory_option);
    6912         564 :   if (!options->DataDirectory)
    6913             :     return -1;
    6914         564 :   if (strlen(options->DataDirectory) > (512-128)) {
    6915           1 :     log_warn(LD_CONFIG, "DataDirectory is too long.");
    6916           1 :     return -1;
    6917             :   }
    6918             : 
    6919         563 :   tor_free(options->KeyDirectory);
    6920         563 :   if (options->KeyDirectory_option) {
    6921           3 :     options->KeyDirectory = get_data_directory(options->KeyDirectory_option);
    6922           3 :     if (!options->KeyDirectory)
    6923             :       return -1;
    6924             :   } else {
    6925             :     /* Default to the data directory's keys subdir */
    6926         560 :     tor_asprintf(&options->KeyDirectory, "%s"PATH_SEPARATOR"keys",
    6927             :                  options->DataDirectory);
    6928             :   }
    6929             : 
    6930         563 :   tor_free(options->CacheDirectory);
    6931         563 :   if (options->CacheDirectory_option) {
    6932           3 :     options->CacheDirectory = get_data_directory(
    6933             :                                              options->CacheDirectory_option);
    6934           3 :     if (!options->CacheDirectory)
    6935           0 :       return -1;
    6936             :   } else {
    6937             :     /* Default to the data directory. */
    6938         560 :     options->CacheDirectory = tor_strdup(options->DataDirectory);
    6939             :   }
    6940             : 
    6941             :   return 0;
    6942             : }
    6943             : 
    6944             : /** This string must remain the same forevermore. It is how we
    6945             :  * recognize that the torrc file doesn't need to be backed up. */
    6946             : #define GENERATED_FILE_PREFIX "# This file was generated by Tor; " \
    6947             :   "if you edit it, comments will not be preserved"
    6948             : /** This string can change; it tries to give the reader an idea
    6949             :  * that editing this file by hand is not a good plan. */
    6950             : #define GENERATED_FILE_COMMENT "# The old torrc file was renamed " \
    6951             :   "to torrc.orig.1, and Tor will ignore it"
    6952             : 
    6953             : /** Save a configuration file for the configuration in <b>options</b>
    6954             :  * into the file <b>fname</b>.  If the file already exists, and
    6955             :  * doesn't begin with GENERATED_FILE_PREFIX, rename it.  Otherwise
    6956             :  * replace it.  Return 0 on success, -1 on failure. */
    6957             : static int
    6958           0 : write_configuration_file(const char *fname, const or_options_t *options)
    6959             : {
    6960           0 :   char *old_val=NULL, *new_val=NULL, *new_conf=NULL;
    6961           0 :   int rename_old = 0, r;
    6962             : 
    6963           0 :   if (!fname)
    6964             :     return -1;
    6965             : 
    6966           0 :   switch (file_status(fname)) {
    6967             :     /* create backups of old config files, even if they're empty */
    6968           0 :     case FN_FILE:
    6969             :     case FN_EMPTY:
    6970           0 :       old_val = read_file_to_str(fname, 0, NULL);
    6971           0 :       if (!old_val || strcmpstart(old_val, GENERATED_FILE_PREFIX)) {
    6972             :         rename_old = 1;
    6973             :       }
    6974           0 :       tor_free(old_val);
    6975           0 :       break;
    6976             :     case FN_NOENT:
    6977             :       break;
    6978           0 :     case FN_ERROR:
    6979             :     case FN_DIR:
    6980             :     default:
    6981           0 :       log_warn(LD_CONFIG,
    6982             :                "Config file \"%s\" is not a file? Failing.", fname);
    6983           0 :       return -1;
    6984             :   }
    6985             : 
    6986           0 :   if (!(new_conf = options_dump(options, OPTIONS_DUMP_MINIMAL))) {
    6987           0 :     log_warn(LD_BUG, "Couldn't get configuration string");
    6988           0 :     goto err;
    6989             :   }
    6990             : 
    6991           0 :   tor_asprintf(&new_val, "%s\n%s\n\n%s",
    6992             :                GENERATED_FILE_PREFIX, GENERATED_FILE_COMMENT, new_conf);
    6993             : 
    6994           0 :   if (rename_old) {
    6995           0 :     char *fn_tmp = NULL;
    6996           0 :     tor_asprintf(&fn_tmp, CONFIG_BACKUP_PATTERN, fname);
    6997           0 :     file_status_t fn_tmp_status = file_status(fn_tmp);
    6998           0 :     if (fn_tmp_status == FN_DIR || fn_tmp_status == FN_ERROR) {
    6999           0 :       log_warn(LD_CONFIG,
    7000             :                "Config backup file \"%s\" is not a file? Failing.", fn_tmp);
    7001           0 :       tor_free(fn_tmp);
    7002           0 :       goto err;
    7003             :     }
    7004             : 
    7005           0 :     log_notice(LD_CONFIG, "Renaming old configuration file to \"%s\"", fn_tmp);
    7006           0 :     if (replace_file(fname, fn_tmp) < 0) {
    7007           0 :       log_warn(LD_FS,
    7008             :                "Couldn't rename configuration file \"%s\" to \"%s\": %s",
    7009             :                fname, fn_tmp, strerror(errno));
    7010           0 :       tor_free(fn_tmp);
    7011           0 :       goto err;
    7012             :     }
    7013           0 :     tor_free(fn_tmp);
    7014             :   }
    7015             : 
    7016           0 :   if (write_str_to_file(fname, new_val, 0) < 0)
    7017           0 :     goto err;
    7018             : 
    7019           0 :   r = 0;
    7020           0 :   goto done;
    7021             :  err:
    7022             :   r = -1;
    7023           0 :  done:
    7024           0 :   tor_free(new_val);
    7025           0 :   tor_free(new_conf);
    7026           0 :   return r;
    7027             : }
    7028             : 
    7029             : /**
    7030             :  * Save the current configuration file value to disk.  Return 0 on
    7031             :  * success, -1 on failure.
    7032             :  **/
    7033             : int
    7034           0 : options_save_current(void)
    7035             : {
    7036             :   /* This fails if we can't write to our configuration file.
    7037             :    *
    7038             :    * If we try falling back to datadirectory or something, we have a better
    7039             :    * chance of saving the configuration, but a better chance of doing
    7040             :    * something the user never expected. */
    7041           0 :   return write_configuration_file(get_torrc_fname(0), get_options());
    7042             : }
    7043             : 
    7044             : /** Return the number of cpus configured in <b>options</b>.  If we are
    7045             :  * told to auto-detect the number of cpus, return the auto-detected number. */
    7046             : int
    7047           4 : get_num_cpus(const or_options_t *options)
    7048             : {
    7049           4 :   if (options->NumCPUs == 0) {
    7050           4 :     int n = compute_num_cpus();
    7051           4 :     return (n >= 1) ? n : 1;
    7052             :   } else {
    7053             :     return options->NumCPUs;
    7054             :   }
    7055             : }
    7056             : 
    7057             : /**
    7058             :  * Initialize the libevent library.
    7059             :  */
    7060             : static void
    7061           4 : init_libevent(const or_options_t *options)
    7062             : {
    7063           4 :   tor_libevent_cfg_t cfg;
    7064             : 
    7065           4 :   tor_assert(options);
    7066             : 
    7067           4 :   configure_libevent_logging();
    7068             :   /* If the kernel complains that some method (say, epoll) doesn't
    7069             :    * exist, we don't care about it, since libevent will cope.
    7070             :    */
    7071           4 :   suppress_libevent_log_msg("Function not implemented");
    7072             : 
    7073           4 :   memset(&cfg, 0, sizeof(cfg));
    7074           4 :   cfg.num_cpus = get_num_cpus(options);
    7075           4 :   cfg.msec_per_tick = options->TokenBucketRefillInterval;
    7076             : 
    7077           4 :   tor_libevent_initialize(&cfg);
    7078             : 
    7079           4 :   suppress_libevent_log_msg(NULL);
    7080           4 : }
    7081             : 
    7082             : /** Return a newly allocated string holding a filename relative to the
    7083             :  * directory in <b>options</b> specified by <b>roottype</b>.
    7084             :  * If <b>sub1</b> is present, it is the first path component after
    7085             :  * the data directory.  If <b>sub2</b> is also present, it is the second path
    7086             :  * component after the data directory.  If <b>suffix</b> is present, it
    7087             :  * is appended to the filename.
    7088             :  *
    7089             :  * Note: Consider using macros in config.h that wrap this function;
    7090             :  * you should probably never need to call it as-is.
    7091             :  */
    7092         995 : MOCK_IMPL(char *,
    7093             : options_get_dir_fname2_suffix,(const or_options_t *options,
    7094             :                                directory_root_t roottype,
    7095             :                                const char *sub1, const char *sub2,
    7096             :                                const char *suffix))
    7097             : {
    7098         995 :   tor_assert(options);
    7099             : 
    7100         995 :   const char *rootdir = NULL;
    7101         995 :   switch (roottype) {
    7102         587 :     case DIRROOT_DATADIR:
    7103         587 :       rootdir = options->DataDirectory;
    7104         587 :       break;
    7105         195 :     case DIRROOT_CACHEDIR:
    7106         195 :       rootdir = options->CacheDirectory;
    7107         195 :       break;
    7108         213 :     case DIRROOT_KEYDIR:
    7109         213 :       rootdir = options->KeyDirectory;
    7110         213 :       break;
    7111           0 :     default:
    7112           0 :       tor_assert_unreached();
    7113         995 :       break;
    7114             :   }
    7115         995 :   tor_assert(rootdir);
    7116             : 
    7117         995 :   if (!suffix)
    7118         884 :     suffix = "";
    7119             : 
    7120         995 :   char *fname = NULL;
    7121             : 
    7122         995 :   if (sub1 == NULL) {
    7123           1 :     tor_asprintf(&fname, "%s%s", rootdir, suffix);
    7124           1 :     tor_assert(!sub2); /* If sub2 is present, sub1 must be present. */
    7125         994 :   } else if (sub2 == NULL) {
    7126         923 :     tor_asprintf(&fname, "%s"PATH_SEPARATOR"%s%s", rootdir, sub1, suffix);
    7127             :   } else {
    7128          71 :     tor_asprintf(&fname, "%s"PATH_SEPARATOR"%s"PATH_SEPARATOR"%s%s",
    7129             :                  rootdir, sub1, sub2, suffix);
    7130             :   }
    7131             : 
    7132         995 :   return fname;
    7133             : }
    7134             : 
    7135             : /** Check whether the data directory has a private subdirectory
    7136             :  * <b>subdir</b>. If not, try to create it. Return 0 on success,
    7137             :  * -1 otherwise. */
    7138             : int
    7139           4 : check_or_create_data_subdir(const char *subdir)
    7140             : {
    7141           4 :   char *statsdir = get_datadir_fname(subdir);
    7142           4 :   int return_val = 0;
    7143             : 
    7144           4 :   if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
    7145           0 :     log_warn(LD_HIST, "Unable to create %s/ directory!", subdir);
    7146           0 :     return_val = -1;
    7147             :   }
    7148           4 :   tor_free(statsdir);
    7149           4 :   return return_val;
    7150             : }
    7151             : 
    7152             : /** Create a file named <b>fname</b> with contents <b>str</b> in the
    7153             :  * subdirectory <b>subdir</b> of the data directory. <b>descr</b>
    7154             :  * should be a short description of the file's content and will be
    7155             :  * used for the warning message, if it's present and the write process
    7156             :  * fails. Return 0 on success, -1 otherwise.*/
    7157             : int
    7158           3 : write_to_data_subdir(const char* subdir, const char* fname,
    7159             :                      const char* str, const char* descr)
    7160             : {
    7161           3 :   char *filename = get_datadir_fname2(subdir, fname);
    7162           3 :   int return_val = 0;
    7163             : 
    7164           3 :   if (write_str_to_file(filename, str, 0) < 0) {
    7165           1 :     log_warn(LD_HIST, "Unable to write %s to disk!", descr ? descr : fname);
    7166           1 :     return_val = -1;
    7167             :   }
    7168           3 :   tor_free(filename);
    7169           3 :   return return_val;
    7170             : }
    7171             : 
    7172             : /** Helper to implement GETINFO functions about configuration variables (not
    7173             :  * their values).  Given a "config/names" question, set *<b>answer</b> to a
    7174             :  * new string describing the supported configuration variables and their
    7175             :  * types. */
    7176             : int
    7177           1 : getinfo_helper_config(control_connection_t *conn,
    7178             :                       const char *question, char **answer,
    7179             :                       const char **errmsg)
    7180             : {
    7181           1 :   (void) conn;
    7182           1 :   (void) errmsg;
    7183           1 :   if (!strcmp(question, "config/names")) {
    7184           1 :     smartlist_t *sl = smartlist_new();
    7185           1 :     smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
    7186         430 :     SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
    7187             :       /* don't tell controller about invisible options */
    7188         429 :       if (! config_var_is_listable(var))
    7189          74 :         continue;
    7190         355 :       const char *type = struct_var_get_typename(&var->member);
    7191         355 :       if (!type)
    7192           0 :         continue;
    7193         355 :       smartlist_add_asprintf(sl, "%s %s\n",var->member.name,type);
    7194         429 :     } SMARTLIST_FOREACH_END(var);
    7195           1 :     *answer = smartlist_join_strings(sl, "", 0, NULL);
    7196         356 :     SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
    7197           1 :     smartlist_free(sl);
    7198           1 :     smartlist_free(vars);
    7199           0 :   } else if (!strcmp(question, "config/defaults")) {
    7200           0 :     smartlist_t *sl = smartlist_new();
    7201           0 :     int dirauth_lines_seen = 0, fallback_lines_seen = 0;
    7202             :     /* Possibly this should check whether the variables are listable,
    7203             :      * but currently it does not.  See ticket 31654. */
    7204           0 :     smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
    7205           0 :     SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
    7206           0 :       if (var->initvalue != NULL) {
    7207           0 :         if (strcmp(var->member.name, "DirAuthority") == 0) {
    7208             :           /*
    7209             :            * Count dirauth lines we have a default for; we'll use the
    7210             :            * count later to decide whether to add the defaults manually
    7211             :            */
    7212           0 :           ++dirauth_lines_seen;
    7213             :         }
    7214           0 :         if (strcmp(var->member.name, "FallbackDir") == 0) {
    7215             :           /*
    7216             :            * Similarly count fallback lines, so that we can decide later
    7217             :            * to add the defaults manually.
    7218             :            */
    7219           0 :           ++fallback_lines_seen;
    7220             :         }
    7221           0 :         char *val = esc_for_log(var->initvalue);
    7222           0 :         smartlist_add_asprintf(sl, "%s %s\n",var->member.name,val);
    7223           0 :         tor_free(val);
    7224             :       }
    7225           0 :     } SMARTLIST_FOREACH_END(var);
    7226           0 :     smartlist_free(vars);
    7227             : 
    7228           0 :     if (dirauth_lines_seen == 0) {
    7229             :       /*
    7230             :        * We didn't see any directory authorities with default values,
    7231             :        * so add the list of default authorities manually.
    7232             :        */
    7233             : 
    7234             :       /*
    7235             :        * default_authorities is defined earlier in this file and
    7236             :        * is a const char ** NULL-terminated array of dirauth config
    7237             :        * lines.
    7238             :        */
    7239           0 :       for (const char **i = default_authorities; *i != NULL; ++i) {
    7240           0 :         char *val = esc_for_log(*i);
    7241           0 :         smartlist_add_asprintf(sl, "DirAuthority %s\n", val);
    7242           0 :         tor_free(val);
    7243             :       }
    7244             :     }
    7245             : 
    7246           0 :     if (fallback_lines_seen == 0 &&
    7247           0 :         get_options()->UseDefaultFallbackDirs == 1) {
    7248             :       /*
    7249             :        * We didn't see any explicitly configured fallback mirrors,
    7250             :        * so add the defaults to the list manually.
    7251             :        *
    7252             :        * default_fallbacks is included earlier in this file and
    7253             :        * is a const char ** NULL-terminated array of fallback config lines.
    7254             :        */
    7255             :       const char **i;
    7256             : 
    7257           0 :       for (i = default_fallbacks; *i != NULL; ++i) {
    7258           0 :         char *val = esc_for_log(*i);
    7259           0 :         smartlist_add_asprintf(sl, "FallbackDir %s\n", val);
    7260           0 :         tor_free(val);
    7261             :       }
    7262             :     }
    7263             : 
    7264           0 :     *answer = smartlist_join_strings(sl, "", 0, NULL);
    7265           0 :     SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
    7266           0 :     smartlist_free(sl);
    7267             :   }
    7268           1 :   return 0;
    7269             : }
    7270             : 
    7271             : /* Check whether an address has already been set against the options
    7272             :  * depending on address family and destination type. Any exsting
    7273             :  * value will lead to a fail, even if it is the same value. If not
    7274             :  * set and not only validating, copy it into this location too.
    7275             :  * Returns 0 on success or -1 if this address is already set.
    7276             :  */
    7277             : static int
    7278          19 : verify_and_store_outbound_address(sa_family_t family, tor_addr_t *addr,
    7279             :        outbound_addr_t type, or_options_t *options, int validate_only)
    7280             : {
    7281          19 :   if (type>=OUTBOUND_ADDR_MAX || (family!=AF_INET && family!=AF_INET6)) {
    7282             :     return -1;
    7283             :   }
    7284          18 :   int fam_index=0;
    7285          18 :   if (family==AF_INET6) {
    7286           0 :     fam_index=1;
    7287             :   }
    7288          18 :   tor_addr_t *dest=&options->OutboundBindAddresses[type][fam_index];
    7289          18 :   if (!tor_addr_is_null(dest)) {
    7290             :     return -1;
    7291             :   }
    7292          18 :   if (!validate_only) {
    7293           9 :     tor_addr_copy(dest, addr);
    7294             :   }
    7295             :   return 0;
    7296             : }
    7297             : 
    7298             : /* Parse a list of address lines for a specific destination type.
    7299             :  * Will store them into the options if not validate_only. If a
    7300             :  * problem occurs, a suitable error message is store in msg.
    7301             :  * Returns 0 on success or -1 if any address is already set.
    7302             :  */
    7303             : static int
    7304        3109 : parse_outbound_address_lines(const config_line_t *lines, outbound_addr_t type,
    7305             :            or_options_t *options, int validate_only, char **msg)
    7306             : {
    7307        3109 :   tor_addr_t addr;
    7308        3109 :   sa_family_t family;
    7309        3127 :   while (lines) {
    7310          19 :     family = tor_addr_parse(&addr, lines->value);
    7311          19 :     if (verify_and_store_outbound_address(family, &addr, type,
    7312             :                                  options, validate_only)) {
    7313           1 :       if (msg)
    7314           2 :         tor_asprintf(msg, "Multiple%s%s outbound bind addresses "
    7315             :                      "configured: %s",
    7316           1 :                      family==AF_INET?" IPv4":(family==AF_INET6?" IPv6":""),
    7317             :                      type==OUTBOUND_ADDR_OR?" OR":
    7318           1 :                      (type==OUTBOUND_ADDR_EXIT?" exit":
    7319           2 :                      (type==OUTBOUND_ADDR_PT?" PT":"")), lines->value);
    7320           1 :       return -1;
    7321             :     }
    7322          18 :     lines = lines->next;
    7323             :   }
    7324             :   return 0;
    7325             : }
    7326             : 
    7327             : /** Parse outbound bind address option lines. If <b>validate_only</b>
    7328             :  * is not 0 update OutboundBindAddresses in <b>options</b>.
    7329             :  * Only one address can be set for any of these values.
    7330             :  * On failure, set <b>msg</b> (if provided) to a newly allocated string
    7331             :  * containing a description of the problem and return -1.
    7332             :  */
    7333             : static int
    7334         778 : parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
    7335             : {
    7336         778 :   if (!validate_only) {
    7337         213 :     memset(&options->OutboundBindAddresses, 0,
    7338             :            sizeof(options->OutboundBindAddresses));
    7339             :   }
    7340             : 
    7341         778 :   if (parse_outbound_address_lines(options->OutboundBindAddress,
    7342             :                                    OUTBOUND_ADDR_ANY, options,
    7343             :                                    validate_only, msg) < 0) {
    7344           1 :     goto err;
    7345             :   }
    7346             : 
    7347         777 :   if (parse_outbound_address_lines(options->OutboundBindAddressOR,
    7348             :                                    OUTBOUND_ADDR_OR, options, validate_only,
    7349             :                                    msg) < 0) {
    7350           0 :     goto err;
    7351             :   }
    7352             : 
    7353         777 :   if (parse_outbound_address_lines(options->OutboundBindAddressExit,
    7354             :                                    OUTBOUND_ADDR_EXIT, options, validate_only,
    7355             :                                    msg)  < 0) {
    7356           0 :     goto err;
    7357             :   }
    7358             : 
    7359         777 :   if (parse_outbound_address_lines(options->OutboundBindAddressPT,
    7360             :                                    OUTBOUND_ADDR_PT, options, validate_only,
    7361             :                                    msg) < 0) {
    7362           0 :     goto err;
    7363             :   }
    7364             : 
    7365             :   return 0;
    7366             :  err:
    7367             :   return -1;
    7368             : }
    7369             : 
    7370             : /** Load one of the geoip files, <a>family</a> determining which
    7371             :  * one. <a>default_fname</a> is used if on Windows and
    7372             :  * <a>fname</a> equals "<default>". */
    7373             : static void
    7374           8 : config_load_geoip_file_(sa_family_t family,
    7375             :                         const char *fname,
    7376             :                         const char *default_fname)
    7377             : {
    7378           8 :   const or_options_t *options = get_options();
    7379           8 :   const char *msg = "";
    7380           8 :   int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO;
    7381           8 :   int r;
    7382             : 
    7383             : #ifdef _WIN32
    7384             :   char *free_fname = NULL; /* Used to hold any temporary-allocated value */
    7385             :   /* XXXX Don't use this "<default>" junk; make our filename options
    7386             :    * understand prefixes somehow. -NM */
    7387             :   if (!strcmp(fname, "<default>")) {
    7388             :     const char *conf_root = get_windows_conf_root();
    7389             :     tor_asprintf(&free_fname, "%s\\%s", conf_root, default_fname);
    7390             :     fname = free_fname;
    7391             :   }
    7392             :   r = geoip_load_file(family, fname, severity);
    7393             :   tor_free(free_fname);
    7394             : #else /* !defined(_WIN32) */
    7395           8 :   (void)default_fname;
    7396           8 :   r = geoip_load_file(family, fname, severity);
    7397             : #endif /* defined(_WIN32) */
    7398             : 
    7399           8 :   if (r < 0 && severity == LOG_WARN) {
    7400           0 :     log_warn(LD_GENERAL, "%s", msg);
    7401             :   }
    7402           8 : }
    7403             : 
    7404             : /** Load geoip files for IPv4 and IPv6 if <a>options</a> and
    7405             :  * <a>old_options</a> indicate we should. */
    7406             : static void
    7407           4 : config_maybe_load_geoip_files_(const or_options_t *options,
    7408             :                                const or_options_t *old_options)
    7409             : {
    7410             :   /* XXXX Reload GeoIPFile on SIGHUP. -NM */
    7411             : 
    7412           4 :   if (options->GeoIPFile &&
    7413           0 :       ((!old_options || !opt_streq(old_options->GeoIPFile,
    7414             :                                    options->GeoIPFile))
    7415           0 :        || !geoip_is_loaded(AF_INET))) {
    7416           4 :     config_load_geoip_file_(AF_INET, options->GeoIPFile, "geoip");
    7417             :     /* Okay, now we need to maybe change our mind about what is in
    7418             :      * which country. We do this for IPv4 only since that's what we
    7419             :      * store in node->country. */
    7420           4 :     refresh_all_country_info();
    7421             :   }
    7422           4 :   if (options->GeoIPv6File &&
    7423           0 :       ((!old_options || !opt_streq(old_options->GeoIPv6File,
    7424             :                                    options->GeoIPv6File))
    7425           0 :        || !geoip_is_loaded(AF_INET6))) {
    7426           4 :     config_load_geoip_file_(AF_INET6, options->GeoIPv6File, "geoip6");
    7427             :   }
    7428           4 : }
    7429             : 
    7430             : /** Initialize cookie authentication (used so far by the ControlPort
    7431             :  *  and Extended ORPort).
    7432             :  *
    7433             :  *  Allocate memory and create a cookie (of length <b>cookie_len</b>)
    7434             :  *  in <b>cookie_out</b>.
    7435             :  *  Then write it down to <b>fname</b> and prepend it with <b>header</b>.
    7436             :  *
    7437             :  *  If <b>group_readable</b> is set, set <b>fname</b> to be readable
    7438             :  *  by the default GID.
    7439             :  *
    7440             :  *  If the whole procedure was successful, set
    7441             :  *  <b>cookie_is_set_out</b> to True. */
    7442             : int
    7443           3 : init_cookie_authentication(const char *fname, const char *header,
    7444             :                            int cookie_len, int group_readable,
    7445             :                            uint8_t **cookie_out, int *cookie_is_set_out)
    7446             : {
    7447           3 :   char cookie_file_str_len = strlen(header) + cookie_len;
    7448           3 :   char *cookie_file_str = tor_malloc(cookie_file_str_len);
    7449           3 :   int retval = -1;
    7450             : 
    7451             :   /* We don't want to generate a new cookie every time we call
    7452             :    * options_act(). One should be enough. */
    7453           3 :   if (*cookie_is_set_out) {
    7454           1 :     retval = 0; /* we are all set */
    7455           1 :     goto done;
    7456             :   }
    7457             : 
    7458             :   /* If we've already set the cookie, free it before re-setting
    7459             :      it. This can happen if we previously generated a cookie, but
    7460             :      couldn't write it to a disk. */
    7461           2 :   if (*cookie_out)
    7462           2 :     tor_free(*cookie_out);
    7463             : 
    7464             :   /* Generate the cookie */
    7465           2 :   *cookie_out = tor_malloc(cookie_len);
    7466           2 :   crypto_rand((char *)*cookie_out, cookie_len);
    7467             : 
    7468             :   /* Create the string that should be written on the file. */
    7469           2 :   memcpy(cookie_file_str, header, strlen(header));
    7470           2 :   memcpy(cookie_file_str+strlen(header), *cookie_out, cookie_len);
    7471           2 :   if (write_bytes_to_file(fname, cookie_file_str, cookie_file_str_len, 1)) {
    7472           1 :     log_warn(LD_FS,"Error writing auth cookie to %s.", escaped(fname));
    7473           1 :     goto done;
    7474             :   }
    7475             : 
    7476             : #ifndef _WIN32
    7477           1 :   if (group_readable) {
    7478           0 :     if (chmod(fname, 0640)) {
    7479           0 :       log_warn(LD_FS,"Unable to make %s group-readable.", escaped(fname));
    7480             :     }
    7481             :   }
    7482             : #else /* defined(_WIN32) */
    7483             :   (void) group_readable;
    7484             : #endif /* !defined(_WIN32) */
    7485             : 
    7486             :   /* Success! */
    7487           1 :   log_info(LD_GENERAL, "Generated auth cookie file in '%s'.", escaped(fname));
    7488           1 :   *cookie_is_set_out = 1;
    7489           1 :   retval = 0;
    7490             : 
    7491           3 :  done:
    7492           3 :   memwipe(cookie_file_str, 0, cookie_file_str_len);
    7493           3 :   tor_free(cookie_file_str);
    7494           3 :   return retval;
    7495             : }
    7496             : 
    7497             : /**
    7498             :  * Return true if any option is set in <b>options</b> to make us behave
    7499             :  * as a client.
    7500             :  */
    7501             : int
    7502         313 : options_any_client_port_set(const or_options_t *options)
    7503             : {
    7504         313 :   return (options->SocksPort_set ||
    7505             :           options->TransPort_set ||
    7506             :           options->NATDPort_set ||
    7507         313 :           options->DNSPort_set ||
    7508             :           options->HTTPTunnelPort_set);
    7509             : }

Generated by: LCOV version 1.14