Back to index

tor  0.2.3.18-rc
config.c
Go to the documentation of this file.
00001 /* Copyright (c) 2001 Matej Pfajfar.
00002  * Copyright (c) 2001-2004, Roger Dingledine.
00003  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00004  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00005 /* See LICENSE for licensing information */
00006 
00012 #define CONFIG_PRIVATE
00013 
00014 #include "or.h"
00015 #include "circuitbuild.h"
00016 #include "circuitlist.h"
00017 #include "config.h"
00018 #include "connection.h"
00019 #include "connection_edge.h"
00020 #include "connection_or.h"
00021 #include "control.h"
00022 #include "cpuworker.h"
00023 #include "dirserv.h"
00024 #include "dirvote.h"
00025 #include "dns.h"
00026 #include "geoip.h"
00027 #include "hibernate.h"
00028 #include "main.h"
00029 #include "networkstatus.h"
00030 #include "policies.h"
00031 #include "relay.h"
00032 #include "rendclient.h"
00033 #include "rendservice.h"
00034 #include "rephist.h"
00035 #include "router.h"
00036 #include "util.h"
00037 #include "routerlist.h"
00038 #include "transports.h"
00039 #ifdef _WIN32
00040 #include <shlobj.h>
00041 #endif
00042 
00043 #include "procmon.h"
00044 
00045 /* From main.c */
00046 extern int quiet_level;
00047 
00049 typedef enum config_type_t {
00050   CONFIG_TYPE_STRING = 0,   
00051   CONFIG_TYPE_FILENAME,     
00052   CONFIG_TYPE_UINT,         
00053   CONFIG_TYPE_INT,          
00054   CONFIG_TYPE_PORT,         
00056   CONFIG_TYPE_INTERVAL,     
00057   CONFIG_TYPE_MSEC_INTERVAL,
00059   CONFIG_TYPE_MEMUNIT,      
00060   CONFIG_TYPE_DOUBLE,       
00061   CONFIG_TYPE_BOOL,         
00062   CONFIG_TYPE_AUTOBOOL,     
00064   CONFIG_TYPE_ISOTIME,      
00065   CONFIG_TYPE_CSV,          
00067   CONFIG_TYPE_LINELIST,     
00068   CONFIG_TYPE_LINELIST_S,   
00070   CONFIG_TYPE_LINELIST_V,   
00073   CONFIG_TYPE_ROUTERSET,    
00075   CONFIG_TYPE_OBSOLETE,     
00076 } config_type_t;
00077 
00079 typedef struct config_abbrev_t {
00080   const char *abbreviated;
00081   const char *full;
00082   int commandline_only;
00083   int warn;
00084 } config_abbrev_t;
00085 
00086 /* Handy macro for declaring "In the config file or on the command line,
00087  * you can abbreviate <b>tok</b>s as <b>tok</b>". */
00088 #define PLURAL(tok) { #tok, #tok "s", 0, 0 }
00089 
00092 static config_abbrev_t _option_abbrevs[] = {
00093   PLURAL(AuthDirBadDirCC),
00094   PLURAL(AuthDirBadExitCC),
00095   PLURAL(AuthDirInvalidCC),
00096   PLURAL(AuthDirRejectCC),
00097   PLURAL(ExitNode),
00098   PLURAL(EntryNode),
00099   PLURAL(ExcludeNode),
00100   PLURAL(FirewallPort),
00101   PLURAL(LongLivedPort),
00102   PLURAL(HiddenServiceNode),
00103   PLURAL(HiddenServiceExcludeNode),
00104   PLURAL(NumCPU),
00105   PLURAL(RendNode),
00106   PLURAL(RendExcludeNode),
00107   PLURAL(StrictEntryNode),
00108   PLURAL(StrictExitNode),
00109   PLURAL(StrictNode),
00110   { "l", "Log", 1, 0},
00111   { "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0},
00112   { "AutomapHostSuffixes", "AutomapHostsSuffixes", 0, 0},
00113   { "AutomapHostOnResolve", "AutomapHostsOnResolve", 0, 0},
00114   { "BandwidthRateBytes", "BandwidthRate", 0, 0},
00115   { "BandwidthBurstBytes", "BandwidthBurst", 0, 0},
00116   { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0},
00117   { "MaxConn", "ConnLimit", 0, 1},
00118   { "ORBindAddress", "ORListenAddress", 0, 0},
00119   { "DirBindAddress", "DirListenAddress", 0, 0},
00120   { "SocksBindAddress", "SocksListenAddress", 0, 0},
00121   { "UseHelperNodes", "UseEntryGuards", 0, 0},
00122   { "NumHelperNodes", "NumEntryGuards", 0, 0},
00123   { "UseEntryNodes", "UseEntryGuards", 0, 0},
00124   { "NumEntryNodes", "NumEntryGuards", 0, 0},
00125   { "ResolvConf", "ServerDNSResolvConfFile", 0, 1},
00126   { "SearchDomains", "ServerDNSSearchDomains", 0, 1},
00127   { "ServerDNSAllowBrokenResolvConf", "ServerDNSAllowBrokenConfig", 0, 0},
00128   { "PreferTunnelledDirConns", "PreferTunneledDirConns", 0, 0},
00129   { "BridgeAuthoritativeDirectory", "BridgeAuthoritativeDir", 0, 0},
00130   { "HashedControlPassword", "__HashedControlSessionPassword", 1, 0},
00131   { "StrictEntryNodes", "StrictNodes", 0, 1},
00132   { "StrictExitNodes", "StrictNodes", 0, 1},
00133   { NULL, NULL, 0, 0},
00134 };
00135 
00137 static config_abbrev_t _state_abbrevs[] = {
00138   { "AccountingBytesReadInterval", "AccountingBytesReadInInterval", 0, 0 },
00139   { "HelperNode", "EntryGuard", 0, 0 },
00140   { "HelperNodeDownSince", "EntryGuardDownSince", 0, 0 },
00141   { "HelperNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
00142   { "EntryNode", "EntryGuard", 0, 0 },
00143   { "EntryNodeDownSince", "EntryGuardDownSince", 0, 0 },
00144   { "EntryNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
00145   { NULL, NULL, 0, 0},
00146 };
00147 #undef PLURAL
00148 
00150 typedef struct config_var_t {
00151   const char *name; 
00152   config_type_t type; 
00154   off_t var_offset; 
00155   const char *initvalue; 
00156 } config_var_t;
00157 
00162 #define VAR(name,conftype,member,initvalue)                             \
00163   { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member), \
00164       initvalue }
00165 
00166 #define V(member,conftype,initvalue)                                    \
00167   VAR(#member, conftype, member, initvalue)
00168 
00169 #define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
00170 
00175 static config_var_t _option_vars[] = {
00176   OBSOLETE("AccountingMaxKB"),
00177   V(AccountingMax,               MEMUNIT,  "0 bytes"),
00178   V(AccountingStart,             STRING,   NULL),
00179   V(Address,                     STRING,   NULL),
00180   V(AllowDotExit,                BOOL,     "0"),
00181   V(AllowInvalidNodes,           CSV,      "middle,rendezvous"),
00182   V(AllowNonRFC953Hostnames,     BOOL,     "0"),
00183   V(AllowSingleHopCircuits,      BOOL,     "0"),
00184   V(AllowSingleHopExits,         BOOL,     "0"),
00185   V(AlternateBridgeAuthority,    LINELIST, NULL),
00186   V(AlternateDirAuthority,       LINELIST, NULL),
00187   V(AlternateHSAuthority,        LINELIST, NULL),
00188   V(AssumeReachable,             BOOL,     "0"),
00189   V(AuthDirBadDir,               LINELIST, NULL),
00190   V(AuthDirBadDirCCs,            CSV,      ""),
00191   V(AuthDirBadExit,              LINELIST, NULL),
00192   V(AuthDirBadExitCCs,           CSV,      ""),
00193   V(AuthDirInvalid,              LINELIST, NULL),
00194   V(AuthDirInvalidCCs,           CSV,      ""),
00195   V(AuthDirFastGuarantee,        MEMUNIT,  "100 KB"),
00196   V(AuthDirGuardBWGuarantee,     MEMUNIT,  "250 KB"),
00197   V(AuthDirReject,               LINELIST, NULL),
00198   V(AuthDirRejectCCs,            CSV,      ""),
00199   V(AuthDirRejectUnlisted,       BOOL,     "0"),
00200   V(AuthDirListBadDirs,          BOOL,     "0"),
00201   V(AuthDirListBadExits,         BOOL,     "0"),
00202   V(AuthDirMaxServersPerAddr,    UINT,     "2"),
00203   V(AuthDirMaxServersPerAuthAddr,UINT,     "5"),
00204   VAR("AuthoritativeDirectory",  BOOL, AuthoritativeDir,    "0"),
00205   V(AutomapHostsOnResolve,       BOOL,     "0"),
00206   V(AutomapHostsSuffixes,        CSV,      ".onion,.exit"),
00207   V(AvoidDiskWrites,             BOOL,     "0"),
00208   V(BandwidthBurst,              MEMUNIT,  "10 MB"),
00209   V(BandwidthRate,               MEMUNIT,  "5 MB"),
00210   V(BridgeAuthoritativeDir,      BOOL,     "0"),
00211   VAR("Bridge",                  LINELIST, Bridges,    NULL),
00212   V(BridgePassword,              STRING,   NULL),
00213   V(BridgeRecordUsageByCountry,  BOOL,     "1"),
00214   V(BridgeRelay,                 BOOL,     "0"),
00215   V(CellStatistics,              BOOL,     "0"),
00216   V(LearnCircuitBuildTimeout,    BOOL,     "1"),
00217   V(CircuitBuildTimeout,         INTERVAL, "0"),
00218   V(CircuitIdleTimeout,          INTERVAL, "1 hour"),
00219   V(CircuitStreamTimeout,        INTERVAL, "0"),
00220   V(CircuitPriorityHalflife,     DOUBLE,  "-100.0"), /*negative:'Use default'*/
00221   V(ClientDNSRejectInternalAddresses, BOOL,"1"),
00222   V(ClientOnly,                  BOOL,     "0"),
00223   V(ClientRejectInternalAddresses, BOOL,   "1"),
00224   V(ClientTransportPlugin,       LINELIST, NULL),
00225   V(ConsensusParams,             STRING,   NULL),
00226   V(ConnLimit,                   UINT,     "1000"),
00227   V(ConnDirectionStatistics,     BOOL,     "0"),
00228   V(ConstrainedSockets,          BOOL,     "0"),
00229   V(ConstrainedSockSize,         MEMUNIT,  "8192"),
00230   V(ContactInfo,                 STRING,   NULL),
00231   V(ControlListenAddress,        LINELIST, NULL),
00232   V(ControlPort,                 LINELIST, NULL),
00233   V(ControlPortFileGroupReadable,BOOL,     "0"),
00234   V(ControlPortWriteToFile,      FILENAME, NULL),
00235   V(ControlSocket,               LINELIST, NULL),
00236   V(ControlSocketsGroupWritable, BOOL,     "0"),
00237   V(CookieAuthentication,        BOOL,     "0"),
00238   V(CookieAuthFileGroupReadable, BOOL,     "0"),
00239   V(CookieAuthFile,              STRING,   NULL),
00240   V(CountPrivateBandwidth,       BOOL,     "0"),
00241   V(DataDirectory,               FILENAME, NULL),
00242   OBSOLETE("DebugLogFile"),
00243   V(DisableNetwork,              BOOL,     "0"),
00244   V(DirAllowPrivateAddresses,    BOOL,     "0"),
00245   V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"),
00246   V(DirListenAddress,            LINELIST, NULL),
00247   OBSOLETE("DirFetchPeriod"),
00248   V(DirPolicy,                   LINELIST, NULL),
00249   V(DirPort,                     LINELIST, NULL),
00250   V(DirPortFrontPage,            FILENAME, NULL),
00251   OBSOLETE("DirPostPeriod"),
00252   OBSOLETE("DirRecordUsageByCountry"),
00253   OBSOLETE("DirRecordUsageGranularity"),
00254   OBSOLETE("DirRecordUsageRetainIPs"),
00255   OBSOLETE("DirRecordUsageSaveInterval"),
00256   V(DirReqStatistics,            BOOL,     "1"),
00257   VAR("DirServer",               LINELIST, DirServers, NULL),
00258   V(DisableAllSwap,              BOOL,     "0"),
00259   V(DisableDebuggerAttachment,   BOOL,     "1"),
00260   V(DisableIOCP,                 BOOL,     "1"),
00261   V(DynamicDHGroups,             BOOL,     "0"),
00262   V(DNSPort,                     LINELIST, NULL),
00263   V(DNSListenAddress,            LINELIST, NULL),
00264   V(DownloadExtraInfo,           BOOL,     "0"),
00265   V(EnforceDistinctSubnets,      BOOL,     "1"),
00266   V(EntryNodes,                  ROUTERSET,   NULL),
00267   V(EntryStatistics,             BOOL,     "0"),
00268   V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "10 minutes"),
00269   V(ExcludeNodes,                ROUTERSET, NULL),
00270   V(ExcludeExitNodes,            ROUTERSET, NULL),
00271   V(ExcludeSingleHopRelays,      BOOL,     "1"),
00272   V(ExitNodes,                   ROUTERSET, NULL),
00273   V(ExitPolicy,                  LINELIST, NULL),
00274   V(ExitPolicyRejectPrivate,     BOOL,     "1"),
00275   V(ExitPortStatistics,          BOOL,     "0"),
00276   V(ExtraInfoStatistics,         BOOL,     "1"),
00277 
00278 #if defined (WINCE)
00279   V(FallbackNetworkstatusFile,   FILENAME, "fallback-consensus"),
00280 #else
00281   V(FallbackNetworkstatusFile,   FILENAME,
00282     SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "fallback-consensus"),
00283 #endif
00284   V(FascistFirewall,             BOOL,     "0"),
00285   V(FirewallPorts,               CSV,      ""),
00286   V(FastFirstHopPK,              BOOL,     "1"),
00287   V(FetchDirInfoEarly,           BOOL,     "0"),
00288   V(FetchDirInfoExtraEarly,      BOOL,     "0"),
00289   V(FetchServerDescriptors,      BOOL,     "1"),
00290   V(FetchHidServDescriptors,     BOOL,     "1"),
00291   V(FetchUselessDescriptors,     BOOL,     "0"),
00292   V(FetchV2Networkstatus,        BOOL,     "0"),
00293 #ifdef _WIN32
00294   V(GeoIPFile,                   FILENAME, "<default>"),
00295 #else
00296   V(GeoIPFile,                   FILENAME,
00297     SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"),
00298 #endif
00299   OBSOLETE("GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays"),
00300   OBSOLETE("Group"),
00301   V(HardwareAccel,               BOOL,     "0"),
00302   V(HeartbeatPeriod,             INTERVAL, "6 hours"),
00303   V(AccelName,                   STRING,   NULL),
00304   V(AccelDir,                    FILENAME, NULL),
00305   V(HashedControlPassword,       LINELIST, NULL),
00306   V(HidServDirectoryV2,          BOOL,     "1"),
00307   VAR("HiddenServiceDir",    LINELIST_S, RendConfigLines,    NULL),
00308   OBSOLETE("HiddenServiceExcludeNodes"),
00309   OBSOLETE("HiddenServiceNodes"),
00310   VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines,    NULL),
00311   VAR("HiddenServicePort",   LINELIST_S, RendConfigLines,    NULL),
00312   VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines,    NULL),
00313   VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL),
00314   V(HidServAuth,                 LINELIST, NULL),
00315   V(HSAuthoritativeDir,          BOOL,     "0"),
00316   OBSOLETE("HSAuthorityRecordStats"),
00317   V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"),
00318   V(CloseHSServiceRendCircuitsImmediatelyOnTimeout, BOOL, "0"),
00319   V(HTTPProxy,                   STRING,   NULL),
00320   V(HTTPProxyAuthenticator,      STRING,   NULL),
00321   V(HTTPSProxy,                  STRING,   NULL),
00322   V(HTTPSProxyAuthenticator,     STRING,   NULL),
00323   VAR("ServerTransportPlugin",   LINELIST, ServerTransportPlugin,  NULL),
00324   V(Socks4Proxy,                 STRING,   NULL),
00325   V(Socks5Proxy,                 STRING,   NULL),
00326   V(Socks5ProxyUsername,         STRING,   NULL),
00327   V(Socks5ProxyPassword,         STRING,   NULL),
00328   OBSOLETE("IgnoreVersion"),
00329   V(KeepalivePeriod,             INTERVAL, "5 minutes"),
00330   VAR("Log",                     LINELIST, Logs,             NULL),
00331   V(LogMessageDomains,           BOOL,     "0"),
00332   OBSOLETE("LinkPadding"),
00333   OBSOLETE("LogLevel"),
00334   OBSOLETE("LogFile"),
00335   V(LogTimeGranularity,          MSEC_INTERVAL, "1 second"),
00336   V(LongLivedPorts,              CSV,
00337         "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
00338   VAR("MapAddress",              LINELIST, AddressMap,           NULL),
00339   V(MaxAdvertisedBandwidth,      MEMUNIT,  "1 GB"),
00340   V(MaxCircuitDirtiness,         INTERVAL, "10 minutes"),
00341   V(MaxClientCircuitsPending,    UINT,     "32"),
00342   V(MaxOnionsPending,            UINT,     "100"),
00343   OBSOLETE("MonthlyAccountingStart"),
00344   V(MyFamily,                    STRING,   NULL),
00345   V(NewCircuitPeriod,            INTERVAL, "30 seconds"),
00346   VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"),
00347   V(NATDListenAddress,           LINELIST, NULL),
00348   V(NATDPort,                    LINELIST, NULL),
00349   V(Nickname,                    STRING,   NULL),
00350   V(WarnUnsafeSocks,              BOOL,     "1"),
00351   OBSOLETE("NoPublish"),
00352   VAR("NodeFamily",              LINELIST, NodeFamilies,         NULL),
00353   V(NumCPUs,                     UINT,     "0"),
00354   V(NumEntryGuards,              UINT,     "3"),
00355   V(ORListenAddress,             LINELIST, NULL),
00356   V(ORPort,                      LINELIST, NULL),
00357   V(OutboundBindAddress,         STRING,   NULL),
00358 
00359   V(PathBiasCircThreshold,       INT,      "-1"),
00360   V(PathBiasNoticeRate,          DOUBLE,   "-1"),
00361   V(PathBiasDisableRate,         DOUBLE,   "-1"),
00362   V(PathBiasScaleThreshold,      INT,      "-1"),
00363   V(PathBiasScaleFactor,         INT,      "-1"),
00364 
00365   OBSOLETE("PathlenCoinWeight"),
00366   V(PerConnBWBurst,              MEMUNIT,  "0"),
00367   V(PerConnBWRate,               MEMUNIT,  "0"),
00368   V(PidFile,                     STRING,   NULL),
00369   V(TestingTorNetwork,           BOOL,     "0"),
00370   V(OptimisticData,              AUTOBOOL, "auto"),
00371   V(PortForwarding,              BOOL,     "0"),
00372   V(PortForwardingHelper,        FILENAME, "tor-fw-helper"),
00373   V(PreferTunneledDirConns,      BOOL,     "1"),
00374   V(ProtocolWarnings,            BOOL,     "0"),
00375   V(PublishServerDescriptor,     CSV,      "1"),
00376   V(PublishHidServDescriptors,   BOOL,     "1"),
00377   V(ReachableAddresses,          LINELIST, NULL),
00378   V(ReachableDirAddresses,       LINELIST, NULL),
00379   V(ReachableORAddresses,        LINELIST, NULL),
00380   V(RecommendedVersions,         LINELIST, NULL),
00381   V(RecommendedClientVersions,   LINELIST, NULL),
00382   V(RecommendedServerVersions,   LINELIST, NULL),
00383   OBSOLETE("RedirectExit"),
00384   V(RefuseUnknownExits,          AUTOBOOL, "auto"),
00385   V(RejectPlaintextPorts,        CSV,      ""),
00386   V(RelayBandwidthBurst,         MEMUNIT,  "0"),
00387   V(RelayBandwidthRate,          MEMUNIT,  "0"),
00388   OBSOLETE("RendExcludeNodes"),
00389   OBSOLETE("RendNodes"),
00390   V(RendPostPeriod,              INTERVAL, "1 hour"),
00391   V(RephistTrackTime,            INTERVAL, "24 hours"),
00392   OBSOLETE("RouterFile"),
00393   V(RunAsDaemon,                 BOOL,     "0"),
00394 //  V(RunTesting,                  BOOL,     "0"),
00395   OBSOLETE("RunTesting"), // currently unused
00396   V(SafeLogging,                 STRING,   "1"),
00397   V(SafeSocks,                   BOOL,     "0"),
00398   V(ServerDNSAllowBrokenConfig,  BOOL,     "1"),
00399   V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"),
00400   V(ServerDNSDetectHijacking,    BOOL,     "1"),
00401   V(ServerDNSRandomizeCase,      BOOL,     "1"),
00402   V(ServerDNSResolvConfFile,     STRING,   NULL),
00403   V(ServerDNSSearchDomains,      BOOL,     "0"),
00404   V(ServerDNSTestAddresses,      CSV,
00405       "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"),
00406   V(ShutdownWaitLength,          INTERVAL, "30 seconds"),
00407   V(SocksListenAddress,          LINELIST, NULL),
00408   V(SocksPolicy,                 LINELIST, NULL),
00409   V(SocksPort,                   LINELIST, NULL),
00410   V(SocksTimeout,                INTERVAL, "2 minutes"),
00411   OBSOLETE("StatusFetchPeriod"),
00412   V(StrictNodes,                 BOOL,     "0"),
00413   OBSOLETE("SysLog"),
00414   V(TestSocks,                   BOOL,     "0"),
00415   OBSOLETE("TestVia"),
00416   V(TokenBucketRefillInterval,   MSEC_INTERVAL, "100 msec"),
00417   V(Tor2webMode,                 BOOL,     "0"),
00418   V(TrackHostExits,              CSV,      NULL),
00419   V(TrackHostExitsExpire,        INTERVAL, "30 minutes"),
00420   OBSOLETE("TrafficShaping"),
00421   V(TransListenAddress,          LINELIST, NULL),
00422   V(TransPort,                   LINELIST, NULL),
00423   V(TunnelDirConns,              BOOL,     "1"),
00424   V(UpdateBridgesFromAuthority,  BOOL,     "0"),
00425   V(UseBridges,                  BOOL,     "0"),
00426   V(UseEntryGuards,              BOOL,     "1"),
00427   V(UseMicrodescriptors,         AUTOBOOL, "auto"),
00428   V(User,                        STRING,   NULL),
00429   V(UserspaceIOCPBuffers,        BOOL,     "0"),
00430   VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir,   "0"),
00431   VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir,   "0"),
00432   VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir,   "0"),
00433   V(TestingV3AuthInitialVotingInterval, INTERVAL, "30 minutes"),
00434   V(TestingV3AuthInitialVoteDelay, INTERVAL, "5 minutes"),
00435   V(TestingV3AuthInitialDistDelay, INTERVAL, "5 minutes"),
00436   V(V3AuthVotingInterval,        INTERVAL, "1 hour"),
00437   V(V3AuthVoteDelay,             INTERVAL, "5 minutes"),
00438   V(V3AuthDistDelay,             INTERVAL, "5 minutes"),
00439   V(V3AuthNIntervalsValid,       UINT,     "3"),
00440   V(V3AuthUseLegacyKey,          BOOL,     "0"),
00441   V(V3BandwidthsFile,            FILENAME, NULL),
00442   VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
00443   V(VirtualAddrNetwork,          STRING,   "127.192.0.0/10"),
00444   V(WarnPlaintextPorts,          CSV,      "23,109,110,143"),
00445   V(_UseFilteringSSLBufferevents, BOOL,    "0"),
00446   VAR("__ReloadTorrcOnSIGHUP",   BOOL,  ReloadTorrcOnSIGHUP,      "1"),
00447   VAR("__AllDirActionsPrivate",  BOOL,  AllDirActionsPrivate,     "0"),
00448   VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
00449   VAR("__LeaveStreamsUnattached",BOOL,  LeaveStreamsUnattached,   "0"),
00450   VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword,
00451       NULL),
00452   VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
00453   V(MinUptimeHidServDirectoryV2, INTERVAL, "25 hours"),
00454   V(VoteOnHidServDirectoriesV2,  BOOL,     "1"),
00455   V(_UsingTestNetworkDefaults,   BOOL,     "0"),
00456 
00457   { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
00458 };
00459 
00462 static const config_var_t testing_tor_network_defaults[] = {
00463   V(ServerDNSAllowBrokenConfig,  BOOL,  "1"),
00464   V(DirAllowPrivateAddresses,    BOOL,     "1"),
00465   V(EnforceDistinctSubnets,      BOOL,     "0"),
00466   V(AssumeReachable,             BOOL,     "1"),
00467   V(AuthDirMaxServersPerAddr,    UINT,     "0"),
00468   V(AuthDirMaxServersPerAuthAddr,UINT,     "0"),
00469   V(ClientDNSRejectInternalAddresses, BOOL,"0"),
00470   V(ClientRejectInternalAddresses, BOOL,   "0"),
00471   V(CountPrivateBandwidth,       BOOL,     "1"),
00472   V(ExitPolicyRejectPrivate,     BOOL,     "0"),
00473   V(V3AuthVotingInterval,        INTERVAL, "5 minutes"),
00474   V(V3AuthVoteDelay,             INTERVAL, "20 seconds"),
00475   V(V3AuthDistDelay,             INTERVAL, "20 seconds"),
00476   V(TestingV3AuthInitialVotingInterval, INTERVAL, "5 minutes"),
00477   V(TestingV3AuthInitialVoteDelay, INTERVAL, "20 seconds"),
00478   V(TestingV3AuthInitialDistDelay, INTERVAL, "20 seconds"),
00479   V(TestingAuthDirTimeToLearnReachability, INTERVAL, "0 minutes"),
00480   V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
00481   V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"),
00482   V(_UsingTestNetworkDefaults,   BOOL,     "1"),
00483 
00484   { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
00485 };
00486 #undef VAR
00487 
00488 #define VAR(name,conftype,member,initvalue)                             \
00489   { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member),  \
00490       initvalue }
00491 
00493 static config_var_t _state_vars[] = {
00494   /* Remember to document these in state-contents.txt ! */
00495 
00496   V(AccountingBytesReadInInterval,    MEMUNIT,  NULL),
00497   V(AccountingBytesWrittenInInterval, MEMUNIT,  NULL),
00498   V(AccountingExpectedUsage,          MEMUNIT,  NULL),
00499   V(AccountingIntervalStart,          ISOTIME,  NULL),
00500   V(AccountingSecondsActive,          INTERVAL, NULL),
00501   V(AccountingSecondsToReachSoftLimit,INTERVAL, NULL),
00502   V(AccountingSoftLimitHitAt,         ISOTIME,  NULL),
00503   V(AccountingBytesAtSoftLimit,       MEMUNIT,  NULL),
00504 
00505   VAR("EntryGuard",              LINELIST_S,  EntryGuards,             NULL),
00506   VAR("EntryGuardDownSince",     LINELIST_S,  EntryGuards,             NULL),
00507   VAR("EntryGuardUnlistedSince", LINELIST_S,  EntryGuards,             NULL),
00508   VAR("EntryGuardAddedBy",       LINELIST_S,  EntryGuards,             NULL),
00509   VAR("EntryGuardPathBias",      LINELIST_S,  EntryGuards,             NULL),
00510   V(EntryGuards,                 LINELIST_V,  NULL),
00511 
00512   VAR("TransportProxy",               LINELIST_S, TransportProxies, NULL),
00513   V(TransportProxies,                 LINELIST_V, NULL),
00514 
00515   V(BWHistoryReadEnds,                ISOTIME,  NULL),
00516   V(BWHistoryReadInterval,            UINT,     "900"),
00517   V(BWHistoryReadValues,              CSV,      ""),
00518   V(BWHistoryReadMaxima,              CSV,      ""),
00519   V(BWHistoryWriteEnds,               ISOTIME,  NULL),
00520   V(BWHistoryWriteInterval,           UINT,     "900"),
00521   V(BWHistoryWriteValues,             CSV,      ""),
00522   V(BWHistoryWriteMaxima,             CSV,      ""),
00523   V(BWHistoryDirReadEnds,             ISOTIME,  NULL),
00524   V(BWHistoryDirReadInterval,         UINT,     "900"),
00525   V(BWHistoryDirReadValues,           CSV,      ""),
00526   V(BWHistoryDirReadMaxima,           CSV,      ""),
00527   V(BWHistoryDirWriteEnds,            ISOTIME,  NULL),
00528   V(BWHistoryDirWriteInterval,        UINT,     "900"),
00529   V(BWHistoryDirWriteValues,          CSV,      ""),
00530   V(BWHistoryDirWriteMaxima,          CSV,      ""),
00531 
00532   V(TorVersion,                       STRING,   NULL),
00533 
00534   V(LastRotatedOnionKey,              ISOTIME,  NULL),
00535   V(LastWritten,                      ISOTIME,  NULL),
00536 
00537   V(TotalBuildTimes,                  UINT,     NULL),
00538   V(CircuitBuildAbandonedCount,       UINT,     "0"),
00539   VAR("CircuitBuildTimeBin",          LINELIST_S, BuildtimeHistogram, NULL),
00540   VAR("BuildtimeHistogram",           LINELIST_V, BuildtimeHistogram, NULL),
00541   { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
00542 };
00543 
00544 #undef VAR
00545 #undef V
00546 #undef OBSOLETE
00547 
00550 typedef struct config_var_description_t {
00551   const char *name;
00552   const char *description;
00553 } config_var_description_t;
00554 
00558 typedef int (*validate_fn_t)(void*,void*,int,char**);
00559 
00563 typedef struct {
00564   size_t size; 
00565   uint32_t magic; 
00567   off_t magic_offset; 
00568   config_abbrev_t *abbrevs; 
00570   config_var_t *vars; 
00572   validate_fn_t validate_fn; 
00575   config_var_t *extra;
00576 } config_format_t;
00577 
00580 #define CHECK(fmt, cfg) STMT_BEGIN                                      \
00581     tor_assert(fmt && cfg);                                             \
00582     tor_assert((fmt)->magic ==                                          \
00583                *(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset));        \
00584   STMT_END
00585 
00586 #ifdef _WIN32
00587 static char *get_windows_conf_root(void);
00588 #endif
00589 static void config_line_append(config_line_t **lst,
00590                                const char *key, const char *val);
00591 static void option_clear(const config_format_t *fmt, or_options_t *options,
00592                          const config_var_t *var);
00593 static void option_reset(const config_format_t *fmt, or_options_t *options,
00594                          const config_var_t *var, int use_defaults);
00595 static void config_free(const config_format_t *fmt, void *options);
00596 static int config_lines_eq(config_line_t *a, config_line_t *b);
00597 static int option_is_same(const config_format_t *fmt,
00598                           const or_options_t *o1, const or_options_t *o2,
00599                           const char *name);
00600 static or_options_t *options_dup(const config_format_t *fmt,
00601                                  const or_options_t *old);
00602 static int options_validate(or_options_t *old_options,
00603                             or_options_t *options,
00604                             int from_setconf, char **msg);
00605 static int options_act_reversible(const or_options_t *old_options, char **msg);
00606 static int options_act(const or_options_t *old_options);
00607 static int options_transition_allowed(const or_options_t *old,
00608                                       const or_options_t *new,
00609                                       char **msg);
00610 static int options_transition_affects_workers(
00611       const or_options_t *old_options, const or_options_t *new_options);
00612 static int options_transition_affects_descriptor(
00613       const or_options_t *old_options, const or_options_t *new_options);
00614 static int check_nickname_list(const char *lst, const char *name, char **msg);
00615 
00616 static int parse_bridge_line(const char *line, int validate_only);
00617 static int parse_client_transport_line(const char *line, int validate_only);
00618 
00619 static int parse_server_transport_line(const char *line, int validate_only);
00620 static int parse_dir_server_line(const char *line,
00621                                  dirinfo_type_t required_type,
00622                                  int validate_only);
00623 static void port_cfg_free(port_cfg_t *port);
00624 static int parse_ports(const or_options_t *options, int validate_only,
00625                               char **msg_out, int *n_ports_out);
00626 static int check_server_ports(const smartlist_t *ports,
00627                               const or_options_t *options);
00628 
00629 static int validate_data_directory(or_options_t *options);
00630 static int write_configuration_file(const char *fname,
00631                                     const or_options_t *options);
00632 static config_line_t *get_assigned_option(const config_format_t *fmt,
00633                                         const void *options, const char *key,
00634                                         int escape_val);
00635 static void config_init(const config_format_t *fmt, void *options);
00636 static int or_state_validate(or_state_t *old_options, or_state_t *options,
00637                              int from_setconf, char **msg);
00638 static int or_state_load(void);
00639 static int options_init_logs(or_options_t *options, int validate_only);
00640 
00641 static uint64_t config_parse_memunit(const char *s, int *ok);
00642 static int config_parse_msec_interval(const char *s, int *ok);
00643 static int config_parse_interval(const char *s, int *ok);
00644 static void init_libevent(const or_options_t *options);
00645 static int opt_streq(const char *s1, const char *s2);
00646 
00648 #define OR_OPTIONS_MAGIC 9090909
00649 
00651 static config_format_t options_format = {
00652   sizeof(or_options_t),
00653   OR_OPTIONS_MAGIC,
00654   STRUCT_OFFSET(or_options_t, _magic),
00655   _option_abbrevs,
00656   _option_vars,
00657   (validate_fn_t)options_validate,
00658   NULL
00659 };
00660 
00662 #define OR_STATE_MAGIC 0x57A73f57
00663 
00666 static config_var_t state_extra_var = {
00667   "__extra", CONFIG_TYPE_LINELIST, STRUCT_OFFSET(or_state_t, ExtraLines), NULL
00668 };
00669 
00671 static const config_format_t state_format = {
00672   sizeof(or_state_t),
00673   OR_STATE_MAGIC,
00674   STRUCT_OFFSET(or_state_t, _magic),
00675   _state_abbrevs,
00676   _state_vars,
00677   (validate_fn_t)or_state_validate,
00678   &state_extra_var,
00679 };
00680 
00681 /*
00682  * Functions to read and write the global options pointer.
00683  */
00684 
00686 static or_options_t *global_options = NULL;
00689 static or_options_t *global_default_options = NULL;
00691 static char *torrc_fname = NULL;
00693 static char *torrc_defaults_fname;
00695 static or_state_t *global_state = NULL;
00697 static config_line_t *global_cmdline_options = NULL;
00699 static char *global_dirfrontpagecontents = NULL;
00701 static smartlist_t *configured_ports = NULL;
00702 
00704 const char *
00705 get_dirportfrontpage(void)
00706 {
00707   return global_dirfrontpagecontents;
00708 }
00709 
00711 static void *
00712 config_alloc(const config_format_t *fmt)
00713 {
00714   void *opts = tor_malloc_zero(fmt->size);
00715   *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
00716   CHECK(fmt, opts);
00717   return opts;
00718 }
00719 
00721 or_options_t *
00722 get_options_mutable(void)
00723 {
00724   tor_assert(global_options);
00725   return global_options;
00726 }
00727 
00729 const or_options_t *
00730 get_options(void)
00731 {
00732   return get_options_mutable();
00733 }
00734 
00739 int
00740 set_options(or_options_t *new_val, char **msg)
00741 {
00742   int i;
00743   smartlist_t *elements;
00744   config_line_t *line;
00745   or_options_t *old_options = global_options;
00746   global_options = new_val;
00747   /* Note that we pass the *old* options below, for comparison. It
00748    * pulls the new options directly out of global_options. */
00749   if (options_act_reversible(old_options, msg)<0) {
00750     tor_assert(*msg);
00751     global_options = old_options;
00752     return -1;
00753   }
00754   if (options_act(old_options) < 0) { /* acting on the options failed. die. */
00755     log_err(LD_BUG,
00756             "Acting on config options left us in a broken state. Dying.");
00757     exit(1);
00758   }
00759   /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
00760    * just starting up then the old_options will be undefined. */
00761   if (old_options && old_options != global_options) {
00762     elements = smartlist_new();
00763     for (i=0; options_format.vars[i].name; ++i) {
00764       const config_var_t *var = &options_format.vars[i];
00765       const char *var_name = var->name;
00766       if (var->type == CONFIG_TYPE_LINELIST_S ||
00767           var->type == CONFIG_TYPE_OBSOLETE) {
00768         continue;
00769       }
00770       if (!option_is_same(&options_format, new_val, old_options, var_name)) {
00771         line = get_assigned_option(&options_format, new_val, var_name, 1);
00772 
00773         if (line) {
00774           for (; line; line = line->next) {
00775             smartlist_add(elements, line->key);
00776             smartlist_add(elements, line->value);
00777           }
00778         } else {
00779           smartlist_add(elements, (char*)options_format.vars[i].name);
00780           smartlist_add(elements, NULL);
00781         }
00782       }
00783     }
00784     control_event_conf_changed(elements);
00785     smartlist_free(elements);
00786   }
00787 
00788   if (old_options != global_options)
00789     config_free(&options_format, old_options);
00790 
00791   return 0;
00792 }
00793 
00794 extern const char tor_git_revision[]; /* from tor_main.c */
00795 
00797 static char *the_tor_version = NULL;
00800 static char *the_short_tor_version = NULL;
00801 
00803 const char *
00804 get_version(void)
00805 {
00806   if (the_tor_version == NULL) {
00807     if (strlen(tor_git_revision)) {
00808       tor_asprintf(&the_tor_version, "%s (git-%s)", get_short_version(),
00809                    tor_git_revision);
00810     } else {
00811       the_tor_version = tor_strdup(get_short_version());
00812     }
00813   }
00814   return the_tor_version;
00815 }
00816 
00818 const char *
00819 get_short_version(void)
00820 {
00821 
00822   if (the_short_tor_version == NULL) {
00823 #ifdef TOR_BUILD_TAG
00824     tor_asprintf(&the_short_tor_version, "%s (%s)", VERSION, TOR_BUILD_TAG);
00825 #else
00826     the_short_tor_version = tor_strdup(VERSION);
00827 #endif
00828   }
00829   return the_short_tor_version;
00830 }
00831 
00834 static void
00835 or_options_free(or_options_t *options)
00836 {
00837   if (!options)
00838     return;
00839 
00840   routerset_free(options->_ExcludeExitNodesUnion);
00841   if (options->NodeFamilySets) {
00842     SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *,
00843                       rs, routerset_free(rs));
00844     smartlist_free(options->NodeFamilySets);
00845   }
00846   tor_free(options->_BridgePassword_AuthDigest);
00847   config_free(&options_format, options);
00848 }
00849 
00852 void
00853 config_free_all(void)
00854 {
00855   or_options_free(global_options);
00856   global_options = NULL;
00857   or_options_free(global_default_options);
00858   global_default_options = NULL;
00859 
00860   config_free(&state_format, global_state);
00861   global_state = NULL;
00862 
00863   config_free_lines(global_cmdline_options);
00864   global_cmdline_options = NULL;
00865 
00866   if (configured_ports) {
00867     SMARTLIST_FOREACH(configured_ports,
00868                       port_cfg_t *, p, tor_free(p));
00869     smartlist_free(configured_ports);
00870     configured_ports = NULL;
00871   }
00872 
00873   tor_free(torrc_fname);
00874   tor_free(torrc_defaults_fname);
00875   tor_free(the_tor_version);
00876   tor_free(global_dirfrontpagecontents);
00877 }
00878 
00885 const char *
00886 safe_str_client(const char *address)
00887 {
00888   tor_assert(address);
00889   if (get_options()->_SafeLogging == SAFELOG_SCRUB_ALL)
00890     return "[scrubbed]";
00891   else
00892     return address;
00893 }
00894 
00902 const char *
00903 safe_str(const char *address)
00904 {
00905   tor_assert(address);
00906   if (get_options()->_SafeLogging != SAFELOG_SCRUB_NONE)
00907     return "[scrubbed]";
00908   else
00909     return address;
00910 }
00911 
00915 const char *
00916 escaped_safe_str_client(const char *address)
00917 {
00918   if (get_options()->_SafeLogging == SAFELOG_SCRUB_ALL)
00919     return "[scrubbed]";
00920   else
00921     return escaped(address);
00922 }
00923 
00927 const char *
00928 escaped_safe_str(const char *address)
00929 {
00930   if (get_options()->_SafeLogging != SAFELOG_SCRUB_NONE)
00931     return "[scrubbed]";
00932   else
00933     return escaped(address);
00934 }
00935 
00938 static void
00939 add_default_trusted_dir_authorities(dirinfo_type_t type)
00940 {
00941   int i;
00942   const char *dirservers[] = {
00943     "moria1 orport=9101 no-v2 "
00944       "v3ident=D586D18309DED4CD6D57C18FDB97EFA96D330566 "
00945       "128.31.0.39:9131 9695 DFC3 5FFE B861 329B 9F1A B04C 4639 7020 CE31",
00946     "tor26 v1 orport=443 v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 "
00947       "86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D",
00948     "dizum orport=443 v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 "
00949       "194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
00950     "Tonga orport=443 bridge no-v2 82.94.251.203:80 "
00951       "4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D",
00952     "turtles orport=9090 no-v2 "
00953       "v3ident=27B6B5996C426270A5C95488AA5BCEB6BCC86956 "
00954       "76.73.17.194:9030 F397 038A DC51 3361 35E7 B80B D99C A384 4360 292B",
00955     "gabelmoo orport=443 no-v2 "
00956       "v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
00957       "212.112.245.170:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
00958     "dannenberg orport=443 no-v2 "
00959       "v3ident=585769C78764D58426B8B52B6651A5A71137189A "
00960       "193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123",
00961     "urras orport=80 no-v2 v3ident=80550987E1D626E3EBA5E5E75A458DE0626D088C "
00962       "208.83.223.34:443 0AD3 FA88 4D18 F89E EA2D 89C0 1937 9E0E 7FD9 4417",
00963     "maatuska orport=80 no-v2 "
00964       "v3ident=49015F787433103580E3B66A1707A00E60F2D15B "
00965       "171.25.193.9:443 BD6A 8292 55CB 08E6 6FBE 7D37 4836 3586 E46B 3810",
00966     NULL
00967   };
00968   for (i=0; dirservers[i]; i++) {
00969     if (parse_dir_server_line(dirservers[i], type, 0)<0) {
00970       log_err(LD_BUG, "Couldn't parse internal dirserver line %s",
00971               dirservers[i]);
00972     }
00973   }
00974 }
00975 
00980 static int
00981 validate_dir_authorities(or_options_t *options, or_options_t *old_options)
00982 {
00983   config_line_t *cl;
00984 
00985   if (options->DirServers &&
00986       (options->AlternateDirAuthority || options->AlternateBridgeAuthority ||
00987        options->AlternateHSAuthority)) {
00988     log_warn(LD_CONFIG,
00989              "You cannot set both DirServers and Alternate*Authority.");
00990     return -1;
00991   }
00992 
00993   /* do we want to complain to the user about being partitionable? */
00994   if ((options->DirServers &&
00995        (!old_options ||
00996         !config_lines_eq(options->DirServers, old_options->DirServers))) ||
00997       (options->AlternateDirAuthority &&
00998        (!old_options ||
00999         !config_lines_eq(options->AlternateDirAuthority,
01000                          old_options->AlternateDirAuthority)))) {
01001     log_warn(LD_CONFIG,
01002              "You have used DirServer or AlternateDirAuthority to "
01003              "specify alternate directory authorities in "
01004              "your configuration. This is potentially dangerous: it can "
01005              "make you look different from all other Tor users, and hurt "
01006              "your anonymity. Even if you've specified the same "
01007              "authorities as Tor uses by default, the defaults could "
01008              "change in the future. Be sure you know what you're doing.");
01009   }
01010 
01011   /* Now go through the four ways you can configure an alternate
01012    * set of directory authorities, and make sure none are broken. */
01013   for (cl = options->DirServers; cl; cl = cl->next)
01014     if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
01015       return -1;
01016   for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
01017     if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
01018       return -1;
01019   for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
01020     if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
01021       return -1;
01022   for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
01023     if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
01024       return -1;
01025   return 0;
01026 }
01027 
01031 static int
01032 consider_adding_dir_authorities(const or_options_t *options,
01033                                 const or_options_t *old_options)
01034 {
01035   config_line_t *cl;
01036   int need_to_update =
01037     !smartlist_len(router_get_trusted_dir_servers()) || !old_options ||
01038     !config_lines_eq(options->DirServers, old_options->DirServers) ||
01039     !config_lines_eq(options->AlternateBridgeAuthority,
01040                      old_options->AlternateBridgeAuthority) ||
01041     !config_lines_eq(options->AlternateDirAuthority,
01042                      old_options->AlternateDirAuthority) ||
01043     !config_lines_eq(options->AlternateHSAuthority,
01044                      old_options->AlternateHSAuthority);
01045 
01046   if (!need_to_update)
01047     return 0; /* all done */
01048 
01049   /* Start from a clean slate. */
01050   clear_trusted_dir_servers();
01051 
01052   if (!options->DirServers) {
01053     /* then we may want some of the defaults */
01054     dirinfo_type_t type = NO_DIRINFO;
01055     if (!options->AlternateBridgeAuthority)
01056       type |= BRIDGE_DIRINFO;
01057     if (!options->AlternateDirAuthority)
01058       type |= V1_DIRINFO | V2_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
01059         MICRODESC_DIRINFO;
01060     if (!options->AlternateHSAuthority)
01061       type |= HIDSERV_DIRINFO;
01062     add_default_trusted_dir_authorities(type);
01063   }
01064 
01065   for (cl = options->DirServers; cl; cl = cl->next)
01066     if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
01067       return -1;
01068   for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
01069     if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
01070       return -1;
01071   for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
01072     if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
01073       return -1;
01074   for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
01075     if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
01076       return -1;
01077   return 0;
01078 }
01079 
01086 static int
01087 options_act_reversible(const or_options_t *old_options, char **msg)
01088 {
01089   smartlist_t *new_listeners = smartlist_new();
01090   smartlist_t *replaced_listeners = smartlist_new();
01091   static int libevent_initialized = 0;
01092   or_options_t *options = get_options_mutable();
01093   int running_tor = options->command == CMD_RUN_TOR;
01094   int set_conn_limit = 0;
01095   int r = -1;
01096   int logs_marked = 0;
01097 
01098   /* Daemonize _first_, since we only want to open most of this stuff in
01099    * the subprocess.  Libevent bases can't be reliably inherited across
01100    * processes. */
01101   if (running_tor && options->RunAsDaemon) {
01102     /* No need to roll back, since you can't change the value. */
01103     start_daemon();
01104   }
01105 
01106 #ifndef HAVE_SYS_UN_H
01107   if (options->ControlSocket || options->ControlSocketsGroupWritable) {
01108     *msg = tor_strdup("Unix domain sockets (ControlSocket) not supported "
01109                       "on this OS/with this build.");
01110     goto rollback;
01111   }
01112 #else
01113   if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
01114     *msg = tor_strdup("Setting ControlSocketGroupWritable without setting"
01115                       "a ControlSocket makes no sense.");
01116     goto rollback;
01117   }
01118 #endif
01119 
01120   if (running_tor) {
01121     int n_ports=0;
01122     /* We need to set the connection limit before we can open the listeners. */
01123     if (set_max_file_descriptors((unsigned)options->ConnLimit,
01124                                  &options->_ConnLimit) < 0) {
01125       *msg = tor_strdup("Problem with ConnLimit value. See logs for details.");
01126       goto rollback;
01127     }
01128     set_conn_limit = 1;
01129 
01130     /* Set up libevent.  (We need to do this before we can register the
01131      * listeners as listeners.) */
01132     if (running_tor && !libevent_initialized) {
01133       init_libevent(options);
01134       libevent_initialized = 1;
01135     }
01136 
01137     /* Adjust the port configuration so we can launch listeners. */
01138     if (parse_ports(options, 0, msg, &n_ports)) {
01139       if (!*msg)
01140         *msg = tor_strdup("Unexpected problem parsing port config");
01141       goto rollback;
01142     }
01143 
01144     /* Set the hibernation state appropriately.*/
01145     consider_hibernation(time(NULL));
01146 
01147     /* Launch the listeners.  (We do this before we setuid, so we can bind to
01148      * ports under 1024.)  We don't want to rebind if we're hibernating. If
01149      * networking is disabled, this will close all but the control listeners,
01150      * but disable those. */
01151     if (!we_are_hibernating()) {
01152       if (retry_all_listeners(replaced_listeners, new_listeners,
01153                               options->DisableNetwork) < 0) {
01154         *msg = tor_strdup("Failed to bind one of the listener ports.");
01155         goto rollback;
01156       }
01157     }
01158     if (options->DisableNetwork) {
01159       /* Aggressively close non-controller stuff, NOW */
01160       log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept "
01161                  "non-control network connections. Shutting down all existing "
01162                  "connections.");
01163       connection_mark_all_noncontrol_connections();
01164     }
01165   }
01166 
01167 #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
01168   /* Open /dev/pf before dropping privileges. */
01169   if (options->TransPort) {
01170     if (get_pf_socket() < 0) {
01171       *msg = tor_strdup("Unable to open /dev/pf for transparent proxy.");
01172       goto rollback;
01173     }
01174   }
01175 #endif
01176 
01177   /* Attempt to lock all current and future memory with mlockall() only once */
01178   if (options->DisableAllSwap) {
01179     if (tor_mlockall() == -1) {
01180       *msg = tor_strdup("DisableAllSwap failure. Do you have proper "
01181                         "permissions?");
01182       goto done;
01183     }
01184   }
01185 
01186   /* Setuid/setgid as appropriate */
01187   if (options->User) {
01188     if (switch_id(options->User) != 0) {
01189       /* No need to roll back, since you can't change the value. */
01190       *msg = tor_strdup("Problem with User value. See logs for details.");
01191       goto done;
01192     }
01193   }
01194 
01195   /* Ensure data directory is private; create if possible. */
01196   if (check_private_dir(options->DataDirectory,
01197                         running_tor ? CPD_CREATE : CPD_CHECK,
01198                         options->User)<0) {
01199     tor_asprintf(msg,
01200               "Couldn't access/create private data directory \"%s\"",
01201               options->DataDirectory);
01202     goto done;
01203     /* No need to roll back, since you can't change the value. */
01204   }
01205 
01206   /* Write control ports to disk as appropriate */
01207   control_ports_write_to_file();
01208 
01209   if (directory_caches_v2_dir_info(options)) {
01210     char *fn = NULL;
01211     tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-status",
01212                  options->DataDirectory);
01213     if (check_private_dir(fn, running_tor ? CPD_CREATE : CPD_CHECK,
01214                           options->User) < 0) {
01215       tor_asprintf(msg,
01216                 "Couldn't access/create private data directory \"%s\"", fn);
01217       tor_free(fn);
01218       goto done;
01219     }
01220     tor_free(fn);
01221   }
01222 
01223   /* Bail out at this point if we're not going to be a client or server:
01224    * we don't run Tor itself. */
01225   if (!running_tor)
01226     goto commit;
01227 
01228   mark_logs_temp(); /* Close current logs once new logs are open. */
01229   logs_marked = 1;
01230   if (options_init_logs(options, 0)<0) { /* Configure the log(s) */
01231     *msg = tor_strdup("Failed to init Log options. See logs for details.");
01232     goto rollback;
01233   }
01234 
01235  commit:
01236   r = 0;
01237   if (logs_marked) {
01238     log_severity_list_t *severity =
01239       tor_malloc_zero(sizeof(log_severity_list_t));
01240     close_temp_logs();
01241     add_callback_log(severity, control_event_logmsg);
01242     control_adjust_event_log_severity();
01243     tor_free(severity);
01244   }
01245   SMARTLIST_FOREACH(replaced_listeners, connection_t *, conn,
01246   {
01247     log_notice(LD_NET, "Closing old %s on %s:%d",
01248                conn_type_to_string(conn->type), conn->address, conn->port);
01249     connection_close_immediate(conn);
01250     connection_mark_for_close(conn);
01251   });
01252   goto done;
01253 
01254  rollback:
01255   r = -1;
01256   tor_assert(*msg);
01257 
01258   if (logs_marked) {
01259     rollback_log_changes();
01260     control_adjust_event_log_severity();
01261   }
01262 
01263   if (set_conn_limit && old_options)
01264     set_max_file_descriptors((unsigned)old_options->ConnLimit,
01265                              &options->_ConnLimit);
01266 
01267   SMARTLIST_FOREACH(new_listeners, connection_t *, conn,
01268   {
01269     log_notice(LD_NET, "Closing partially-constructed %s on %s:%d",
01270                conn_type_to_string(conn->type), conn->address, conn->port);
01271     connection_close_immediate(conn);
01272     connection_mark_for_close(conn);
01273   });
01274 
01275  done:
01276   smartlist_free(new_listeners);
01277   smartlist_free(replaced_listeners);
01278   return r;
01279 }
01280 
01283 int
01284 options_need_geoip_info(const or_options_t *options, const char **reason_out)
01285 {
01286   int bridge_usage =
01287     options->BridgeRelay && options->BridgeRecordUsageByCountry;
01288   int routerset_usage =
01289     routerset_needs_geoip(options->EntryNodes) ||
01290     routerset_needs_geoip(options->ExitNodes) ||
01291     routerset_needs_geoip(options->ExcludeExitNodes) ||
01292     routerset_needs_geoip(options->ExcludeNodes);
01293 
01294   if (routerset_usage && reason_out) {
01295     *reason_out = "We've been configured to use (or avoid) nodes in certain "
01296       "countries, and we need GEOIP information to figure out which ones they "
01297       "are.";
01298   } else if (bridge_usage && reason_out) {
01299     *reason_out = "We've been configured to see which countries can access "
01300       "us as a bridge, and we need GEOIP information to tell which countries "
01301       "clients are in.";
01302   }
01303   return bridge_usage || routerset_usage;
01304 }
01305 
01308 uint32_t
01309 get_effective_bwrate(const or_options_t *options)
01310 {
01311   uint64_t bw = options->BandwidthRate;
01312   if (bw > options->MaxAdvertisedBandwidth)
01313     bw = options->MaxAdvertisedBandwidth;
01314   if (options->RelayBandwidthRate > 0 && bw > options->RelayBandwidthRate)
01315     bw = options->RelayBandwidthRate;
01316   /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
01317   return (uint32_t)bw;
01318 }
01319 
01322 uint32_t
01323 get_effective_bwburst(const or_options_t *options)
01324 {
01325   uint64_t bw = options->BandwidthBurst;
01326   if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
01327     bw = options->RelayBandwidthBurst;
01328   /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
01329   return (uint32_t)bw;
01330 }
01331 
01334 static int
01335 options_transition_requires_fresh_tls_context(const or_options_t *old_options,
01336                                               const or_options_t *new_options)
01337 {
01338   tor_assert(new_options);
01339 
01340   if (!old_options)
01341     return 0;
01342 
01343   if ((old_options->DynamicDHGroups != new_options->DynamicDHGroups)) {
01344     return 1;
01345   }
01346 
01347   return 0;
01348 }
01349 
01359 static int
01360 options_act(const or_options_t *old_options)
01361 {
01362   config_line_t *cl;
01363   or_options_t *options = get_options_mutable();
01364   int running_tor = options->command == CMD_RUN_TOR;
01365   char *msg;
01366   const int transition_affects_workers =
01367     old_options && options_transition_affects_workers(old_options, options);
01368 
01369   /* disable ptrace and later, other basic debugging techniques */
01370   {
01371     /* Remember if we already disabled debugger attachment */
01372     static int disabled_debugger_attach = 0;
01373     /* Remember if we already warned about being configured not to disable
01374      * debugger attachment */
01375     static int warned_debugger_attach = 0;
01376     /* Don't disable debugger attachment when we're running the unit tests. */
01377     if (options->DisableDebuggerAttachment && !disabled_debugger_attach &&
01378         running_tor) {
01379       int ok = tor_disable_debugger_attach();
01380       if (warned_debugger_attach && ok == 1) {
01381         log_notice(LD_CONFIG, "Disabled attaching debuggers for unprivileged "
01382                    "users.");
01383       }
01384       disabled_debugger_attach = (ok == 1);
01385     } else if (!options->DisableDebuggerAttachment &&
01386                !warned_debugger_attach) {
01387       log_notice(LD_CONFIG, "Not disabling debugger attaching for "
01388                  "unprivileged users.");
01389       warned_debugger_attach = 1;
01390     }
01391   }
01392 
01393   if (running_tor && !have_lockfile()) {
01394     if (try_locking(options, 1) < 0)
01395       return -1;
01396   }
01397 
01398   if (consider_adding_dir_authorities(options, old_options) < 0)
01399     return -1;
01400 
01401 #ifdef NON_ANONYMOUS_MODE_ENABLED
01402   log(LOG_WARN, LD_GENERAL, "This copy of Tor was compiled to run in a "
01403       "non-anonymous mode. It will provide NO ANONYMITY.");
01404 #endif
01405 
01406 #ifdef ENABLE_TOR2WEB_MODE
01407   if (!options->Tor2webMode) {
01408     log_err(LD_CONFIG, "This copy of Tor was compiled to run in "
01409             "'tor2web mode'. It can only be run with the Tor2webMode torrc "
01410             "option enabled.");
01411     return -1;
01412   }
01413 #else
01414   if (options->Tor2webMode) {
01415     log_err(LD_CONFIG, "This copy of Tor was not compiled to run in "
01416             "'tor2web mode'. It cannot be run with the Tor2webMode torrc "
01417             "option enabled. To enable Tor2webMode recompile with the "
01418             "--enable-tor2webmode option.");
01419     return -1;
01420   }
01421 #endif
01422 
01423   if (options->Bridges) {
01424     mark_bridge_list();
01425     for (cl = options->Bridges; cl; cl = cl->next) {
01426       if (parse_bridge_line(cl->value, 0)<0) {
01427         log_warn(LD_BUG,
01428                  "Previously validated Bridge line could not be added!");
01429         return -1;
01430       }
01431     }
01432     sweep_bridge_list();
01433   }
01434 
01435   if (running_tor && rend_config_services(options, 0)<0) {
01436     log_warn(LD_BUG,
01437        "Previously validated hidden services line could not be added!");
01438     return -1;
01439   }
01440 
01441   if (running_tor && rend_parse_service_authorization(options, 0) < 0) {
01442     log_warn(LD_BUG, "Previously validated client authorization for "
01443                      "hidden services could not be added!");
01444     return -1;
01445   }
01446 
01447   /* Load state */
01448   if (! global_state && running_tor) {
01449     if (or_state_load())
01450       return -1;
01451     rep_hist_load_mtbf_data(time(NULL));
01452   }
01453 
01454   mark_transport_list();
01455   pt_prepare_proxy_list_for_config_read();
01456   if (options->ClientTransportPlugin) {
01457     for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
01458       if (parse_client_transport_line(cl->value, 0)<0) {
01459         log_warn(LD_BUG,
01460                  "Previously validated ClientTransportPlugin line "
01461                  "could not be added!");
01462         return -1;
01463       }
01464     }
01465   }
01466 
01467   if (options->ServerTransportPlugin) {
01468     for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
01469       if (parse_server_transport_line(cl->value, 0)<0) {
01470         log_warn(LD_BUG,
01471                  "Previously validated ServerTransportPlugin line "
01472                  "could not be added!");
01473         return -1;
01474       }
01475     }
01476   }
01477   sweep_transport_list();
01478   sweep_proxy_list();
01479 
01480   /* Bail out at this point if we're not going to be a client or server:
01481    * we want to not fork, and to log stuff to stderr. */
01482   if (!running_tor)
01483     return 0;
01484 
01485   /* Finish backgrounding the process */
01486   if (options->RunAsDaemon) {
01487     /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
01488     finish_daemon(options->DataDirectory);
01489   }
01490 
01491   /* If needed, generate a new TLS DH prime according to the current torrc. */
01492   if (server_mode(options) && options->DynamicDHGroups) {
01493     char *keydir = get_datadir_fname("keys");
01494     if (check_private_dir(keydir, CPD_CREATE, options->User)) {
01495       tor_free(keydir);
01496       return -1;
01497     }
01498     tor_free(keydir);
01499 
01500     if (!old_options || !old_options->DynamicDHGroups) {
01501       char *fname = get_datadir_fname2("keys", "dynamic_dh_params");
01502       crypto_set_tls_dh_prime(fname);
01503       tor_free(fname);
01504     }
01505   } else { /* clients don't need a dynamic DH prime. */
01506     crypto_set_tls_dh_prime(NULL);
01507   }
01508 
01509   /* We want to reinit keys as needed before we do much of anything else:
01510      keys are important, and other things can depend on them. */
01511   if (transition_affects_workers ||
01512       (options->V3AuthoritativeDir && (!old_options ||
01513                                        !old_options->V3AuthoritativeDir))) {
01514     if (init_keys() < 0) {
01515       log_warn(LD_BUG,"Error initializing keys; exiting");
01516       return -1;
01517     }
01518   } else if (old_options &&
01519              options_transition_requires_fresh_tls_context(old_options,
01520                                                            options)) {
01521     if (router_initialize_tls_context() < 0) {
01522       log_warn(LD_BUG,"Error initializing TLS context.");
01523       return -1;
01524     }
01525   }
01526 
01527   /* Write our PID to the PID file. If we do not have write permissions we
01528    * will log a warning */
01529   if (options->PidFile)
01530     write_pidfile(options->PidFile);
01531 
01532   /* Register addressmap directives */
01533   config_register_addressmaps(options);
01534   parse_virtual_addr_network(options->VirtualAddrNetwork, 0, &msg);
01535 
01536   /* Update address policies. */
01537   if (policies_parse_from_options(options) < 0) {
01538     /* This should be impossible, but let's be sure. */
01539     log_warn(LD_BUG,"Error parsing already-validated policy options.");
01540     return -1;
01541   }
01542 
01543   if (init_cookie_authentication(options->CookieAuthentication) < 0) {
01544     log_warn(LD_CONFIG,"Error creating cookie authentication file.");
01545     return -1;
01546   }
01547 
01548   monitor_owning_controller_process(options->OwningControllerProcess);
01549 
01550   /* reload keys as needed for rendezvous services. */
01551   if (rend_service_load_keys()<0) {
01552     log_warn(LD_GENERAL,"Error loading rendezvous service keys");
01553     return -1;
01554   }
01555 
01556   /* Set up accounting */
01557   if (accounting_parse_options(options, 0)<0) {
01558     log_warn(LD_CONFIG,"Error in accounting options");
01559     return -1;
01560   }
01561   if (accounting_is_enabled(options))
01562     configure_accounting(time(NULL));
01563 
01564 #ifdef USE_BUFFEREVENTS
01565   /* If we're using the bufferevents implementation and our rate limits
01566    * changed, we need to tell the rate-limiting system about it. */
01567   if (!old_options ||
01568       old_options->BandwidthRate != options->BandwidthRate ||
01569       old_options->BandwidthBurst != options->BandwidthBurst ||
01570       old_options->RelayBandwidthRate != options->RelayBandwidthRate ||
01571       old_options->RelayBandwidthBurst != options->RelayBandwidthBurst)
01572     connection_bucket_init();
01573 #endif
01574 
01575   /* Change the cell EWMA settings */
01576   cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus());
01577 
01578   /* Update the BridgePassword's hashed version as needed.  We store this as a
01579    * digest so that we can do side-channel-proof comparisons on it.
01580    */
01581   if (options->BridgePassword) {
01582     char *http_authenticator;
01583     http_authenticator = alloc_http_authenticator(options->BridgePassword);
01584     if (!http_authenticator) {
01585       log_warn(LD_BUG, "Unable to allocate HTTP authenticator. Not setting "
01586                "BridgePassword.");
01587       return -1;
01588     }
01589     options->_BridgePassword_AuthDigest = tor_malloc(DIGEST256_LEN);
01590     crypto_digest256(options->_BridgePassword_AuthDigest,
01591                      http_authenticator, strlen(http_authenticator),
01592                      DIGEST_SHA256);
01593     tor_free(http_authenticator);
01594   }
01595 
01596   /* Check for transitions that need action. */
01597   if (old_options) {
01598     int revise_trackexithosts = 0;
01599     int revise_automap_entries = 0;
01600     if ((options->UseEntryGuards && !old_options->UseEntryGuards) ||
01601         options->UseBridges != old_options->UseBridges ||
01602         (options->UseBridges &&
01603          !config_lines_eq(options->Bridges, old_options->Bridges)) ||
01604         !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes) ||
01605         !routerset_equal(old_options->ExcludeExitNodes,
01606                          options->ExcludeExitNodes) ||
01607         !routerset_equal(old_options->EntryNodes, options->EntryNodes) ||
01608         !routerset_equal(old_options->ExitNodes, options->ExitNodes) ||
01609         options->StrictNodes != old_options->StrictNodes) {
01610       log_info(LD_CIRC,
01611                "Changed to using entry guards or bridges, or changed "
01612                "preferred or excluded node lists. "
01613                "Abandoning previous circuits.");
01614       circuit_mark_all_unused_circs();
01615       circuit_expire_all_dirty_circs();
01616       revise_trackexithosts = 1;
01617     }
01618 
01619     if (!smartlist_strings_eq(old_options->TrackHostExits,
01620                               options->TrackHostExits))
01621       revise_trackexithosts = 1;
01622 
01623     if (revise_trackexithosts)
01624       addressmap_clear_excluded_trackexithosts(options);
01625 
01626     if (!options->AutomapHostsOnResolve) {
01627       if (old_options->AutomapHostsOnResolve)
01628         revise_automap_entries = 1;
01629     } else {
01630       if (!smartlist_strings_eq(old_options->AutomapHostsSuffixes,
01631                                 options->AutomapHostsSuffixes))
01632         revise_automap_entries = 1;
01633       else if (!opt_streq(old_options->VirtualAddrNetwork,
01634                           options->VirtualAddrNetwork))
01635         revise_automap_entries = 1;
01636     }
01637 
01638     if (revise_automap_entries)
01639       addressmap_clear_invalid_automaps(options);
01640 
01641 /* How long should we delay counting bridge stats after becoming a bridge?
01642  * We use this so we don't count people who used our bridge thinking it is
01643  * a relay. If you change this, don't forget to change the log message
01644  * below. It's 4 hours (the time it takes to stop being used by clients)
01645  * plus some extra time for clock skew. */
01646 #define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60)
01647 
01648     if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) {
01649       int was_relay = 0;
01650       if (options->BridgeRelay) {
01651         time_t int_start = time(NULL);
01652         if (config_lines_eq(old_options->ORPort, options->ORPort)) {
01653           int_start += RELAY_BRIDGE_STATS_DELAY;
01654           was_relay = 1;
01655         }
01656         geoip_bridge_stats_init(int_start);
01657         log_info(LD_CONFIG, "We are acting as a bridge now.  Starting new "
01658                  "GeoIP stats interval%s.", was_relay ? " in 6 "
01659                  "hours from now" : "");
01660       } else {
01661         geoip_bridge_stats_term();
01662         log_info(LD_GENERAL, "We are no longer acting as a bridge.  "
01663                  "Forgetting GeoIP stats.");
01664       }
01665     }
01666 
01667     if (transition_affects_workers) {
01668       log_info(LD_GENERAL,
01669                "Worker-related options changed. Rotating workers.");
01670 
01671       if (server_mode(options) && !server_mode(old_options)) {
01672         ip_address_changed(0);
01673         if (can_complete_circuit || !any_predicted_circuits(time(NULL)))
01674           inform_testing_reachability();
01675       }
01676       cpuworkers_rotate();
01677       if (dns_reset())
01678         return -1;
01679     } else {
01680       if (dns_reset())
01681         return -1;
01682     }
01683 
01684     if (options->PerConnBWRate != old_options->PerConnBWRate ||
01685         options->PerConnBWBurst != old_options->PerConnBWBurst)
01686       connection_or_update_token_buckets(get_connection_array(), options);
01687   }
01688 
01689   /* Maybe load geoip file */
01690   if (options->GeoIPFile &&
01691       ((!old_options || !opt_streq(old_options->GeoIPFile, options->GeoIPFile))
01692        || !geoip_is_loaded())) {
01693     /* XXXX Don't use this "<default>" junk; make our filename options
01694      * understand prefixes somehow. -NM */
01695     /* XXXX024 Reload GeoIPFile on SIGHUP. -NM */
01696     char *actual_fname = tor_strdup(options->GeoIPFile);
01697 #ifdef _WIN32
01698     if (!strcmp(actual_fname, "<default>")) {
01699       const char *conf_root = get_windows_conf_root();
01700       tor_free(actual_fname);
01701       tor_asprintf(&actual_fname, "%s\\geoip", conf_root);
01702     }
01703 #endif
01704     geoip_load_file(actual_fname, options);
01705     tor_free(actual_fname);
01706   }
01707 
01708   if (options->CellStatistics || options->DirReqStatistics ||
01709       options->EntryStatistics || options->ExitPortStatistics ||
01710       options->ConnDirectionStatistics ||
01711       options->BridgeAuthoritativeDir) {
01712     time_t now = time(NULL);
01713     int print_notice = 0;
01714 
01715     /* If we aren't acting as a server, we can't collect stats anyway. */
01716     if (!server_mode(options)) {
01717       options->CellStatistics = 0;
01718       options->DirReqStatistics = 0;
01719       options->EntryStatistics = 0;
01720       options->ExitPortStatistics = 0;
01721     }
01722 
01723     if ((!old_options || !old_options->CellStatistics) &&
01724         options->CellStatistics) {
01725       rep_hist_buffer_stats_init(now);
01726       print_notice = 1;
01727     }
01728     if ((!old_options || !old_options->DirReqStatistics) &&
01729         options->DirReqStatistics) {
01730       if (geoip_is_loaded()) {
01731         geoip_dirreq_stats_init(now);
01732         print_notice = 1;
01733       } else {
01734         options->DirReqStatistics = 0;
01735         /* Don't warn Tor clients, they don't use statistics */
01736         if (options->ORPort)
01737           log_notice(LD_CONFIG, "Configured to measure directory request "
01738                                 "statistics, but no GeoIP database found. "
01739                                 "Please specify a GeoIP database using the "
01740                                 "GeoIPFile option.");
01741       }
01742     }
01743     if ((!old_options || !old_options->EntryStatistics) &&
01744         options->EntryStatistics && !should_record_bridge_info(options)) {
01745       if (geoip_is_loaded()) {
01746         geoip_entry_stats_init(now);
01747         print_notice = 1;
01748       } else {
01749         options->EntryStatistics = 0;
01750         log_notice(LD_CONFIG, "Configured to measure entry node "
01751                               "statistics, but no GeoIP database found. "
01752                               "Please specify a GeoIP database using the "
01753                               "GeoIPFile option.");
01754       }
01755     }
01756     if ((!old_options || !old_options->ExitPortStatistics) &&
01757         options->ExitPortStatistics) {
01758       rep_hist_exit_stats_init(now);
01759       print_notice = 1;
01760     }
01761     if ((!old_options || !old_options->ConnDirectionStatistics) &&
01762         options->ConnDirectionStatistics) {
01763       rep_hist_conn_stats_init(now);
01764     }
01765     if ((!old_options || !old_options->BridgeAuthoritativeDir) &&
01766         options->BridgeAuthoritativeDir) {
01767       rep_hist_desc_stats_init(now);
01768       print_notice = 1;
01769     }
01770     if (print_notice)
01771       log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
01772                  "the *-stats files that will first be written to the "
01773                  "data directory in 24 hours from now.");
01774   }
01775 
01776   if (old_options && old_options->CellStatistics &&
01777       !options->CellStatistics)
01778     rep_hist_buffer_stats_term();
01779   if (old_options && old_options->DirReqStatistics &&
01780       !options->DirReqStatistics)
01781     geoip_dirreq_stats_term();
01782   if (old_options && old_options->EntryStatistics &&
01783       !options->EntryStatistics)
01784     geoip_entry_stats_term();
01785   if (old_options && old_options->ExitPortStatistics &&
01786       !options->ExitPortStatistics)
01787     rep_hist_exit_stats_term();
01788   if (old_options && old_options->ConnDirectionStatistics &&
01789       !options->ConnDirectionStatistics)
01790     rep_hist_conn_stats_term();
01791   if (old_options && old_options->BridgeAuthoritativeDir &&
01792       !options->BridgeAuthoritativeDir)
01793     rep_hist_desc_stats_term();
01794 
01795   /* Check if we need to parse and add the EntryNodes config option. */
01796   if (options->EntryNodes &&
01797       (!old_options ||
01798        !routerset_equal(old_options->EntryNodes,options->EntryNodes) ||
01799        !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes)))
01800     entry_nodes_should_be_added();
01801 
01802   /* Since our options changed, we might need to regenerate and upload our
01803    * server descriptor.
01804    */
01805   if (!old_options ||
01806       options_transition_affects_descriptor(old_options, options))
01807     mark_my_descriptor_dirty("config change");
01808 
01809   /* We may need to reschedule some directory stuff if our status changed. */
01810   if (old_options) {
01811     if (authdir_mode_v3(options) && !authdir_mode_v3(old_options))
01812       dirvote_recalculate_timing(options, time(NULL));
01813     if (!bool_eq(directory_fetches_dir_info_early(options),
01814                  directory_fetches_dir_info_early(old_options)) ||
01815         !bool_eq(directory_fetches_dir_info_later(options),
01816                  directory_fetches_dir_info_later(old_options))) {
01817       /* Make sure update_router_have_min_dir_info gets called. */
01818       router_dir_info_changed();
01819       /* We might need to download a new consensus status later or sooner than
01820        * we had expected. */
01821       update_consensus_networkstatus_fetch_time(time(NULL));
01822     }
01823   }
01824 
01825   /* Load the webpage we're going to serve every time someone asks for '/' on
01826      our DirPort. */
01827   tor_free(global_dirfrontpagecontents);
01828   if (options->DirPortFrontPage) {
01829     global_dirfrontpagecontents =
01830       read_file_to_str(options->DirPortFrontPage, 0, NULL);
01831     if (!global_dirfrontpagecontents) {
01832       log_warn(LD_CONFIG,
01833                "DirPortFrontPage file '%s' not found. Continuing anyway.",
01834                options->DirPortFrontPage);
01835     }
01836   }
01837 
01838   return 0;
01839 }
01840 
01841 /*
01842  * Functions to parse config options
01843  */
01844 
01850 static const char *
01851 expand_abbrev(const config_format_t *fmt, const char *option, int command_line,
01852               int warn_obsolete)
01853 {
01854   int i;
01855   if (! fmt->abbrevs)
01856     return option;
01857   for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
01858     /* Abbreviations are case insensitive. */
01859     if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
01860         (command_line || !fmt->abbrevs[i].commandline_only)) {
01861       if (warn_obsolete && fmt->abbrevs[i].warn) {
01862         log_warn(LD_CONFIG,
01863                  "The configuration option '%s' is deprecated; "
01864                  "use '%s' instead.",
01865                  fmt->abbrevs[i].abbreviated,
01866                  fmt->abbrevs[i].full);
01867       }
01868       /* Keep going through the list in case we want to rewrite it more.
01869        * (We could imagine recursing here, but I don't want to get the
01870        * user into an infinite loop if we craft our list wrong.) */
01871       option = fmt->abbrevs[i].full;
01872     }
01873   }
01874   return option;
01875 }
01876 
01880 static int
01881 config_get_commandlines(int argc, char **argv, config_line_t **result)
01882 {
01883   config_line_t *front = NULL;
01884   config_line_t **new = &front;
01885   char *s;
01886   int i = 1;
01887 
01888   while (i < argc) {
01889     unsigned command = CONFIG_LINE_NORMAL;
01890     int want_arg = 1;
01891 
01892     if (!strcmp(argv[i],"-f") ||
01893         !strcmp(argv[i],"--defaults-torrc") ||
01894         !strcmp(argv[i],"--hash-password")) {
01895       i += 2; /* command-line option with argument. ignore them. */
01896       continue;
01897     } else if (!strcmp(argv[i],"--list-fingerprint") ||
01898                !strcmp(argv[i],"--verify-config") ||
01899                !strcmp(argv[i],"--ignore-missing-torrc") ||
01900                !strcmp(argv[i],"--quiet") ||
01901                !strcmp(argv[i],"--hush")) {
01902       i += 1; /* command-line option. ignore it. */
01903       continue;
01904     } else if (!strcmp(argv[i],"--nt-service") ||
01905                !strcmp(argv[i],"-nt-service")) {
01906       i += 1;
01907       continue;
01908     }
01909 
01910     *new = tor_malloc_zero(sizeof(config_line_t));
01911     s = argv[i];
01912 
01913     /* Each keyword may be prefixed with one or two dashes. */
01914     if (*s == '-')
01915       s++;
01916     if (*s == '-')
01917       s++;
01918     /* Figure out the command, if any. */
01919     if (*s == '+') {
01920       s++;
01921       command = CONFIG_LINE_APPEND;
01922     } else if (*s == '/') {
01923       s++;
01924       command = CONFIG_LINE_CLEAR;
01925       /* A 'clear' command has no argument. */
01926       want_arg = 0;
01927     }
01928 
01929     if (want_arg && i == argc-1) {
01930       log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
01931                argv[i]);
01932       config_free_lines(front);
01933       return -1;
01934     }
01935 
01936     (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1));
01937     (*new)->value = want_arg ? tor_strdup(argv[i+1]) : tor_strdup("");
01938     (*new)->command = command;
01939     (*new)->next = NULL;
01940     log(LOG_DEBUG, LD_CONFIG, "command line: parsed keyword '%s', value '%s'",
01941         (*new)->key, (*new)->value);
01942 
01943     new = &((*new)->next);
01944     i += want_arg ? 2 : 1;
01945   }
01946   *result = front;
01947   return 0;
01948 }
01949 
01952 static void
01953 config_line_append(config_line_t **lst,
01954                    const char *key,
01955                    const char *val)
01956 {
01957   config_line_t *newline;
01958 
01959   newline = tor_malloc_zero(sizeof(config_line_t));
01960   newline->key = tor_strdup(key);
01961   newline->value = tor_strdup(val);
01962   newline->next = NULL;
01963   while (*lst)
01964     lst = &((*lst)->next);
01965 
01966   (*lst) = newline;
01967 }
01968 
01976 int
01977 config_get_lines(const char *string, config_line_t **result, int extended)
01978 {
01979   config_line_t *list = NULL, **next;
01980   char *k, *v;
01981 
01982   next = &list;
01983   do {
01984     k = v = NULL;
01985     string = parse_config_line_from_str(string, &k, &v);
01986     if (!string) {
01987       config_free_lines(list);
01988       tor_free(k);
01989       tor_free(v);
01990       return -1;
01991     }
01992     if (k && v) {
01993       unsigned command = CONFIG_LINE_NORMAL;
01994       if (extended) {
01995         if (k[0] == '+') {
01996           char *k_new = tor_strdup(k+1);
01997           tor_free(k);
01998           k = k_new;
01999           command = CONFIG_LINE_APPEND;
02000         } else if (k[0] == '/') {
02001           char *k_new = tor_strdup(k+1);
02002           tor_free(k);
02003           k = k_new;
02004           tor_free(v);
02005           v = tor_strdup("");
02006           command = CONFIG_LINE_CLEAR;
02007         }
02008       }
02009       /* This list can get long, so we keep a pointer to the end of it
02010        * rather than using config_line_append over and over and getting
02011        * n^2 performance. */
02012       *next = tor_malloc_zero(sizeof(config_line_t));
02013       (*next)->key = k;
02014       (*next)->value = v;
02015       (*next)->next = NULL;
02016       (*next)->command = command;
02017       next = &((*next)->next);
02018     } else {
02019       tor_free(k);
02020       tor_free(v);
02021     }
02022   } while (*string);
02023 
02024   *result = list;
02025   return 0;
02026 }
02027 
02031 void
02032 config_free_lines(config_line_t *front)
02033 {
02034   config_line_t *tmp;
02035 
02036   while (front) {
02037     tmp = front;
02038     front = tmp->next;
02039 
02040     tor_free(tmp->key);
02041     tor_free(tmp->value);
02042     tor_free(tmp);
02043   }
02044 }
02045 
02047 static config_var_t *
02048 config_find_option_mutable(config_format_t *fmt, const char *key)
02049 {
02050   int i;
02051   size_t keylen = strlen(key);
02052   if (!keylen)
02053     return NULL; /* if they say "--" on the command line, it's not an option */
02054   /* First, check for an exact (case-insensitive) match */
02055   for (i=0; fmt->vars[i].name; ++i) {
02056     if (!strcasecmp(key, fmt->vars[i].name)) {
02057       return &fmt->vars[i];
02058     }
02059   }
02060   /* If none, check for an abbreviated match */
02061   for (i=0; fmt->vars[i].name; ++i) {
02062     if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
02063       log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. "
02064                "Please use '%s' instead",
02065                key, fmt->vars[i].name);
02066       return &fmt->vars[i];
02067     }
02068   }
02069   /* Okay, unrecognized option */
02070   return NULL;
02071 }
02072 
02078 static const config_var_t *
02079 config_find_option(const config_format_t *fmt, const char *key)
02080 {
02081   return config_find_option_mutable((config_format_t*)fmt, key);
02082 }
02083 
02085 static int
02086 config_count_options(const config_format_t *fmt)
02087 {
02088   int i;
02089   for (i=0; fmt->vars[i].name; ++i)
02090     ;
02091   return i;
02092 }
02093 
02094 /*
02095  * Functions to assign config options.
02096  */
02097 
02103 static int
02104 config_assign_value(const config_format_t *fmt, or_options_t *options,
02105                     config_line_t *c, char **msg)
02106 {
02107   int i, ok;
02108   const config_var_t *var;
02109   void *lvalue;
02110 
02111   CHECK(fmt, options);
02112 
02113   var = config_find_option(fmt, c->key);
02114   tor_assert(var);
02115 
02116   lvalue = STRUCT_VAR_P(options, var->var_offset);
02117 
02118   switch (var->type) {
02119 
02120   case CONFIG_TYPE_PORT:
02121     if (!strcasecmp(c->value, "auto")) {
02122       *(int *)lvalue = CFG_AUTO_PORT;
02123       break;
02124     }
02125     /* fall through */
02126   case CONFIG_TYPE_INT:
02127   case CONFIG_TYPE_UINT:
02128     i = (int)tor_parse_long(c->value, 10,
02129                             var->type==CONFIG_TYPE_INT ? INT_MIN : 0,
02130                             var->type==CONFIG_TYPE_PORT ? 65535 : INT_MAX,
02131                             &ok, NULL);
02132     if (!ok) {
02133       tor_asprintf(msg,
02134           "Int keyword '%s %s' is malformed or out of bounds.",
02135           c->key, c->value);
02136       return -1;
02137     }
02138     *(int *)lvalue = i;
02139     break;
02140 
02141   case CONFIG_TYPE_INTERVAL: {
02142     i = config_parse_interval(c->value, &ok);
02143     if (!ok) {
02144       tor_asprintf(msg,
02145           "Interval '%s %s' is malformed or out of bounds.",
02146           c->key, c->value);
02147       return -1;
02148     }
02149     *(int *)lvalue = i;
02150     break;
02151   }
02152 
02153   case CONFIG_TYPE_MSEC_INTERVAL: {
02154     i = config_parse_msec_interval(c->value, &ok);
02155     if (!ok) {
02156       tor_asprintf(msg,
02157           "Msec interval '%s %s' is malformed or out of bounds.",
02158           c->key, c->value);
02159       return -1;
02160     }
02161     *(int *)lvalue = i;
02162     break;
02163   }
02164 
02165   case CONFIG_TYPE_MEMUNIT: {
02166     uint64_t u64 = config_parse_memunit(c->value, &ok);
02167     if (!ok) {
02168       tor_asprintf(msg,
02169           "Value '%s %s' is malformed or out of bounds.",
02170           c->key, c->value);
02171       return -1;
02172     }
02173     *(uint64_t *)lvalue = u64;
02174     break;
02175   }
02176 
02177   case CONFIG_TYPE_BOOL:
02178     i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
02179     if (!ok) {
02180       tor_asprintf(msg,
02181           "Boolean '%s %s' expects 0 or 1.",
02182           c->key, c->value);
02183       return -1;
02184     }
02185     *(int *)lvalue = i;
02186     break;
02187 
02188   case CONFIG_TYPE_AUTOBOOL:
02189     if (!strcmp(c->value, "auto"))
02190       *(int *)lvalue = -1;
02191     else if (!strcmp(c->value, "0"))
02192       *(int *)lvalue = 0;
02193     else if (!strcmp(c->value, "1"))
02194       *(int *)lvalue = 1;
02195     else {
02196       tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.",
02197                    c->key, c->value);
02198       return -1;
02199     }
02200     break;
02201 
02202   case CONFIG_TYPE_STRING:
02203   case CONFIG_TYPE_FILENAME:
02204     tor_free(*(char **)lvalue);
02205     *(char **)lvalue = tor_strdup(c->value);
02206     break;
02207 
02208   case CONFIG_TYPE_DOUBLE:
02209     *(double *)lvalue = atof(c->value);
02210     break;
02211 
02212   case CONFIG_TYPE_ISOTIME:
02213     if (parse_iso_time(c->value, (time_t *)lvalue)) {
02214       tor_asprintf(msg,
02215           "Invalid time '%s' for keyword '%s'", c->value, c->key);
02216       return -1;
02217     }
02218     break;
02219 
02220   case CONFIG_TYPE_ROUTERSET:
02221     if (*(routerset_t**)lvalue) {
02222       routerset_free(*(routerset_t**)lvalue);
02223     }
02224     *(routerset_t**)lvalue = routerset_new();
02225     if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) {
02226       tor_asprintf(msg, "Invalid exit list '%s' for option '%s'",
02227                    c->value, c->key);
02228       return -1;
02229     }
02230     break;
02231 
02232   case CONFIG_TYPE_CSV:
02233     if (*(smartlist_t**)lvalue) {
02234       SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
02235       smartlist_clear(*(smartlist_t**)lvalue);
02236     } else {
02237       *(smartlist_t**)lvalue = smartlist_new();
02238     }
02239 
02240     smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
02241                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
02242     break;
02243 
02244   case CONFIG_TYPE_LINELIST:
02245   case CONFIG_TYPE_LINELIST_S:
02246     {
02247       config_line_t *lastval = *(config_line_t**)lvalue;
02248       if (lastval && lastval->fragile) {
02249         if (c->command != CONFIG_LINE_APPEND) {
02250           config_free_lines(lastval);
02251           *(config_line_t**)lvalue = NULL;
02252         } else {
02253           lastval->fragile = 0;
02254         }
02255       }
02256 
02257       config_line_append((config_line_t**)lvalue, c->key, c->value);
02258     }
02259     break;
02260   case CONFIG_TYPE_OBSOLETE:
02261     log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key);
02262     break;
02263   case CONFIG_TYPE_LINELIST_V:
02264     tor_asprintf(msg,
02265         "You may not provide a value for virtual option '%s'", c->key);
02266     return -1;
02267   default:
02268     tor_assert(0);
02269     break;
02270   }
02271   return 0;
02272 }
02273 
02276 static void
02277 config_mark_lists_fragile(const config_format_t *fmt, or_options_t *options)
02278 {
02279   int i;
02280   tor_assert(fmt);
02281   tor_assert(options);
02282 
02283   for (i = 0; fmt->vars[i].name; ++i) {
02284     const config_var_t *var = &fmt->vars[i];
02285     config_line_t *list;
02286     if (var->type != CONFIG_TYPE_LINELIST &&
02287         var->type != CONFIG_TYPE_LINELIST_V)
02288       continue;
02289 
02290     list = *(config_line_t **)STRUCT_VAR_P(options, var->var_offset);
02291     if (list)
02292       list->fragile = 1;
02293   }
02294 }
02295 
02305 static int
02306 config_assign_line(const config_format_t *fmt, or_options_t *options,
02307                    config_line_t *c, int use_defaults,
02308                    int clear_first, bitarray_t *options_seen, char **msg)
02309 {
02310   const config_var_t *var;
02311 
02312   CHECK(fmt, options);
02313 
02314   var = config_find_option(fmt, c->key);
02315   if (!var) {
02316     if (fmt->extra) {
02317       void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset);
02318       log_info(LD_CONFIG,
02319                "Found unrecognized option '%s'; saving it.", c->key);
02320       config_line_append((config_line_t**)lvalue, c->key, c->value);
02321       return 0;
02322     } else {
02323       tor_asprintf(msg,
02324                 "Unknown option '%s'.  Failing.", c->key);
02325       return -1;
02326     }
02327   }
02328 
02329   /* Put keyword into canonical case. */
02330   if (strcmp(var->name, c->key)) {
02331     tor_free(c->key);
02332     c->key = tor_strdup(var->name);
02333   }
02334 
02335   if (!strlen(c->value)) {
02336     /* reset or clear it, then return */
02337     if (!clear_first) {
02338       if ((var->type == CONFIG_TYPE_LINELIST ||
02339            var->type == CONFIG_TYPE_LINELIST_S) &&
02340           c->command != CONFIG_LINE_CLEAR) {
02341         /* We got an empty linelist from the torrc or command line.
02342            As a special case, call this an error. Warn and ignore. */
02343         log_warn(LD_CONFIG,
02344                  "Linelist option '%s' has no value. Skipping.", c->key);
02345       } else { /* not already cleared */
02346         option_reset(fmt, options, var, use_defaults);
02347       }
02348     }
02349     return 0;
02350   } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) {
02351     option_reset(fmt, options, var, use_defaults);
02352   }
02353 
02354   if (options_seen && (var->type != CONFIG_TYPE_LINELIST &&
02355                        var->type != CONFIG_TYPE_LINELIST_S)) {
02356     /* We're tracking which options we've seen, and this option is not
02357      * supposed to occur more than once. */
02358     int var_index = (int)(var - fmt->vars);
02359     if (bitarray_is_set(options_seen, var_index)) {
02360       log_warn(LD_CONFIG, "Option '%s' used more than once; all but the last "
02361                "value will be ignored.", var->name);
02362     }
02363     bitarray_set(options_seen, var_index);
02364   }
02365 
02366   if (config_assign_value(fmt, options, c, msg) < 0)
02367     return -2;
02368   return 0;
02369 }
02370 
02373 static void
02374 config_reset_line(const config_format_t *fmt, or_options_t *options,
02375                   const char *key, int use_defaults)
02376 {
02377   const config_var_t *var;
02378 
02379   CHECK(fmt, options);
02380 
02381   var = config_find_option(fmt, key);
02382   if (!var)
02383     return; /* give error on next pass. */
02384 
02385   option_reset(fmt, options, var, use_defaults);
02386 }
02387 
02389 int
02390 option_is_recognized(const char *key)
02391 {
02392   const config_var_t *var = config_find_option(&options_format, key);
02393   return (var != NULL);
02394 }
02395 
02398 const char *
02399 option_get_canonical_name(const char *key)
02400 {
02401   const config_var_t *var = config_find_option(&options_format, key);
02402   return var ? var->name : NULL;
02403 }
02404 
02407 config_line_t *
02408 option_get_assignment(const or_options_t *options, const char *key)
02409 {
02410   return get_assigned_option(&options_format, options, key, 1);
02411 }
02412 
02415 static int
02416 config_value_needs_escape(const char *value)
02417 {
02418   if (*value == '\"')
02419     return 1;
02420   while (*value) {
02421     switch (*value)
02422     {
02423     case '\r':
02424     case '\n':
02425     case '#':
02426       /* Note: quotes and backspaces need special handling when we are using
02427        * quotes, not otherwise, so they don't trigger escaping on their
02428        * own. */
02429       return 1;
02430     default:
02431       if (!TOR_ISPRINT(*value))
02432         return 1;
02433     }
02434     ++value;
02435   }
02436   return 0;
02437 }
02438 
02440 static config_line_t *
02441 config_lines_dup(const config_line_t *inp)
02442 {
02443   config_line_t *result = NULL;
02444   config_line_t **next_out = &result;
02445   while (inp) {
02446     *next_out = tor_malloc_zero(sizeof(config_line_t));
02447     (*next_out)->key = tor_strdup(inp->key);
02448     (*next_out)->value = tor_strdup(inp->value);
02449     inp = inp->next;
02450     next_out = &((*next_out)->next);
02451   }
02452   (*next_out) = NULL;
02453   return result;
02454 }
02455 
02460 static config_line_t *
02461 get_assigned_option(const config_format_t *fmt, const void *options,
02462                     const char *key, int escape_val)
02463 {
02464   const config_var_t *var;
02465   const void *value;
02466   config_line_t *result;
02467   tor_assert(options && key);
02468 
02469   CHECK(fmt, options);
02470 
02471   var = config_find_option(fmt, key);
02472   if (!var) {
02473     log_warn(LD_CONFIG, "Unknown option '%s'.  Failing.", key);
02474     return NULL;
02475   }
02476   value = STRUCT_VAR_P(options, var->var_offset);
02477 
02478   result = tor_malloc_zero(sizeof(config_line_t));
02479   result->key = tor_strdup(var->name);
02480   switch (var->type)
02481     {
02482     case CONFIG_TYPE_STRING:
02483     case CONFIG_TYPE_FILENAME:
02484       if (*(char**)value) {
02485         result->value = tor_strdup(*(char**)value);
02486       } else {
02487         tor_free(result->key);
02488         tor_free(result);
02489         return NULL;
02490       }
02491       break;
02492     case CONFIG_TYPE_ISOTIME:
02493       if (*(time_t*)value) {
02494         result->value = tor_malloc(ISO_TIME_LEN+1);
02495         format_iso_time(result->value, *(time_t*)value);
02496       } else {
02497         tor_free(result->key);
02498         tor_free(result);
02499       }
02500       escape_val = 0; /* Can't need escape. */
02501       break;
02502     case CONFIG_TYPE_PORT:
02503       if (*(int*)value == CFG_AUTO_PORT) {
02504         result->value = tor_strdup("auto");
02505         escape_val = 0;
02506         break;
02507       }
02508       /* fall through */
02509     case CONFIG_TYPE_INTERVAL:
02510     case CONFIG_TYPE_MSEC_INTERVAL:
02511     case CONFIG_TYPE_UINT:
02512     case CONFIG_TYPE_INT:
02513       /* This means every or_options_t uint or bool element
02514        * needs to be an int. Not, say, a uint16_t or char. */
02515       tor_asprintf(&result->value, "%d", *(int*)value);
02516       escape_val = 0; /* Can't need escape. */
02517       break;
02518     case CONFIG_TYPE_MEMUNIT:
02519       tor_asprintf(&result->value, U64_FORMAT,
02520                    U64_PRINTF_ARG(*(uint64_t*)value));
02521       escape_val = 0; /* Can't need escape. */
02522       break;
02523     case CONFIG_TYPE_DOUBLE:
02524       tor_asprintf(&result->value, "%f", *(double*)value);
02525       escape_val = 0; /* Can't need escape. */
02526       break;
02527 
02528     case CONFIG_TYPE_AUTOBOOL:
02529       if (*(int*)value == -1) {
02530         result->value = tor_strdup("auto");
02531         escape_val = 0;
02532         break;
02533       }
02534       /* fall through */
02535     case CONFIG_TYPE_BOOL:
02536       result->value = tor_strdup(*(int*)value ? "1" : "0");
02537       escape_val = 0; /* Can't need escape. */
02538       break;
02539     case CONFIG_TYPE_ROUTERSET:
02540       result->value = routerset_to_string(*(routerset_t**)value);
02541       break;
02542     case CONFIG_TYPE_CSV:
02543       if (*(smartlist_t**)value)
02544         result->value =
02545           smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
02546       else
02547         result->value = tor_strdup("");
02548       break;
02549     case CONFIG_TYPE_OBSOLETE:
02550       log_fn(LOG_PROTOCOL_WARN, LD_CONFIG,
02551              "You asked me for the value of an obsolete config option '%s'.",
02552              key);
02553       tor_free(result->key);
02554       tor_free(result);
02555       return NULL;
02556     case CONFIG_TYPE_LINELIST_S:
02557       log_warn(LD_CONFIG,
02558                "Can't return context-sensitive '%s' on its own", key);
02559       tor_free(result->key);
02560       tor_free(result);
02561       return NULL;
02562     case CONFIG_TYPE_LINELIST:
02563     case CONFIG_TYPE_LINELIST_V:
02564       tor_free(result->key);
02565       tor_free(result);
02566       result = config_lines_dup(*(const config_line_t**)value);
02567       break;
02568     default:
02569       tor_free(result->key);
02570       tor_free(result);
02571       log_warn(LD_BUG,"Unknown type %d for known key '%s'",
02572                var->type, key);
02573       return NULL;
02574     }
02575 
02576   if (escape_val) {
02577     config_line_t *line;
02578     for (line = result; line; line = line->next) {
02579       if (line->value && config_value_needs_escape(line->value)) {
02580         char *newval = esc_for_log(line->value);
02581         tor_free(line->value);
02582         line->value = newval;
02583       }
02584     }
02585   }
02586 
02587   return result;
02588 }
02589 
02619 /*
02620 There are three call cases for config_assign() currently.
02621 
02622 Case one: Torrc entry
02623 options_init_from_torrc() calls config_assign(0, 0)
02624   calls config_assign_line(0, 0).
02625     if value is empty, calls option_reset(0) and returns.
02626     calls config_assign_value(), appends.
02627 
02628 Case two: setconf
02629 options_trial_assign() calls config_assign(0, 1)
02630   calls config_reset_line(0)
02631     calls option_reset(0)
02632       calls option_clear().
02633   calls config_assign_line(0, 1).
02634     if value is empty, returns.
02635     calls config_assign_value(), appends.
02636 
02637 Case three: resetconf
02638 options_trial_assign() calls config_assign(1, 1)
02639   calls config_reset_line(1)
02640     calls option_reset(1)
02641       calls option_clear().
02642       calls config_assign_value(default)
02643   calls config_assign_line(1, 1).
02644     returns.
02645 */
02646 static int
02647 config_assign(const config_format_t *fmt, void *options, config_line_t *list,
02648               int use_defaults, int clear_first, char **msg)
02649 {
02650   config_line_t *p;
02651   bitarray_t *options_seen;
02652   const int n_options = config_count_options(fmt);
02653 
02654   CHECK(fmt, options);
02655 
02656   /* pass 1: normalize keys */
02657   for (p = list; p; p = p->next) {
02658     const char *full = expand_abbrev(fmt, p->key, 0, 1);
02659     if (strcmp(full,p->key)) {
02660       tor_free(p->key);
02661       p->key = tor_strdup(full);
02662     }
02663   }
02664 
02665   /* pass 2: if we're reading from a resetting source, clear all
02666    * mentioned config options, and maybe set to their defaults. */
02667   if (clear_first) {
02668     for (p = list; p; p = p->next)
02669       config_reset_line(fmt, options, p->key, use_defaults);
02670   }
02671 
02672   options_seen = bitarray_init_zero(n_options);
02673   /* pass 3: assign. */
02674   while (list) {
02675     int r;
02676     if ((r=config_assign_line(fmt, options, list, use_defaults,
02677                               clear_first, options_seen, msg))) {
02678       bitarray_free(options_seen);
02679       return r;
02680     }
02681     list = list->next;
02682   }
02683   bitarray_free(options_seen);
02684 
02688   config_mark_lists_fragile(fmt, options);
02689 
02690   return 0;
02691 }
02692 
02702 setopt_err_t
02703 options_trial_assign(config_line_t *list, int use_defaults,
02704                      int clear_first, char **msg)
02705 {
02706   int r;
02707   or_options_t *trial_options = options_dup(&options_format, get_options());
02708 
02709   if ((r=config_assign(&options_format, trial_options,
02710                        list, use_defaults, clear_first, msg)) < 0) {
02711     config_free(&options_format, trial_options);
02712     return r;
02713   }
02714 
02715   if (options_validate(get_options_mutable(), trial_options, 1, msg) < 0) {
02716     config_free(&options_format, trial_options);
02717     return SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
02718   }
02719 
02720   if (options_transition_allowed(get_options(), trial_options, msg) < 0) {
02721     config_free(&options_format, trial_options);
02722     return SETOPT_ERR_TRANSITION;
02723   }
02724 
02725   if (set_options(trial_options, msg)<0) {
02726     config_free(&options_format, trial_options);
02727     return SETOPT_ERR_SETTING;
02728   }
02729 
02730   /* we liked it. put it in place. */
02731   return SETOPT_OK;
02732 }
02733 
02736 static void
02737 option_clear(const config_format_t *fmt, or_options_t *options,
02738              const config_var_t *var)
02739 {
02740   void *lvalue = STRUCT_VAR_P(options, var->var_offset);
02741   (void)fmt; /* unused */
02742   switch (var->type) {
02743     case CONFIG_TYPE_STRING:
02744     case CONFIG_TYPE_FILENAME:
02745       tor_free(*(char**)lvalue);
02746       break;
02747     case CONFIG_TYPE_DOUBLE:
02748       *(double*)lvalue = 0.0;
02749       break;
02750     case CONFIG_TYPE_ISOTIME:
02751       *(time_t*)lvalue = 0;
02752       break;
02753     case CONFIG_TYPE_INTERVAL:
02754     case CONFIG_TYPE_MSEC_INTERVAL:
02755     case CONFIG_TYPE_UINT:
02756     case CONFIG_TYPE_INT:
02757     case CONFIG_TYPE_PORT:
02758     case CONFIG_TYPE_BOOL:
02759       *(int*)lvalue = 0;
02760       break;
02761     case CONFIG_TYPE_AUTOBOOL:
02762       *(int*)lvalue = -1;
02763       break;
02764     case CONFIG_TYPE_MEMUNIT:
02765       *(uint64_t*)lvalue = 0;
02766       break;
02767     case CONFIG_TYPE_ROUTERSET:
02768       if (*(routerset_t**)lvalue) {
02769         routerset_free(*(routerset_t**)lvalue);
02770         *(routerset_t**)lvalue = NULL;
02771       }
02772       break;
02773     case CONFIG_TYPE_CSV:
02774       if (*(smartlist_t**)lvalue) {
02775         SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
02776         smartlist_free(*(smartlist_t **)lvalue);
02777         *(smartlist_t **)lvalue = NULL;
02778       }
02779       break;
02780     case CONFIG_TYPE_LINELIST:
02781     case CONFIG_TYPE_LINELIST_S:
02782       config_free_lines(*(config_line_t **)lvalue);
02783       *(config_line_t **)lvalue = NULL;
02784       break;
02785     case CONFIG_TYPE_LINELIST_V:
02786       /* handled by linelist_s. */
02787       break;
02788     case CONFIG_TYPE_OBSOLETE:
02789       break;
02790   }
02791 }
02792 
02796 static void
02797 option_reset(const config_format_t *fmt, or_options_t *options,
02798              const config_var_t *var, int use_defaults)
02799 {
02800   config_line_t *c;
02801   char *msg = NULL;
02802   CHECK(fmt, options);
02803   option_clear(fmt, options, var); /* clear it first */
02804   if (!use_defaults)
02805     return; /* all done */
02806   if (var->initvalue) {
02807     c = tor_malloc_zero(sizeof(config_line_t));
02808     c->key = tor_strdup(var->name);
02809     c->value = tor_strdup(var->initvalue);
02810     if (config_assign_value(fmt, options, c, &msg) < 0) {
02811       log_warn(LD_BUG, "Failed to assign default: %s", msg);
02812       tor_free(msg); /* if this happens it's a bug */
02813     }
02814     config_free_lines(c);
02815   }
02816 }
02817 
02819 static void
02820 print_usage(void)
02821 {
02822   printf(
02823 "Copyright (c) 2001-2004, Roger Dingledine\n"
02824 "Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n"
02825 "Copyright (c) 2007-2012, The Tor Project, Inc.\n\n"
02826 "tor -f <torrc> [args]\n"
02827 "See man page for options, or https://www.torproject.org/ for "
02828 "documentation.\n");
02829 }
02830 
02832 static void
02833 list_torrc_options(void)
02834 {
02835   int i;
02836   smartlist_t *lines = smartlist_new();
02837   for (i = 0; _option_vars[i].name; ++i) {
02838     const config_var_t *var = &_option_vars[i];
02839     if (var->type == CONFIG_TYPE_OBSOLETE ||
02840         var->type == CONFIG_TYPE_LINELIST_V)
02841       continue;
02842     printf("%s\n", var->name);
02843   }
02844   smartlist_free(lines);
02845 }
02846 
02848 static uint32_t last_resolved_addr = 0;
02857 int
02858 resolve_my_address(int warn_severity, const or_options_t *options,
02859                    uint32_t *addr_out, char **hostname_out)
02860 {
02861   struct in_addr in;
02862   uint32_t addr; /* host order */
02863   char hostname[256];
02864   int explicit_ip=1;
02865   int explicit_hostname=1;
02866   int from_interface=0;
02867   char *addr_string = NULL;
02868   const char *address = options->Address;
02869   int notice_severity = warn_severity <= LOG_NOTICE ?
02870                           LOG_NOTICE : warn_severity;
02871 
02872   tor_assert(addr_out);
02873 
02874   if (address && *address) {
02875     strlcpy(hostname, address, sizeof(hostname));
02876   } else { /* then we need to guess our address */
02877     explicit_ip = 0; /* it's implicit */
02878     explicit_hostname = 0; /* it's implicit */
02879 
02880     if (gethostname(hostname, sizeof(hostname)) < 0) {
02881       log_fn(warn_severity, LD_NET,"Error obtaining local hostname");
02882       return -1;
02883     }
02884     log_debug(LD_CONFIG,"Guessed local host name as '%s'",hostname);
02885   }
02886 
02887   /* now we know hostname. resolve it and keep only the IP address */
02888 
02889   if (tor_inet_aton(hostname, &in) == 0) {
02890     /* then we have to resolve it */
02891     explicit_ip = 0;
02892     if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */
02893       uint32_t interface_ip; /* host order */
02894 
02895       if (explicit_hostname) {
02896         log_fn(warn_severity, LD_CONFIG,
02897                "Could not resolve local Address '%s'. Failing.", hostname);
02898         return -1;
02899       }
02900       log_fn(notice_severity, LD_CONFIG,
02901              "Could not resolve guessed local hostname '%s'. "
02902              "Trying something else.", hostname);
02903       if (get_interface_address(warn_severity, &interface_ip)) {
02904         log_fn(warn_severity, LD_CONFIG,
02905                "Could not get local interface IP address. Failing.");
02906         return -1;
02907       }
02908       from_interface = 1;
02909       addr = interface_ip;
02910       log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
02911              "local interface. Using that.", fmt_addr32(addr));
02912       strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
02913     } else { /* resolved hostname into addr */
02914       if (!explicit_hostname &&
02915           is_internal_IP(addr, 0)) {
02916         uint32_t interface_ip;
02917 
02918         log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
02919                "resolves to a private IP address (%s). Trying something "
02920                "else.", hostname, fmt_addr32(addr));
02921 
02922         if (get_interface_address(warn_severity, &interface_ip)) {
02923           log_fn(warn_severity, LD_CONFIG,
02924                  "Could not get local interface IP address. Too bad.");
02925         } else if (is_internal_IP(interface_ip, 0)) {
02926           log_fn(notice_severity, LD_CONFIG,
02927                  "Interface IP address '%s' is a private address too. "
02928                  "Ignoring.", fmt_addr32(interface_ip));
02929         } else {
02930           from_interface = 1;
02931           addr = interface_ip;
02932           log_fn(notice_severity, LD_CONFIG,
02933                  "Learned IP address '%s' for local interface."
02934                  " Using that.", fmt_addr32(addr));
02935           strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
02936         }
02937       }
02938     }
02939   } else {
02940     addr = ntohl(in.s_addr); /* set addr so that addr_string is not
02941                               * illformed */
02942   }
02943 
02944   addr_string = tor_dup_ip(addr);
02945   if (is_internal_IP(addr, 0)) {
02946     /* make sure we're ok with publishing an internal IP */
02947     if (!options->DirServers && !options->AlternateDirAuthority) {
02948       /* if they are using the default dirservers, disallow internal IPs
02949        * always. */
02950       log_fn(warn_severity, LD_CONFIG,
02951              "Address '%s' resolves to private IP address '%s'. "
02952              "Tor servers that use the default DirServers must have public "
02953              "IP addresses.", hostname, addr_string);
02954       tor_free(addr_string);
02955       return -1;
02956     }
02957     if (!explicit_ip) {
02958       /* even if they've set their own dirservers, require an explicit IP if
02959        * they're using an internal address. */
02960       log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private "
02961              "IP address '%s'. Please set the Address config option to be "
02962              "the IP address you want to use.", hostname, addr_string);
02963       tor_free(addr_string);
02964       return -1;
02965     }
02966   }
02967 
02968   log_debug(LD_CONFIG, "Resolved Address to '%s'.", fmt_addr32(addr));
02969   *addr_out = addr;
02970   if (last_resolved_addr && last_resolved_addr != *addr_out) {
02971     /* Leave this as a notice, regardless of the requested severity,
02972      * at least until dynamic IP address support becomes bulletproof. */
02973     log_notice(LD_NET,
02974                "Your IP address seems to have changed to %s. Updating.",
02975                addr_string);
02976     ip_address_changed(0);
02977   }
02978   if (last_resolved_addr != *addr_out) {
02979     const char *method;
02980     const char *h = hostname;
02981     if (explicit_ip) {
02982       method = "CONFIGURED";
02983       h = NULL;
02984     } else if (explicit_hostname) {
02985       method = "RESOLVED";
02986     } else if (from_interface) {
02987       method = "INTERFACE";
02988       h = NULL;
02989     } else {
02990       method = "GETHOSTNAME";
02991     }
02992     control_event_server_status(LOG_NOTICE,
02993                                 "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s",
02994                                 addr_string, method, h?"HOSTNAME=":"", h);
02995   }
02996   last_resolved_addr = *addr_out;
02997   if (hostname_out)
02998     *hostname_out = tor_strdup(hostname);
02999   tor_free(addr_string);
03000   return 0;
03001 }
03002 
03006 int
03007 is_local_addr(const tor_addr_t *addr)
03008 {
03009   if (tor_addr_is_internal(addr, 0))
03010     return 1;
03011   /* Check whether ip is on the same /24 as we are. */
03012   if (get_options()->EnforceDistinctSubnets == 0)
03013     return 0;
03014   if (tor_addr_family(addr) == AF_INET) {
03015     /*XXXX023 IP6 what corresponds to an /24? */
03016     uint32_t ip = tor_addr_to_ipv4h(addr);
03017 
03018     /* It's possible that this next check will hit before the first time
03019      * resolve_my_address actually succeeds.  (For clients, it is likely that
03020      * resolve_my_address will never be called at all).  In those cases,
03021      * last_resolved_addr will be 0, and so checking to see whether ip is on
03022      * the same /24 as last_resolved_addr will be the same as checking whether
03023      * it was on net 0, which is already done by is_internal_IP.
03024      */
03025     if ((last_resolved_addr & (uint32_t)0xffffff00ul)
03026         == (ip & (uint32_t)0xffffff00ul))
03027       return 1;
03028   }
03029   return 0;
03030 }
03031 
03033 static void
03034 config_free(const config_format_t *fmt, void *options)
03035 {
03036   int i;
03037 
03038   if (!options)
03039     return;
03040 
03041   tor_assert(fmt);
03042 
03043   for (i=0; fmt->vars[i].name; ++i)
03044     option_clear(fmt, options, &(fmt->vars[i]));
03045   if (fmt->extra) {
03046     config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset);
03047     config_free_lines(*linep);
03048     *linep = NULL;
03049   }
03050   tor_free(options);
03051 }
03052 
03055 static int
03056 config_lines_eq(config_line_t *a, config_line_t *b)
03057 {
03058   while (a && b) {
03059     if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value))
03060       return 0;
03061     a = a->next;
03062     b = b->next;
03063   }
03064   if (a || b)
03065     return 0;
03066   return 1;
03067 }
03068 
03072 static int
03073 option_is_same(const config_format_t *fmt,
03074                const or_options_t *o1, const or_options_t *o2,
03075                const char *name)
03076 {
03077   config_line_t *c1, *c2;
03078   int r = 1;
03079   CHECK(fmt, o1);
03080   CHECK(fmt, o2);
03081 
03082   c1 = get_assigned_option(fmt, o1, name, 0);
03083   c2 = get_assigned_option(fmt, o2, name, 0);
03084   r = config_lines_eq(c1, c2);
03085   config_free_lines(c1);
03086   config_free_lines(c2);
03087   return r;
03088 }
03089 
03091 static or_options_t *
03092 options_dup(const config_format_t *fmt, const or_options_t *old)
03093 {
03094   or_options_t *newopts;
03095   int i;
03096   config_line_t *line;
03097 
03098   newopts = config_alloc(fmt);
03099   for (i=0; fmt->vars[i].name; ++i) {
03100     if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
03101       continue;
03102     if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE)
03103       continue;
03104     line = get_assigned_option(fmt, old, fmt->vars[i].name, 0);
03105     if (line) {
03106       char *msg = NULL;
03107       if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) {
03108         log_err(LD_BUG, "Config_get_assigned_option() generated "
03109                 "something we couldn't config_assign(): %s", msg);
03110         tor_free(msg);
03111         tor_assert(0);
03112       }
03113     }
03114     config_free_lines(line);
03115   }
03116   return newopts;
03117 }
03118 
03120 or_options_t *
03121 options_new(void)
03122 {
03123   return config_alloc(&options_format);
03124 }
03125 
03128 void
03129 options_init(or_options_t *options)
03130 {
03131   config_init(&options_format, options);
03132 }
03133 
03136 static void
03137 config_init(const config_format_t *fmt, void *options)
03138 {
03139   int i;
03140   const config_var_t *var;
03141   CHECK(fmt, options);
03142 
03143   for (i=0; fmt->vars[i].name; ++i) {
03144     var = &fmt->vars[i];
03145     if (!var->initvalue)
03146       continue; /* defaults to NULL or 0 */
03147     option_reset(fmt, options, var, 1);
03148   }
03149 }
03150 
03155 static char *
03156 config_dump(const config_format_t *fmt, const void *default_options,
03157             const void *options, int minimal,
03158             int comment_defaults)
03159 {
03160   smartlist_t *elements;
03161   const or_options_t *defaults = default_options;
03162   void *defaults_tmp = NULL;
03163   config_line_t *line, *assigned;
03164   char *result;
03165   int i;
03166   char *msg = NULL;
03167 
03168   if (defaults == NULL) {
03169     defaults = defaults_tmp = config_alloc(fmt);
03170     config_init(fmt, defaults_tmp);
03171   }
03172 
03173   /* XXX use a 1 here so we don't add a new log line while dumping */
03174   if (default_options == NULL) {
03175     if (fmt->validate_fn(NULL, defaults_tmp, 1, &msg) < 0) {
03176       log_err(LD_BUG, "Failed to validate default config.");
03177       tor_free(msg);
03178       tor_assert(0);
03179     }
03180   }
03181 
03182   elements = smartlist_new();
03183   for (i=0; fmt->vars[i].name; ++i) {
03184     int comment_option = 0;
03185     if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE ||
03186         fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
03187       continue;
03188     /* Don't save 'hidden' control variables. */
03189     if (!strcmpstart(fmt->vars[i].name, "__"))
03190       continue;
03191     if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name))
03192       continue;
03193     else if (comment_defaults &&
03194              option_is_same(fmt, options, defaults, fmt->vars[i].name))
03195       comment_option = 1;
03196 
03197     line = assigned = get_assigned_option(fmt, options, fmt->vars[i].name, 1);
03198 
03199     for (; line; line = line->next) {
03200       smartlist_add_asprintf(elements, "%s%s %s\n",
03201                    comment_option ? "# " : "",
03202                    line->key, line->value);
03203     }
03204     config_free_lines(assigned);
03205   }
03206 
03207   if (fmt->extra) {
03208     line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset);
03209     for (; line; line = line->next) {
03210       smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value);
03211     }
03212   }
03213 
03214   result = smartlist_join_strings(elements, "", 0, NULL);
03215   SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
03216   smartlist_free(elements);
03217   if (defaults_tmp)
03218     config_free(fmt, defaults_tmp);
03219   return result;
03220 }
03221 
03226 char *
03227 options_dump(const or_options_t *options, int minimal)
03228 {
03229   return config_dump(&options_format, global_default_options,
03230                      options, minimal, 0);
03231 }
03232 
03236 static int
03237 validate_ports_csv(smartlist_t *sl, const char *name, char **msg)
03238 {
03239   int i;
03240   tor_assert(name);
03241 
03242   if (!sl)
03243     return 0;
03244 
03245   SMARTLIST_FOREACH(sl, const char *, cp,
03246   {
03247     i = atoi(cp);
03248     if (i < 1 || i > 65535) {
03249       tor_asprintf(msg, "Port '%s' out of range in %s", cp, name);
03250       return -1;
03251     }
03252   });
03253   return 0;
03254 }
03255 
03260 static int
03261 ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
03262 {
03263   if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
03264     /* This handles an understandable special case where somebody says "2gb"
03265      * whereas our actual maximum is 2gb-1 (INT_MAX) */
03266     --*value;
03267   }
03268   if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
03269     tor_asprintf(msg, "%s ("U64_FORMAT") must be at most %d",
03270                  desc, U64_PRINTF_ARG(*value),
03271                  ROUTER_MAX_DECLARED_BANDWIDTH);
03272     return -1;
03273   }
03274   return 0;
03275 }
03276 
03283 static int
03284 compute_publishserverdescriptor(or_options_t *options)
03285 {
03286   smartlist_t *list = options->PublishServerDescriptor;
03287   dirinfo_type_t *auth = &options->_PublishServerDescriptor;
03288   *auth = NO_DIRINFO;
03289   if (!list) /* empty list, answer is none */
03290     return 0;
03291   SMARTLIST_FOREACH(list, const char *, string, {
03292     if (!strcasecmp(string, "v1"))
03293       *auth |= V1_DIRINFO;
03294     else if (!strcmp(string, "1"))
03295       if (options->BridgeRelay)
03296         *auth |= BRIDGE_DIRINFO;
03297       else
03298         *auth |= V2_DIRINFO | V3_DIRINFO;
03299     else if (!strcasecmp(string, "v2"))
03300       *auth |= V2_DIRINFO;
03301     else if (!strcasecmp(string, "v3"))
03302       *auth |= V3_DIRINFO;
03303     else if (!strcasecmp(string, "bridge"))
03304       *auth |= BRIDGE_DIRINFO;
03305     else if (!strcasecmp(string, "hidserv"))
03306       log_warn(LD_CONFIG,
03307                "PublishServerDescriptor hidserv is invalid. See "
03308                "PublishHidServDescriptors.");
03309     else if (!strcasecmp(string, "") || !strcmp(string, "0"))
03310       /* no authority */;
03311     else
03312       return -1;
03313     });
03314   return 0;
03315 }
03316 
03319 #define MIN_REND_POST_PERIOD (10*60)
03320 
03322 #define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2)
03323 
03326 #define MIN_MAX_CIRCUIT_DIRTINESS 10
03327 
03330 #define MIN_CIRCUIT_STREAM_TIMEOUT 10
03331 
03334 #define MIN_HEARTBEAT_PERIOD (30*60)
03335 
03341 #define RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT (10)
03342 
03355 static int
03356 options_validate(or_options_t *old_options, or_options_t *options,
03357                  int from_setconf, char **msg)
03358 {
03359   int i;
03360   config_line_t *cl;
03361   const char *uname = get_uname();
03362   int n_ports=0;
03363 #define REJECT(arg) \
03364   STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
03365 #define COMPLAIN(arg) STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END
03366 
03367   tor_assert(msg);
03368   *msg = NULL;
03369 
03370   if (server_mode(options) &&
03371       (!strcmpstart(uname, "Windows 95") ||
03372        !strcmpstart(uname, "Windows 98") ||
03373        !strcmpstart(uname, "Windows Me"))) {
03374     log(LOG_WARN, LD_CONFIG, "Tor is running as a server, but you are "
03375         "running %s; this probably won't work. See "
03376         "https://wiki.torproject.org/TheOnionRouter/TorFAQ#ServerOS "
03377         "for details.", uname);
03378   }
03379 
03380   if (parse_ports(options, 1, msg, &n_ports) < 0)
03381     return -1;
03382 
03383   if (validate_data_directory(options)<0)
03384     REJECT("Invalid DataDirectory");
03385 
03386   if (options->Nickname == NULL) {
03387     if (server_mode(options)) {
03388         options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME);
03389     }
03390   } else {
03391     if (!is_legal_nickname(options->Nickname)) {
03392       tor_asprintf(msg,
03393           "Nickname '%s' is wrong length or contains illegal characters.",
03394           options->Nickname);
03395       return -1;
03396     }
03397   }
03398 
03399   if (server_mode(options) && !options->ContactInfo)
03400     log(LOG_NOTICE, LD_CONFIG, "Your ContactInfo config option is not set. "
03401         "Please consider setting it, so we can contact you if your server is "
03402         "misconfigured or something else goes wrong.");
03403 
03404   /* Special case on first boot if no Log options are given. */
03405   if (!options->Logs && !options->RunAsDaemon && !from_setconf) {
03406     if (quiet_level == 0)
03407         config_line_append(&options->Logs, "Log", "notice stdout");
03408     else if (quiet_level == 1)
03409         config_line_append(&options->Logs, "Log", "warn stdout");
03410   }
03411 
03412   if (options_init_logs(options, 1)<0) /* Validate the log(s) */
03413     REJECT("Failed to validate Log options. See logs for details.");
03414 
03415   if (authdir_mode(options)) {
03416     /* confirm that our address isn't broken, so we can complain now */
03417     uint32_t tmp;
03418     if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0)
03419       REJECT("Failed to resolve/guess local address. See logs for details.");
03420   }
03421 
03422 #ifndef _WIN32
03423   if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname))
03424     REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
03425 #endif
03426 
03427   /* XXXX require that the only port not be DirPort? */
03428   /* XXXX require that at least one port be listened-upon. */
03429   if (n_ports == 0 && !options->RendConfigLines)
03430     log(LOG_WARN, LD_CONFIG,
03431         "SocksPort, TransPort, NATDPort, DNSPort, and ORPort are all "
03432         "undefined, and there aren't any hidden services configured.  "
03433         "Tor will still run, but probably won't do anything.");
03434 
03435 #ifndef USE_TRANSPARENT
03436   if (options->TransPort || options->TransListenAddress)
03437     REJECT("TransPort and TransListenAddress are disabled in this build.");
03438 #endif
03439 
03440   if (options->TokenBucketRefillInterval <= 0
03441       || options->TokenBucketRefillInterval > 1000) {
03442     REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
03443   }
03444 
03445   if (options->ExcludeExitNodes || options->ExcludeNodes) {
03446     options->_ExcludeExitNodesUnion = routerset_new();
03447     routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeExitNodes);
03448     routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes);
03449   }
03450 
03451   if (options->NodeFamilies) {
03452     options->NodeFamilySets = smartlist_new();
03453     for (cl = options->NodeFamilies; cl; cl = cl->next) {
03454       routerset_t *rs = routerset_new();
03455       if (routerset_parse(rs, cl->value, cl->key) == 0) {
03456         smartlist_add(options->NodeFamilySets, rs);
03457       } else {
03458         routerset_free(rs);
03459       }
03460     }
03461   }
03462 
03463   if (options->ExcludeNodes && options->StrictNodes) {
03464     COMPLAIN("You have asked to exclude certain relays from all positions "
03465              "in your circuits. Expect hidden services and other Tor "
03466              "features to be broken in unpredictable ways.");
03467   }
03468 
03469   if (options->AuthoritativeDir) {
03470     if (!options->ContactInfo && !options->TestingTorNetwork)
03471       REJECT("Authoritative directory servers must set ContactInfo");
03472     if (options->V1AuthoritativeDir && !options->RecommendedVersions)
03473       REJECT("V1 authoritative dir servers must set RecommendedVersions.");
03474     if (!options->RecommendedClientVersions)
03475       options->RecommendedClientVersions =
03476         config_lines_dup(options->RecommendedVersions);
03477     if (!options->RecommendedServerVersions)
03478       options->RecommendedServerVersions =
03479         config_lines_dup(options->RecommendedVersions);
03480     if (options->VersioningAuthoritativeDir &&
03481         (!options->RecommendedClientVersions ||
03482          !options->RecommendedServerVersions))
03483       REJECT("Versioning authoritative dir servers must set "
03484              "Recommended*Versions.");
03485     if (options->UseEntryGuards) {
03486       log_info(LD_CONFIG, "Authoritative directory servers can't set "
03487                "UseEntryGuards. Disabling.");
03488       options->UseEntryGuards = 0;
03489     }
03490     if (!options->DownloadExtraInfo && authdir_mode_any_main(options)) {
03491       log_info(LD_CONFIG, "Authoritative directories always try to download "
03492                "extra-info documents. Setting DownloadExtraInfo.");
03493       options->DownloadExtraInfo = 1;
03494     }
03495     if (!(options->BridgeAuthoritativeDir || options->HSAuthoritativeDir ||
03496           options->V1AuthoritativeDir || options->V2AuthoritativeDir ||
03497           options->V3AuthoritativeDir))
03498       REJECT("AuthoritativeDir is set, but none of "
03499              "(Bridge/HS/V1/V2/V3)AuthoritativeDir is set.");
03500     /* If we have a v3bandwidthsfile and it's broken, complain on startup */
03501     if (options->V3BandwidthsFile && !old_options) {
03502       dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL);
03503     }
03504   }
03505 
03506   if (options->AuthoritativeDir && !options->DirPort)
03507     REJECT("Running as authoritative directory, but no DirPort set.");
03508 
03509   if (options->AuthoritativeDir && !options->ORPort)
03510     REJECT("Running as authoritative directory, but no ORPort set.");
03511 
03512   if (options->AuthoritativeDir && options->ClientOnly)
03513     REJECT("Running as authoritative directory, but ClientOnly also set.");
03514 
03515   if (options->FetchDirInfoExtraEarly && !options->FetchDirInfoEarly)
03516     REJECT("FetchDirInfoExtraEarly requires that you also set "
03517            "FetchDirInfoEarly");
03518 
03519   if (options->HSAuthoritativeDir && proxy_mode(options))
03520     REJECT("Running as authoritative v0 HS directory, but also configured "
03521            "as a client.");
03522 
03523   if (options->ConnLimit <= 0) {
03524     tor_asprintf(msg,
03525         "ConnLimit must be greater than 0, but was set to %d",
03526         options->ConnLimit);
03527     return -1;
03528   }
03529 
03530   if (options->MaxClientCircuitsPending <= 0 ||
03531       options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) {
03532     tor_asprintf(msg,
03533                  "MaxClientCircuitsPending must be between 1 and %d, but "
03534                  "was set to %d", MAX_MAX_CLIENT_CIRCUITS_PENDING,
03535                  options->MaxClientCircuitsPending);
03536     return -1;
03537   }
03538 
03539   if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0)
03540     return -1;
03541 
03542   if (validate_ports_csv(options->LongLivedPorts, "LongLivedPorts", msg) < 0)
03543     return -1;
03544 
03545   if (validate_ports_csv(options->RejectPlaintextPorts,
03546                          "RejectPlaintextPorts", msg) < 0)
03547     return -1;
03548 
03549   if (validate_ports_csv(options->WarnPlaintextPorts,
03550                          "WarnPlaintextPorts", msg) < 0)
03551     return -1;
03552 
03553   if (options->FascistFirewall && !options->ReachableAddresses) {
03554     if (options->FirewallPorts && smartlist_len(options->FirewallPorts)) {
03555       /* We already have firewall ports set, so migrate them to
03556        * ReachableAddresses, which will set ReachableORAddresses and
03557        * ReachableDirAddresses if they aren't set explicitly. */
03558       smartlist_t *instead = smartlist_new();
03559       config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
03560       new_line->key = tor_strdup("ReachableAddresses");
03561       /* If we're configured with the old format, we need to prepend some
03562        * open ports. */
03563       SMARTLIST_FOREACH(options->FirewallPorts, const char *, portno,
03564       {
03565         int p = atoi(portno);
03566         if (p<0) continue;
03567         smartlist_add_asprintf(instead, "*:%d", p);
03568       });
03569       new_line->value = smartlist_join_strings(instead,",",0,NULL);
03570       /* These have been deprecated since 0.1.1.5-alpha-cvs */
03571       log(LOG_NOTICE, LD_CONFIG,
03572           "Converting FascistFirewall and FirewallPorts "
03573           "config options to new format: \"ReachableAddresses %s\"",
03574           new_line->value);
03575       options->ReachableAddresses = new_line;
03576       SMARTLIST_FOREACH(instead, char *, cp, tor_free(cp));
03577       smartlist_free(instead);
03578     } else {
03579       /* We do not have FirewallPorts set, so add 80 to
03580        * ReachableDirAddresses, and 443 to ReachableORAddresses. */
03581       if (!options->ReachableDirAddresses) {
03582         config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
03583         new_line->key = tor_strdup("ReachableDirAddresses");
03584         new_line->value = tor_strdup("*:80");
03585         options->ReachableDirAddresses = new_line;
03586         log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
03587             "to new format: \"ReachableDirAddresses *:80\"");
03588       }
03589       if (!options->ReachableORAddresses) {
03590         config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
03591         new_line->key = tor_strdup("ReachableORAddresses");
03592         new_line->value = tor_strdup("*:443");
03593         options->ReachableORAddresses = new_line;
03594         log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
03595             "to new format: \"ReachableORAddresses *:443\"");
03596       }
03597     }
03598   }
03599 
03600   for (i=0; i<3; i++) {
03601     config_line_t **linep =
03602       (i==0) ? &options->ReachableAddresses :
03603         (i==1) ? &options->ReachableORAddresses :
03604                  &options->ReachableDirAddresses;
03605     if (!*linep)
03606       continue;
03607     /* We need to end with a reject *:*, not an implicit accept *:* */
03608     for (;;) {
03609       if (!strcmp((*linep)->value, "reject *:*")) /* already there */
03610         break;
03611       linep = &((*linep)->next);
03612       if (!*linep) {
03613         *linep = tor_malloc_zero(sizeof(config_line_t));
03614         (*linep)->key = tor_strdup(
03615           (i==0) ?  "ReachableAddresses" :
03616             (i==1) ? "ReachableORAddresses" :
03617                      "ReachableDirAddresses");
03618         (*linep)->value = tor_strdup("reject *:*");
03619         break;
03620       }
03621     }
03622   }
03623 
03624   if ((options->ReachableAddresses ||
03625        options->ReachableORAddresses ||
03626        options->ReachableDirAddresses) &&
03627       server_mode(options))
03628     REJECT("Servers must be able to freely connect to the rest "
03629            "of the Internet, so they must not set Reachable*Addresses "
03630            "or FascistFirewall.");
03631 
03632   if (options->UseBridges &&
03633       server_mode(options))
03634     REJECT("Servers must be able to freely connect to the rest "
03635            "of the Internet, so they must not set UseBridges.");
03636 
03637   /* If both of these are set, we'll end up with funny behavior where we
03638    * demand enough entrynodes be up and running else we won't build
03639    * circuits, yet we never actually use them. */
03640   if (options->UseBridges && options->EntryNodes)
03641     REJECT("You cannot set both UseBridges and EntryNodes.");
03642 
03643   if (options->EntryNodes && !options->UseEntryGuards)
03644     log_warn(LD_CONFIG, "EntryNodes is set, but UseEntryGuards is disabled. "
03645              "EntryNodes will be ignored.");
03646 
03647   options->_AllowInvalid = 0;
03648   if (options->AllowInvalidNodes) {
03649     SMARTLIST_FOREACH(options->AllowInvalidNodes, const char *, cp, {
03650         if (!strcasecmp(cp, "entry"))
03651           options->_AllowInvalid |= ALLOW_INVALID_ENTRY;
03652         else if (!strcasecmp(cp, "exit"))
03653           options->_AllowInvalid |= ALLOW_INVALID_EXIT;
03654         else if (!strcasecmp(cp, "middle"))
03655           options->_AllowInvalid |= ALLOW_INVALID_MIDDLE;
03656         else if (!strcasecmp(cp, "introduction"))
03657           options->_AllowInvalid |= ALLOW_INVALID_INTRODUCTION;
03658         else if (!strcasecmp(cp, "rendezvous"))
03659           options->_AllowInvalid |= ALLOW_INVALID_RENDEZVOUS;
03660         else {
03661           tor_asprintf(msg,
03662               "Unrecognized value '%s' in AllowInvalidNodes", cp);
03663           return -1;
03664         }
03665       });
03666   }
03667 
03668   if (!options->SafeLogging ||
03669       !strcasecmp(options->SafeLogging, "0")) {
03670     options->_SafeLogging = SAFELOG_SCRUB_NONE;
03671   } else if (!strcasecmp(options->SafeLogging, "relay")) {
03672     options->_SafeLogging = SAFELOG_SCRUB_RELAY;
03673   } else if (!strcasecmp(options->SafeLogging, "1")) {
03674     options->_SafeLogging = SAFELOG_SCRUB_ALL;
03675   } else {
03676     tor_asprintf(msg,
03677                      "Unrecognized value '%s' in SafeLogging",
03678                      escaped(options->SafeLogging));
03679     return -1;
03680   }
03681 
03682   if (compute_publishserverdescriptor(options) < 0) {
03683     tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor");
03684     return -1;
03685   }
03686 
03687   if ((options->BridgeRelay
03688         || options->_PublishServerDescriptor & BRIDGE_DIRINFO)
03689       && (options->_PublishServerDescriptor
03690           & (V1_DIRINFO|V2_DIRINFO|V3_DIRINFO))) {
03691     REJECT("Bridges are not supposed to publish router descriptors to the "
03692            "directory authorities. Please correct your "
03693            "PublishServerDescriptor line.");
03694   }
03695 
03696   if (options->BridgeRelay && options->DirPort) {
03697     log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling "
03698              "DirPort");
03699     config_free_lines(options->DirPort);
03700     options->DirPort = NULL;
03701   }
03702 
03703   if (options->MinUptimeHidServDirectoryV2 < 0) {
03704     log_warn(LD_CONFIG, "MinUptimeHidServDirectoryV2 option must be at "
03705                         "least 0 seconds. Changing to 0.");
03706     options->MinUptimeHidServDirectoryV2 = 0;
03707   }
03708 
03709   if (options->RendPostPeriod < MIN_REND_POST_PERIOD) {
03710     log_warn(LD_CONFIG, "RendPostPeriod option is too short; "
03711              "raising to %d seconds.", MIN_REND_POST_PERIOD);
03712     options->RendPostPeriod = MIN_REND_POST_PERIOD;
03713   }
03714 
03715   if (options->RendPostPeriod > MAX_DIR_PERIOD) {
03716     log_warn(LD_CONFIG, "RendPostPeriod is too large; clipping to %ds.",
03717              MAX_DIR_PERIOD);
03718     options->RendPostPeriod = MAX_DIR_PERIOD;
03719   }
03720 
03721   if (options->Tor2webMode && options->LearnCircuitBuildTimeout) {
03722     /* LearnCircuitBuildTimeout and Tor2webMode are incompatible in
03723      * two ways:
03724      *
03725      * - LearnCircuitBuildTimeout results in a low CBT, which
03726      *   Tor2webMode's use of one-hop rendezvous circuits lowers
03727      *   much further, producing *far* too many timeouts.
03728      *
03729      * - The adaptive CBT code does not update its timeout estimate
03730      *   using build times for single-hop circuits.
03731      *
03732      * If we fix both of these issues someday, we should test
03733      * Tor2webMode with LearnCircuitBuildTimeout on again. */
03734     log_notice(LD_CONFIG,"Tor2webMode is enabled; turning "
03735                "LearnCircuitBuildTimeout off.");
03736     options->LearnCircuitBuildTimeout = 0;
03737   }
03738 
03739   if (!(options->LearnCircuitBuildTimeout) &&
03740         options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) {
03741     log_warn(LD_CONFIG,
03742         "CircuitBuildTimeout is shorter (%d seconds) than recommended "
03743         "(%d seconds), and LearnCircuitBuildTimeout is disabled.  "
03744         "If tor isn't working, raise this value or enable "
03745         "LearnCircuitBuildTimeout.",
03746         options->CircuitBuildTimeout,
03747         RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT );
03748   }
03749 
03750   if (options->MaxCircuitDirtiness < MIN_MAX_CIRCUIT_DIRTINESS) {
03751     log_warn(LD_CONFIG, "MaxCircuitDirtiness option is too short; "
03752              "raising to %d seconds.", MIN_MAX_CIRCUIT_DIRTINESS);
03753     options->MaxCircuitDirtiness = MIN_MAX_CIRCUIT_DIRTINESS;
03754   }
03755 
03756   if (options->CircuitStreamTimeout &&
03757       options->CircuitStreamTimeout < MIN_CIRCUIT_STREAM_TIMEOUT) {
03758     log_warn(LD_CONFIG, "CircuitStreamTimeout option is too short; "
03759              "raising to %d seconds.", MIN_CIRCUIT_STREAM_TIMEOUT);
03760     options->CircuitStreamTimeout = MIN_CIRCUIT_STREAM_TIMEOUT;
03761   }
03762 
03763   if (options->HeartbeatPeriod &&
03764       options->HeartbeatPeriod < MIN_HEARTBEAT_PERIOD) {
03765     log_warn(LD_CONFIG, "HeartbeatPeriod option is too short; "
03766              "raising to %d seconds.", MIN_HEARTBEAT_PERIOD);
03767     options->HeartbeatPeriod = MIN_HEARTBEAT_PERIOD;
03768   }
03769 
03770   if (options->KeepalivePeriod < 1)
03771     REJECT("KeepalivePeriod option must be positive.");
03772 
03773   if (ensure_bandwidth_cap(&options->BandwidthRate,
03774                            "BandwidthRate", msg) < 0)
03775     return -1;
03776   if (ensure_bandwidth_cap(&options->BandwidthBurst,
03777                            "BandwidthBurst", msg) < 0)
03778     return -1;
03779   if (ensure_bandwidth_cap(&options->MaxAdvertisedBandwidth,
03780                            "MaxAdvertisedBandwidth", msg) < 0)
03781     return -1;
03782   if (ensure_bandwidth_cap(&options->RelayBandwidthRate,
03783                            "RelayBandwidthRate", msg) < 0)
03784     return -1;
03785   if (ensure_bandwidth_cap(&options->RelayBandwidthBurst,
03786                            "RelayBandwidthBurst", msg) < 0)
03787     return -1;
03788   if (ensure_bandwidth_cap(&options->PerConnBWRate,
03789                            "PerConnBWRate", msg) < 0)
03790     return -1;
03791   if (ensure_bandwidth_cap(&options->PerConnBWBurst,
03792                            "PerConnBWBurst", msg) < 0)
03793     return -1;
03794   if (ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
03795                            "AuthDirFastGuarantee", msg) < 0)
03796     return -1;
03797   if (ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
03798                            "AuthDirGuardBWGuarantee", msg) < 0)
03799     return -1;
03800 
03801   if (options->RelayBandwidthRate && !options->RelayBandwidthBurst)
03802     options->RelayBandwidthBurst = options->RelayBandwidthRate;
03803   if (options->RelayBandwidthBurst && !options->RelayBandwidthRate)
03804     options->RelayBandwidthRate = options->RelayBandwidthBurst;
03805 
03806   if (server_mode(options)) {
03807     if (options->BandwidthRate < ROUTER_REQUIRED_MIN_BANDWIDTH) {
03808       tor_asprintf(msg,
03809                        "BandwidthRate is set to %d bytes/second. "
03810                        "For servers, it must be at least %d.",
03811                        (int)options->BandwidthRate,
03812                        ROUTER_REQUIRED_MIN_BANDWIDTH);
03813       return -1;
03814     } else if (options->MaxAdvertisedBandwidth <
03815                ROUTER_REQUIRED_MIN_BANDWIDTH/2) {
03816       tor_asprintf(msg,
03817                        "MaxAdvertisedBandwidth is set to %d bytes/second. "
03818                        "For servers, it must be at least %d.",
03819                        (int)options->MaxAdvertisedBandwidth,
03820                        ROUTER_REQUIRED_MIN_BANDWIDTH/2);
03821       return -1;
03822     }
03823     if (options->RelayBandwidthRate &&
03824       options->RelayBandwidthRate < ROUTER_REQUIRED_MIN_BANDWIDTH) {
03825       tor_asprintf(msg,
03826                        "RelayBandwidthRate is set to %d bytes/second. "
03827                        "For servers, it must be at least %d.",
03828                        (int)options->RelayBandwidthRate,
03829                        ROUTER_REQUIRED_MIN_BANDWIDTH);
03830       return -1;
03831     }
03832   }
03833 
03834   if (options->RelayBandwidthRate > options->RelayBandwidthBurst)
03835     REJECT("RelayBandwidthBurst must be at least equal "
03836            "to RelayBandwidthRate.");
03837 
03838   if (options->BandwidthRate > options->BandwidthBurst)
03839     REJECT("BandwidthBurst must be at least equal to BandwidthRate.");
03840 
03841   /* if they set relaybandwidth* really high but left bandwidth*
03842    * at the default, raise the defaults. */
03843   if (options->RelayBandwidthRate > options->BandwidthRate)
03844     options->BandwidthRate = options->RelayBandwidthRate;
03845   if (options->RelayBandwidthBurst > options->BandwidthBurst)
03846     options->BandwidthBurst = options->RelayBandwidthBurst;
03847 
03848   if (accounting_parse_options(options, 1)<0)
03849     REJECT("Failed to parse accounting options. See logs for details.");
03850 
03851   if (options->HTTPProxy) { /* parse it now */
03852     if (tor_addr_port_lookup(options->HTTPProxy,
03853                         &options->HTTPProxyAddr, &options->HTTPProxyPort) < 0)
03854       REJECT("HTTPProxy failed to parse or resolve. Please fix.");
03855     if (options->HTTPProxyPort == 0) { /* give it a default */
03856       options->HTTPProxyPort = 80;
03857     }
03858   }
03859 
03860   if (options->HTTPProxyAuthenticator) {
03861     if (strlen(options->HTTPProxyAuthenticator) >= 512)
03862       REJECT("HTTPProxyAuthenticator is too long (>= 512 chars).");
03863   }
03864 
03865   if (options->HTTPSProxy) { /* parse it now */
03866     if (tor_addr_port_lookup(options->HTTPSProxy,
03867                         &options->HTTPSProxyAddr, &options->HTTPSProxyPort) <0)
03868       REJECT("HTTPSProxy failed to parse or resolve. Please fix.");
03869     if (options->HTTPSProxyPort == 0) { /* give it a default */
03870       options->HTTPSProxyPort = 443;
03871     }
03872   }
03873 
03874   if (options->HTTPSProxyAuthenticator) {
03875     if (strlen(options->HTTPSProxyAuthenticator) >= 512)
03876       REJECT("HTTPSProxyAuthenticator is too long (>= 512 chars).");
03877   }
03878 
03879   if (options->Socks4Proxy) { /* parse it now */
03880     if (tor_addr_port_lookup(options->Socks4Proxy,
03881                         &options->Socks4ProxyAddr,
03882                         &options->Socks4ProxyPort) <0)
03883       REJECT("Socks4Proxy failed to parse or resolve. Please fix.");
03884     if (options->Socks4ProxyPort == 0) { /* give it a default */
03885       options->Socks4ProxyPort = 1080;
03886     }
03887   }
03888 
03889   if (options->Socks5Proxy) { /* parse it now */
03890     if (tor_addr_port_lookup(options->Socks5Proxy,
03891                             &options->Socks5ProxyAddr,
03892                             &options->Socks5ProxyPort) <0)
03893       REJECT("Socks5Proxy failed to parse or resolve. Please fix.");
03894     if (options->Socks5ProxyPort == 0) { /* give it a default */
03895       options->Socks5ProxyPort = 1080;
03896     }
03897   }
03898 
03899   /* Check if more than one proxy type has been enabled. */
03900   if (!!options->Socks4Proxy + !!options->Socks5Proxy +
03901       !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1)
03902     REJECT("You have configured more than one proxy type. "
03903            "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)");
03904 
03905   /* Check if the proxies will give surprising behavior. */
03906   if (options->HTTPProxy && !(options->Socks4Proxy ||
03907                               options->Socks5Proxy ||
03908                               options->HTTPSProxy)) {
03909     log_warn(LD_CONFIG, "HTTPProxy configured, but no SOCKS proxy or "
03910              "HTTPS proxy configured. Watch out: this configuration will "
03911              "proxy unencrypted directory connections only.");
03912   }
03913 
03914   if (options->Socks5ProxyUsername) {
03915     size_t len;
03916 
03917     len = strlen(options->Socks5ProxyUsername);
03918     if (len < 1 || len > 255)
03919       REJECT("Socks5ProxyUsername must be between 1 and 255 characters.");
03920 
03921     if (!options->Socks5ProxyPassword)
03922       REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
03923 
03924     len = strlen(options->Socks5ProxyPassword);
03925     if (len < 1 || len > 255)
03926       REJECT("Socks5ProxyPassword must be between 1 and 255 characters.");
03927   } else if (options->Socks5ProxyPassword)
03928     REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
03929 
03930   if (options->HashedControlPassword) {
03931     smartlist_t *sl = decode_hashed_passwords(options->HashedControlPassword);
03932     if (!sl) {
03933       REJECT("Bad HashedControlPassword: wrong length or bad encoding");
03934     } else {
03935       SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
03936       smartlist_free(sl);
03937     }
03938   }
03939 
03940   if (options->HashedControlSessionPassword) {
03941     smartlist_t *sl = decode_hashed_passwords(
03942                                   options->HashedControlSessionPassword);
03943     if (!sl) {
03944       REJECT("Bad HashedControlSessionPassword: wrong length or bad encoding");
03945     } else {
03946       SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
03947       smartlist_free(sl);
03948     }
03949   }
03950 
03951   if (options->OwningControllerProcess) {
03952     const char *validate_pspec_msg = NULL;
03953     if (tor_validate_process_specifier(options->OwningControllerProcess,
03954                                        &validate_pspec_msg)) {
03955       tor_asprintf(msg, "Bad OwningControllerProcess: %s",
03956                    validate_pspec_msg);
03957       return -1;
03958     }
03959   }
03960 
03961   if (options->ControlPort && !options->HashedControlPassword &&
03962       !options->HashedControlSessionPassword &&
03963       !options->CookieAuthentication) {
03964     log_warn(LD_CONFIG, "ControlPort is open, but no authentication method "
03965              "has been configured.  This means that any program on your "
03966              "computer can reconfigure your Tor.  That's bad!  You should "
03967              "upgrade your Tor controller as soon as possible.");
03968   }
03969 
03970   if (options->CookieAuthFileGroupReadable && !options->CookieAuthFile) {
03971     log_warn(LD_CONFIG, "CookieAuthFileGroupReadable is set, but will have "
03972              "no effect: you must specify an explicit CookieAuthFile to "
03973              "have it group-readable.");
03974   }
03975 
03976   if (options->UseEntryGuards && ! options->NumEntryGuards)
03977     REJECT("Cannot enable UseEntryGuards with NumEntryGuards set to 0");
03978 
03979   if (options->MyFamily && options->BridgeRelay) {
03980     log_warn(LD_CONFIG, "Listing a family for a bridge relay is not "
03981              "supported: it can reveal bridge fingerprints to censors. "
03982              "You should also make sure you aren't listing this bridge's "
03983              "fingerprint in any other MyFamily.");
03984   }
03985   if (check_nickname_list(options->MyFamily, "MyFamily", msg))
03986     return -1;
03987   for (cl = options->NodeFamilies; cl; cl = cl->next) {
03988     routerset_t *rs = routerset_new();
03989     if (routerset_parse(rs, cl->value, cl->key)) {
03990       routerset_free(rs);
03991       return -1;
03992     }
03993     routerset_free(rs);
03994   }
03995 
03996   if (validate_addr_policies(options, msg) < 0)
03997     return -1;
03998 
03999   if (validate_dir_authorities(options, old_options) < 0)
04000     REJECT("Directory authority line did not parse. See logs for details.");
04001 
04002   if (options->UseBridges && !options->Bridges)
04003     REJECT("If you set UseBridges, you must specify at least one bridge.");
04004   if (options->UseBridges && !options->TunnelDirConns)
04005     REJECT("If you set UseBridges, you must set TunnelDirConns.");
04006 
04007   for (cl = options->Bridges; cl; cl = cl->next) {
04008     if (parse_bridge_line(cl->value, 1)<0)
04009       REJECT("Bridge line did not parse. See logs for details.");
04010   }
04011 
04012   for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
04013     if (parse_client_transport_line(cl->value, 1)<0)
04014       REJECT("Transport line did not parse. See logs for details.");
04015   }
04016 
04017   for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
04018     if (parse_server_transport_line(cl->value, 1)<0)
04019       REJECT("Server transport line did not parse. See logs for details.");
04020   }
04021 
04022   if (options->ConstrainedSockets) {
04023     /* If the user wants to constrain socket buffer use, make sure the desired
04024      * limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */
04025     if (options->ConstrainedSockSize < MIN_CONSTRAINED_TCP_BUFFER ||
04026         options->ConstrainedSockSize > MAX_CONSTRAINED_TCP_BUFFER ||
04027         options->ConstrainedSockSize % 1024) {
04028       tor_asprintf(msg,
04029           "ConstrainedSockSize is invalid.  Must be a value between %d and %d "
04030           "in 1024 byte increments.",
04031           MIN_CONSTRAINED_TCP_BUFFER, MAX_CONSTRAINED_TCP_BUFFER);
04032       return -1;
04033     }
04034     if (options->DirPort) {
04035       /* Providing cached directory entries while system TCP buffers are scarce
04036        * will exacerbate the socket errors.  Suggest that this be disabled. */
04037       COMPLAIN("You have requested constrained socket buffers while also "
04038                "serving directory entries via DirPort.  It is strongly "
04039                "suggested that you disable serving directory requests when "
04040                "system TCP buffer resources are scarce.");
04041     }
04042   }
04043 
04044   if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
04045       options->V3AuthVotingInterval/2) {
04046     REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
04047            "V3AuthVotingInterval");
04048   }
04049   if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS)
04050     REJECT("V3AuthVoteDelay is way too low.");
04051   if (options->V3AuthDistDelay < MIN_DIST_SECONDS)
04052     REJECT("V3AuthDistDelay is way too low.");
04053 
04054   if (options->V3AuthNIntervalsValid < 2)
04055     REJECT("V3AuthNIntervalsValid must be at least 2.");
04056 
04057   if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
04058     REJECT("V3AuthVotingInterval is insanely low.");
04059   } else if (options->V3AuthVotingInterval > 24*60*60) {
04060     REJECT("V3AuthVotingInterval is insanely high.");
04061   } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
04062     COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours.");
04063   }
04064 
04065   if (rend_config_services(options, 1) < 0)
04066     REJECT("Failed to configure rendezvous options. See logs for details.");
04067 
04068   /* Parse client-side authorization for hidden services. */
04069   if (rend_parse_service_authorization(options, 1) < 0)
04070     REJECT("Failed to configure client authorization for hidden services. "
04071            "See logs for details.");
04072 
04073   if (parse_virtual_addr_network(options->VirtualAddrNetwork, 1, NULL)<0)
04074     return -1;
04075 
04076   if (options->PreferTunneledDirConns && !options->TunnelDirConns)
04077     REJECT("Must set TunnelDirConns if PreferTunneledDirConns is set.");
04078 
04079   if ((options->Socks4Proxy || options->Socks5Proxy) &&
04080       !options->HTTPProxy && !options->PreferTunneledDirConns)
04081     REJECT("When Socks4Proxy or Socks5Proxy is configured, "
04082            "PreferTunneledDirConns and TunnelDirConns must both be "
04083            "set to 1, or HTTPProxy must be configured.");
04084 
04085   if (options->AutomapHostsSuffixes) {
04086     SMARTLIST_FOREACH(options->AutomapHostsSuffixes, char *, suf,
04087     {
04088       size_t len = strlen(suf);
04089       if (len && suf[len-1] == '.')
04090         suf[len-1] = '\0';
04091     });
04092   }
04093 
04094   if (options->TestingTorNetwork && !options->DirServers) {
04095     REJECT("TestingTorNetwork may only be configured in combination with "
04096            "a non-default set of DirServers.");
04097   }
04098 
04099   if (options->AllowSingleHopExits && !options->DirServers) {
04100     COMPLAIN("You have set AllowSingleHopExits; now your relay will allow "
04101              "others to make one-hop exits. However, since by default most "
04102              "clients avoid relays that set this option, most clients will "
04103              "ignore you.");
04104   }
04105 
04106   /*XXXX checking for defaults manually like this is a bit fragile.*/
04107 
04108   /* Keep changes to hard-coded values synchronous to man page and default
04109    * values table. */
04110   if (options->TestingV3AuthInitialVotingInterval != 30*60 &&
04111       !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) {
04112     REJECT("TestingV3AuthInitialVotingInterval may only be changed in testing "
04113            "Tor networks!");
04114   } else if (options->TestingV3AuthInitialVotingInterval < MIN_VOTE_INTERVAL) {
04115     REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
04116   } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
04117     REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
04118            "30 minutes.");
04119   }
04120 
04121   if (options->TestingV3AuthInitialVoteDelay != 5*60 &&
04122       !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) {
04123 
04124     REJECT("TestingV3AuthInitialVoteDelay may only be changed in testing "
04125            "Tor networks!");
04126   } else if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS) {
04127     REJECT("TestingV3AuthInitialVoteDelay is way too low.");
04128   }
04129 
04130   if (options->TestingV3AuthInitialDistDelay != 5*60 &&
04131       !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) {
04132     REJECT("TestingV3AuthInitialDistDelay may only be changed in testing "
04133            "Tor networks!");
04134   } else if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS) {
04135     REJECT("TestingV3AuthInitialDistDelay is way too low.");
04136   }
04137 
04138   if (options->TestingV3AuthInitialVoteDelay +
04139       options->TestingV3AuthInitialDistDelay >=
04140       options->TestingV3AuthInitialVotingInterval/2) {
04141     REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
04142            "must be less than half TestingV3AuthInitialVotingInterval");
04143   }
04144 
04145   if (options->TestingAuthDirTimeToLearnReachability != 30*60 &&
04146       !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) {
04147     REJECT("TestingAuthDirTimeToLearnReachability may only be changed in "
04148            "testing Tor networks!");
04149   } else if (options->TestingAuthDirTimeToLearnReachability < 0) {
04150     REJECT("TestingAuthDirTimeToLearnReachability must be non-negative.");
04151   } else if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
04152     COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
04153   }
04154 
04155   if (options->TestingEstimatedDescriptorPropagationTime != 10*60 &&
04156       !options->TestingTorNetwork && !options->_UsingTestNetworkDefaults) {
04157     REJECT("TestingEstimatedDescriptorPropagationTime may only be changed in "
04158            "testing Tor networks!");
04159   } else if (options->TestingEstimatedDescriptorPropagationTime < 0) {
04160     REJECT("TestingEstimatedDescriptorPropagationTime must be non-negative.");
04161   } else if (options->TestingEstimatedDescriptorPropagationTime > 60*60) {
04162     COMPLAIN("TestingEstimatedDescriptorPropagationTime is insanely high.");
04163   }
04164 
04165   if (options->TestingTorNetwork) {
04166     log_warn(LD_CONFIG, "TestingTorNetwork is set. This will make your node "
04167                         "almost unusable in the public Tor network, and is "
04168                         "therefore only advised if you are building a "
04169                         "testing Tor network!");
04170   }
04171 
04172   if (options->AccelName && !options->HardwareAccel)
04173     options->HardwareAccel = 1;
04174   if (options->AccelDir && !options->AccelName)
04175     REJECT("Can't use hardware crypto accelerator dir without engine name.");
04176 
04177   if (options->PublishServerDescriptor)
04178     SMARTLIST_FOREACH(options->PublishServerDescriptor, const char *, pubdes, {
04179       if (!strcmp(pubdes, "1") || !strcmp(pubdes, "0"))
04180         if (smartlist_len(options->PublishServerDescriptor) > 1) {
04181           COMPLAIN("You have passed a list of multiple arguments to the "
04182                    "PublishServerDescriptor option that includes 0 or 1. "
04183                    "0 or 1 should only be used as the sole argument. "
04184                    "This configuration will be rejected in a future release.");
04185           break;
04186         }
04187     });
04188 
04189   if (options->BridgeRelay == 1 && ! options->ORPort)
04190       REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
04191              "combination.");
04192 
04193   return 0;
04194 #undef REJECT
04195 #undef COMPLAIN
04196 }
04197 
04200 static int
04201 opt_streq(const char *s1, const char *s2)
04202 {
04203   return 0 == strcmp_opt(s1, s2);
04204 }
04205 
04207 static int
04208 options_transition_allowed(const or_options_t *old,
04209                            const or_options_t *new_val,
04210                            char **msg)
04211 {
04212   if (!old)
04213     return 0;
04214 
04215   if (!opt_streq(old->PidFile, new_val->PidFile)) {
04216     *msg = tor_strdup("PidFile is not allowed to change.");
04217     return -1;
04218   }
04219 
04220   if (old->RunAsDaemon != new_val->RunAsDaemon) {
04221     *msg = tor_strdup("While Tor is running, changing RunAsDaemon "
04222                       "is not allowed.");
04223     return -1;
04224   }
04225 
04226   if (strcmp(old->DataDirectory,new_val->DataDirectory)!=0) {
04227     tor_asprintf(msg,
04228                "While Tor is running, changing DataDirectory "
04229                "(\"%s\"->\"%s\") is not allowed.",
04230                old->DataDirectory, new_val->DataDirectory);
04231     return -1;
04232   }
04233 
04234   if (!opt_streq(old->User, new_val->User)) {
04235     *msg = tor_strdup("While Tor is running, changing User is not allowed.");
04236     return -1;
04237   }
04238 
04239   if ((old->HardwareAccel != new_val->HardwareAccel)
04240       || !opt_streq(old->AccelName, new_val->AccelName)
04241       || !opt_streq(old->AccelDir, new_val->AccelDir)) {
04242     *msg = tor_strdup("While Tor is running, changing OpenSSL hardware "
04243                       "acceleration engine is not allowed.");
04244     return -1;
04245   }
04246 
04247   if (old->TestingTorNetwork != new_val->TestingTorNetwork) {
04248     *msg = tor_strdup("While Tor is running, changing TestingTorNetwork "
04249                       "is not allowed.");
04250     return -1;
04251   }
04252 
04253   if (old->DisableAllSwap != new_val->DisableAllSwap) {
04254     *msg = tor_strdup("While Tor is running, changing DisableAllSwap "
04255                       "is not allowed.");
04256     return -1;
04257   }
04258 
04259   if (old->TokenBucketRefillInterval != new_val->TokenBucketRefillInterval) {
04260     *msg = tor_strdup("While Tor is running, changing TokenBucketRefill"
04261                       "Interval is not allowed");
04262     return -1;
04263   }
04264 
04265   if (old->DisableIOCP != new_val->DisableIOCP) {
04266     *msg = tor_strdup("While Tor is running, changing DisableIOCP "
04267                       "is not allowed.");
04268     return -1;
04269   }
04270 
04271   if (old->DisableDebuggerAttachment &&
04272       !new_val->DisableDebuggerAttachment) {
04273     *msg = tor_strdup("While Tor is running, disabling "
04274                       "DisableDebuggerAttachment is not allowed.");
04275     return -1;
04276   }
04277 
04278   return 0;
04279 }
04280 
04283 static int
04284 options_transition_affects_workers(const or_options_t *old_options,
04285                                    const or_options_t *new_options)
04286 {
04287   if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
04288       old_options->NumCPUs != new_options->NumCPUs ||
04289       !config_lines_eq(old_options->ORPort, new_options->ORPort) ||
04290       old_options->ServerDNSSearchDomains !=
04291                                        new_options->ServerDNSSearchDomains ||
04292       old_options->_SafeLogging != new_options->_SafeLogging ||
04293       old_options->ClientOnly != new_options->ClientOnly ||
04294       public_server_mode(old_options) != public_server_mode(new_options) ||
04295       !config_lines_eq(old_options->Logs, new_options->Logs) ||
04296       old_options->LogMessageDomains != new_options->LogMessageDomains)
04297     return 1;
04298 
04299   /* Check whether log options match. */
04300 
04301   /* Nothing that changed matters. */
04302   return 0;
04303 }
04304 
04307 static int
04308 options_transition_affects_descriptor(const or_options_t *old_options,
04309                                       const or_options_t *new_options)
04310 {
04311   /* XXX We can be smarter here. If your DirPort isn't being
04312    * published and you just turned it off, no need to republish. Etc. */
04313   if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
04314       !opt_streq(old_options->Nickname,new_options->Nickname) ||
04315       !opt_streq(old_options->Address,new_options->Address) ||
04316       !config_lines_eq(old_options->ExitPolicy,new_options->ExitPolicy) ||
04317       old_options->ExitPolicyRejectPrivate !=
04318         new_options->ExitPolicyRejectPrivate ||
04319       !config_lines_eq(old_options->ORPort, new_options->ORPort) ||
04320       !config_lines_eq(old_options->DirPort, new_options->DirPort) ||
04321       old_options->ClientOnly != new_options->ClientOnly ||
04322       old_options->DisableNetwork != new_options->DisableNetwork ||
04323       old_options->_PublishServerDescriptor !=
04324         new_options->_PublishServerDescriptor ||
04325       get_effective_bwrate(old_options) != get_effective_bwrate(new_options) ||
04326       get_effective_bwburst(old_options) !=
04327         get_effective_bwburst(new_options) ||
04328       !opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
04329       !opt_streq(old_options->MyFamily, new_options->MyFamily) ||
04330       !opt_streq(old_options->AccountingStart, new_options->AccountingStart) ||
04331       old_options->AccountingMax != new_options->AccountingMax ||
04332       public_server_mode(old_options) != public_server_mode(new_options))
04333     return 1;
04334 
04335   return 0;
04336 }
04337 
04338 #ifdef _WIN32
04339 
04341 static char *
04342 get_windows_conf_root(void)
04343 {
04344   static int is_set = 0;
04345   static char path[MAX_PATH*2+1];
04346   TCHAR tpath[MAX_PATH] = {0};
04347 
04348   LPITEMIDLIST idl;
04349   IMalloc *m;
04350   HRESULT result;
04351 
04352   if (is_set)
04353     return path;
04354 
04355   /* Find X:\documents and settings\username\application data\ .
04356    * We would use SHGetSpecialFolder path, but that wasn't added until IE4.
04357    */
04358 #ifdef ENABLE_LOCAL_APPDATA
04359 #define APPDATA_PATH CSIDL_LOCAL_APPDATA
04360 #else
04361 #define APPDATA_PATH CSIDL_APPDATA
04362 #endif
04363   if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, APPDATA_PATH, &idl))) {
04364     getcwd(path,MAX_PATH);
04365     is_set = 1;
04366     log_warn(LD_CONFIG,
04367              "I couldn't find your application data folder: are you "
04368              "running an ancient version of Windows 95? Defaulting to \"%s\"",
04369              path);
04370     return path;
04371   }
04372   /* Convert the path from an "ID List" (whatever that is!) to a path. */
04373   result = SHGetPathFromIDList(idl, tpath);
04374 #ifdef UNICODE
04375   wcstombs(path,tpath,sizeof(path));
04376   path[sizeof(path)-1] = '\0';
04377 #else
04378   strlcpy(path,tpath,sizeof(path));
04379 #endif
04380 
04381   /* Now we need to free the memory that the path-idl was stored in.  In
04382    * typical Windows fashion, we can't just call 'free()' on it. */
04383   SHGetMalloc(&m);
04384   if (m) {
04385     m->lpVtbl->Free(m, idl);
04386     m->lpVtbl->Release(m);
04387   }
04388   if (!SUCCEEDED(result)) {
04389     return NULL;
04390   }
04391   strlcat(path,"\\tor",MAX_PATH);
04392   is_set = 1;
04393   return path;
04394 }
04395 #endif
04396 
04399 static const char *
04400 get_default_conf_file(int defaults_file)
04401 {
04402 #ifdef _WIN32
04403   if (defaults_file) {
04404     static char defaults_path[MAX_PATH+1];
04405     tor_snprintf(defaults_path, MAX_PATH, "%s\\torrc-defaults",
04406                  get_windows_conf_root());
04407     return defaults_path;
04408   } else {
04409     static char path[MAX_PATH+1];
04410     tor_snprintf(path, MAX_PATH, "%s\\torrc",
04411                  get_windows_conf_root());
04412     return path;
04413   }
04414 #else
04415   return defaults_file ? CONFDIR "/torrc-defaults" : CONFDIR "/torrc";
04416 #endif
04417 }
04418 
04422 static int
04423 check_nickname_list(const char *lst, const char *name, char **msg)
04424 {
04425   int r = 0;
04426   smartlist_t *sl;
04427 
04428   if (!lst)
04429     return 0;
04430   sl = smartlist_new();
04431 
04432   smartlist_split_string(sl, lst, ",",
04433     SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);
04434 
04435   SMARTLIST_FOREACH(sl, const char *, s,
04436     {
04437       if (!is_legal_nickname_or_hexdigest(s)) {
04438         tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
04439         r = -1;
04440         break;
04441       }
04442     });
04443   SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
04444   smartlist_free(sl);
04445   return r;
04446 }
04447 
04459 static char *
04460 find_torrc_filename(int argc, char **argv,
04461                     int defaults_file,
04462                     int *using_default_fname, int *ignore_missing_torrc)
04463 {
04464   char *fname=NULL;
04465   int i;
04466   const char *fname_opt = defaults_file ? "--defaults-torrc" : "-f";
04467   const char *ignore_opt = defaults_file ? NULL : "--ignore-missing-torrc";
04468 
04469   if (defaults_file)
04470     *ignore_missing_torrc = 1;
04471 
04472   for (i = 1; i < argc; ++i) {
04473     if (i < argc-1 && !strcmp(argv[i],fname_opt)) {
04474       if (fname) {
04475         log(LOG_WARN, LD_CONFIG, "Duplicate %s options on command line.",
04476             fname_opt);
04477         tor_free(fname);
04478       }
04479       fname = expand_filename(argv[i+1]);
04480 
04481       {
04482         char *absfname;
04483         absfname = make_path_absolute(fname);
04484         tor_free(fname);
04485         fname = absfname;
04486       }
04487 
04488       *using_default_fname = 0;
04489       ++i;
04490     } else if (ignore_opt && !strcmp(argv[i],ignore_opt)) {
04491       *ignore_missing_torrc = 1;
04492     }
04493   }
04494 
04495   if (*using_default_fname) {
04496     /* didn't find one, try CONFDIR */
04497     const char *dflt = get_default_conf_file(defaults_file);
04498     if (dflt && file_status(dflt) == FN_FILE) {
04499       fname = tor_strdup(dflt);
04500     } else {
04501 #ifndef _WIN32
04502       char *fn = NULL;
04503       if (!defaults_file)
04504         fn = expand_filename("~/.torrc");
04505       if (fn && file_status(fn) == FN_FILE) {
04506         fname = fn;
04507       } else {
04508         tor_free(fn);
04509         fname = tor_strdup(dflt);
04510       }
04511 #else
04512       fname = tor_strdup(dflt);
04513 #endif
04514     }
04515   }
04516   return fname;
04517 }
04518 
04526 static char *
04527 load_torrc_from_disk(int argc, char **argv, int defaults_file)
04528 {
04529   char *fname=NULL;
04530   char *cf = NULL;
04531   int using_default_torrc = 1;
04532   int ignore_missing_torrc = 0;
04533   char **fname_var = defaults_file ? &torrc_defaults_fname : &torrc_fname;
04534 
04535   fname = find_torrc_filename(argc, argv, defaults_file,
04536                               &using_default_torrc, &ignore_missing_torrc);
04537   tor_assert(fname);
04538   log(LOG_DEBUG, LD_CONFIG, "Opening config file \"%s\"", fname);
04539 
04540   tor_free(*fname_var);
04541   *fname_var = fname;
04542 
04543   /* Open config file */
04544   if (file_status(fname) != FN_FILE ||
04545       !(cf = read_file_to_str(fname,0,NULL))) {
04546     if (using_default_torrc == 1 || ignore_missing_torrc) {
04547       if (!defaults_file)
04548         log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, "
04549             "using reasonable defaults.", fname);
04550       tor_free(fname); /* sets fname to NULL */
04551       *fname_var = NULL;
04552       cf = tor_strdup("");
04553     } else {
04554       log(LOG_WARN, LD_CONFIG,
04555           "Unable to open configuration file \"%s\".", fname);
04556       goto err;
04557     }
04558   } else {
04559     log(LOG_NOTICE, LD_CONFIG, "Read configuration file \"%s\".", fname);
04560   }
04561 
04562   return cf;
04563  err:
04564   tor_free(fname);
04565   *fname_var = NULL;
04566   return NULL;
04567 }
04568 
04573 int
04574 options_init_from_torrc(int argc, char **argv)
04575 {
04576   char *cf=NULL, *cf_defaults=NULL;
04577   int i, command;
04578   int retval = -1;
04579   static char **backup_argv;
04580   static int backup_argc;
04581   char *command_arg = NULL;
04582   char *errmsg=NULL;
04583 
04584   if (argv) { /* first time we're called. save command line args */
04585     backup_argv = argv;
04586     backup_argc = argc;
04587   } else { /* we're reloading. need to clean up old options first. */
04588     argv = backup_argv;
04589     argc = backup_argc;
04590   }
04591   if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1],"--help"))) {
04592     print_usage();
04593     exit(0);
04594   }
04595   if (argc > 1 && !strcmp(argv[1], "--list-torrc-options")) {
04596     /* For documenting validating whether we've documented everything. */
04597     list_torrc_options();
04598     exit(0);
04599   }
04600 
04601   if (argc > 1 && (!strcmp(argv[1],"--version"))) {
04602     printf("Tor version %s.\n",get_version());
04603     exit(0);
04604   }
04605   if (argc > 1 && (!strcmp(argv[1],"--digests"))) {
04606     printf("Tor version %s.\n",get_version());
04607     printf("%s", libor_get_digests());
04608     printf("%s", tor_get_digests());
04609     exit(0);
04610   }
04611 
04612   /* Go through command-line variables */
04613   if (!global_cmdline_options) {
04614     /* Or we could redo the list every time we pass this place.
04615      * It does not really matter */
04616     if (config_get_commandlines(argc, argv, &global_cmdline_options) < 0) {
04617       goto err;
04618     }
04619   }
04620 
04621   command = CMD_RUN_TOR;
04622   for (i = 1; i < argc; ++i) {
04623     if (!strcmp(argv[i],"--list-fingerprint")) {
04624       command = CMD_LIST_FINGERPRINT;
04625     } else if (!strcmp(argv[i],"--hash-password")) {
04626       command = CMD_HASH_PASSWORD;
04627       command_arg = tor_strdup( (i < argc-1) ? argv[i+1] : "");
04628       ++i;
04629     } else if (!strcmp(argv[i],"--verify-config")) {
04630       command = CMD_VERIFY_CONFIG;
04631     }
04632   }
04633 
04634   if (command == CMD_HASH_PASSWORD) {
04635     cf = tor_strdup("");
04636   } else {
04637     cf_defaults = load_torrc_from_disk(argc, argv, 1);
04638     cf = load_torrc_from_disk(argc, argv, 0);
04639     if (!cf)
04640       goto err;
04641   }
04642 
04643   retval = options_init_from_string(cf_defaults, cf, command, command_arg,
04644                                     &errmsg);
04645 
04646  err:
04647 
04648   tor_free(cf);
04649   tor_free(cf_defaults);
04650   if (errmsg) {
04651     log(LOG_WARN,LD_CONFIG,"%s", errmsg);
04652     tor_free(errmsg);
04653   }
04654   return retval < 0 ? -1 : 0;
04655 }
04656 
04666 setopt_err_t
04667 options_init_from_string(const char *cf_defaults, const char *cf,
04668                          int command, const char *command_arg,
04669                          char **msg)
04670 {
04671   or_options_t *oldoptions, *newoptions, *newdefaultoptions=NULL;
04672   config_line_t *cl;
04673   int retval, i;
04674   setopt_err_t err = SETOPT_ERR_MISC;
04675   tor_assert(msg);
04676 
04677   oldoptions = global_options; /* get_options unfortunately asserts if
04678                                   this is the first time we run*/
04679 
04680   newoptions = tor_malloc_zero(sizeof(or_options_t));
04681   newoptions->_magic = OR_OPTIONS_MAGIC;
04682   options_init(newoptions);
04683   newoptions->command = command;
04684   newoptions->command_arg = command_arg;
04685 
04686   for (i = 0; i < 2; ++i) {
04687     const char *body = i==0 ? cf_defaults : cf;
04688     if (!body)
04689       continue;
04690     /* get config lines, assign them */
04691     retval = config_get_lines(body, &cl, 1);
04692     if (retval < 0) {
04693       err = SETOPT_ERR_PARSE;
04694       goto err;
04695     }
04696     retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
04697     config_free_lines(cl);
04698     if (retval < 0) {
04699       err = SETOPT_ERR_PARSE;
04700       goto err;
04701     }
04702     if (i==0)
04703       newdefaultoptions = options_dup(&options_format, newoptions);
04704   }
04705 
04706   /* Go through command-line variables too */
04707   retval = config_assign(&options_format, newoptions,
04708                          global_cmdline_options, 0, 0, msg);
04709   if (retval < 0) {
04710     err = SETOPT_ERR_PARSE;
04711     goto err;
04712   }
04713 
04714   /* If this is a testing network configuration, change defaults
04715    * for a list of dependent config options, re-initialize newoptions
04716    * with the new defaults, and assign all options to it second time. */
04717   if (newoptions->TestingTorNetwork) {
04718     /* XXXX this is a bit of a kludge.  perhaps there's a better way to do
04719      * this?  We could, for example, make the parsing algorithm do two passes
04720      * over the configuration.  If it finds any "suite" options like
04721      * TestingTorNetwork, it could change the defaults before its second pass.
04722      * Not urgent so long as this seems to work, but at any sign of trouble,
04723      * let's clean it up.  -NM */
04724 
04725     /* Change defaults. */
04726     int i;
04727     for (i = 0; testing_tor_network_defaults[i].name; ++i) {
04728       const config_var_t *new_var = &testing_tor_network_defaults[i];
04729       config_var_t *old_var =
04730           config_find_option_mutable(&options_format, new_var->name);
04731       tor_assert(new_var);
04732       tor_assert(old_var);
04733       old_var->initvalue = new_var->initvalue;
04734     }
04735 
04736     /* Clear newoptions and re-initialize them with new defaults. */
04737     config_free(&options_format, newoptions);
04738     config_free(&options_format, newdefaultoptions);
04739     newdefaultoptions = NULL;
04740     newoptions = tor_malloc_zero(sizeof(or_options_t));
04741     newoptions->_magic = OR_OPTIONS_MAGIC;
04742     options_init(newoptions);
04743     newoptions->command = command;
04744     newoptions->command_arg = command_arg;
04745 
04746     /* Assign all options a second time. */
04747     for (i = 0; i < 2; ++i) {
04748       const char *body = i==0 ? cf_defaults : cf;
04749       if (!body)
04750         continue;
04751       /* get config lines, assign them */
04752       retval = config_get_lines(body, &cl, 1);
04753       if (retval < 0) {
04754         err = SETOPT_ERR_PARSE;
04755         goto err;
04756       }
04757       retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
04758       config_free_lines(cl);
04759       if (retval < 0) {
04760         err = SETOPT_ERR_PARSE;
04761         goto err;
04762       }
04763       if (i==0)
04764         newdefaultoptions = options_dup(&options_format, newoptions);
04765     }
04766     /* Assign command-line variables a second time too */
04767     retval = config_assign(&options_format, newoptions,
04768                            global_cmdline_options, 0, 0, msg);
04769     if (retval < 0) {
04770       err = SETOPT_ERR_PARSE;
04771       goto err;
04772     }
04773   }
04774 
04775   /* Validate newoptions */
04776   if (options_validate(oldoptions, newoptions, 0, msg) < 0) {
04777     err = SETOPT_ERR_PARSE; /*XXX make this a separate return value.*/
04778     goto err;
04779   }
04780 
04781   if (options_transition_allowed(oldoptions, newoptions, msg) < 0) {
04782     err = SETOPT_ERR_TRANSITION;
04783     goto err;
04784   }
04785 
04786   if (set_options(newoptions, msg)) {
04787     err = SETOPT_ERR_SETTING;
04788     goto err; /* frees and replaces old options */
04789   }
04790   config_free(&options_format, global_default_options);
04791   global_default_options = newdefaultoptions;
04792 
04793   return SETOPT_OK;
04794 
04795  err:
04796   config_free(&options_format, newoptions);
04797   config_free(&options_format, newdefaultoptions);
04798   if (*msg) {
04799     char *old_msg = *msg;
04800     tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg);
04801     tor_free(old_msg);
04802   }
04803   return err;
04804 }
04805 
04808 const char *
04809 get_torrc_fname(int defaults_fname)
04810 {
04811   const char *fname = defaults_fname ? torrc_defaults_fname : torrc_fname;
04812 
04813   if (fname)
04814     return fname;
04815   else
04816     return get_default_conf_file(defaults_fname);
04817 }
04818 
04822 void
04823 config_register_addressmaps(const or_options_t *options)
04824 {
04825   smartlist_t *elts;
04826   config_line_t *opt;
04827   char *from, *to;
04828 
04829   addressmap_clear_configured();
04830   elts = smartlist_new();
04831   for (opt = options->AddressMap; opt; opt = opt->next) {
04832     int from_wildcard = 0, to_wildcard = 0;
04833     smartlist_split_string(elts, opt->value, NULL,
04834                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
04835     if (smartlist_len(elts) < 2) {
04836       log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.",
04837                opt->value);
04838       goto cleanup;
04839     }
04840 
04841     from = smartlist_get(elts,0);
04842     to = smartlist_get(elts,1);
04843 
04844     if (to[0] == '.' || from[0] == '.') {
04845       log_warn(LD_CONFIG,"MapAddress '%s' is ambiguous - address starts with a"
04846               "'.'. Ignoring.",opt->value);
04847       goto cleanup;
04848     }
04849 
04850     if (!strcmp(to, "*") || !strcmp(from, "*")) {
04851       log_warn(LD_CONFIG,"MapAddress '%s' is unsupported - can't remap from "
04852                "or to *. Ignoring.",opt->value);
04853       goto cleanup;
04854     }
04855     /* Detect asterisks in expressions of type: '*.example.com' */
04856     if (!strncmp(from,"*.",2)) {
04857       from += 2;
04858       from_wildcard = 1;
04859     }
04860     if (!strncmp(to,"*.",2)) {
04861       to += 2;
04862       to_wildcard = 1;
04863     }
04864 
04865     if (to_wildcard && !from_wildcard) {
04866       log_warn(LD_CONFIG,
04867                 "Skipping invalid argument '%s' to MapAddress: "
04868                 "can only use wildcard (i.e. '*.') if 'from' address "
04869                 "uses wildcard also", opt->value);
04870       goto cleanup;
04871     }
04872 
04873     if (address_is_invalid_destination(to, 1)) {
04874       log_warn(LD_CONFIG,
04875                 "Skipping invalid argument '%s' to MapAddress", opt->value);
04876       goto cleanup;
04877     }
04878 
04879     addressmap_register(from, tor_strdup(to), 0, ADDRMAPSRC_TORRC,
04880                         from_wildcard, to_wildcard);
04881 
04882     if (smartlist_len(elts) > 2)
04883       log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress.");
04884 
04885   cleanup:
04886     SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
04887     smartlist_clear(elts);
04888   }
04889   smartlist_free(elts);
04890 }
04891 
04895 static int
04896 options_init_logs(or_options_t *options, int validate_only)
04897 {
04898   config_line_t *opt;
04899   int ok;
04900   smartlist_t *elts;
04901   int daemon =
04902 #ifdef _WIN32
04903                0;
04904 #else
04905                options->RunAsDaemon;
04906 #endif
04907 
04908   if (options->LogTimeGranularity <= 0) {
04909     log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.",
04910              options->LogTimeGranularity);
04911     return -1;
04912   } else if (1000 % options->LogTimeGranularity != 0 &&
04913              options->LogTimeGranularity % 1000 != 0) {
04914     int granularity = options->LogTimeGranularity;
04915     if (granularity < 40) {
04916       do granularity++;
04917       while (1000 % granularity != 0);
04918     } else if (granularity < 1000) {
04919       granularity = 1000 / granularity;
04920       while (1000 % granularity != 0)
04921         granularity--;
04922       granularity = 1000 / granularity;
04923     } else {
04924       granularity = 1000 * ((granularity / 1000) + 1);
04925     }
04926     log_warn(LD_CONFIG, "Log time granularity '%d' has to be either a "
04927                         "divisor or a multiple of 1 second. Changing to "
04928                         "'%d'.",
04929              options->LogTimeGranularity, granularity);
04930     if (!validate_only)
04931       set_log_time_granularity(granularity);
04932   } else {
04933     if (!validate_only)
04934       set_log_time_granularity(options->LogTimeGranularity);
04935   }
04936 
04937   ok = 1;
04938   elts = smartlist_new();
04939 
04940   for (opt = options->Logs; opt; opt = opt->next) {
04941     log_severity_list_t *severity;
04942     const char *cfg = opt->value;
04943     severity = tor_malloc_zero(sizeof(log_severity_list_t));
04944     if (parse_log_severity_config(&cfg, severity) < 0) {
04945       log_warn(LD_CONFIG, "Couldn't parse log levels in Log option 'Log %s'",
04946                opt->value);
04947       ok = 0; goto cleanup;
04948     }
04949 
04950     smartlist_split_string(elts, cfg, NULL,
04951                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
04952 
04953     if (smartlist_len(elts) == 0)
04954       smartlist_add(elts, tor_strdup("stdout"));
04955 
04956     if (smartlist_len(elts) == 1 &&
04957         (!strcasecmp(smartlist_get(elts,0), "stdout") ||
04958          !strcasecmp(smartlist_get(elts,0), "stderr"))) {
04959       int err = smartlist_len(elts) &&
04960         !strcasecmp(smartlist_get(elts,0), "stderr");
04961       if (!validate_only) {
04962         if (daemon) {
04963           log_warn(LD_CONFIG,
04964                    "Can't log to %s with RunAsDaemon set; skipping stdout",
04965                    err?"stderr":"stdout");
04966         } else {
04967           add_stream_log(severity, err?"<stderr>":"<stdout>",
04968                          fileno(err?stderr:stdout));
04969         }
04970       }
04971       goto cleanup;
04972     }
04973     if (smartlist_len(elts) == 1 &&
04974         !strcasecmp(smartlist_get(elts,0), "syslog")) {
04975 #ifdef HAVE_SYSLOG_H
04976       if (!validate_only) {
04977         add_syslog_log(severity);
04978       }
04979 #else
04980       log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry.");
04981 #endif
04982       goto cleanup;
04983     }
04984 
04985     if (smartlist_len(elts) == 2 &&
04986         !strcasecmp(smartlist_get(elts,0), "file")) {
04987       if (!validate_only) {
04988         char *fname = expand_filename(smartlist_get(elts, 1));
04989         if (add_file_log(severity, fname) < 0) {
04990           log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s",
04991                    opt->value, strerror(errno));
04992           ok = 0;
04993         }
04994         tor_free(fname);
04995       }
04996       goto cleanup;
04997     }
04998 
04999     log_warn(LD_CONFIG, "Bad syntax on file Log option 'Log %s'",
05000              opt->value);
05001     ok = 0; goto cleanup;
05002 
05003   cleanup:
05004     SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
05005     smartlist_clear(elts);
05006     tor_free(severity);
05007   }
05008   smartlist_free(elts);
05009 
05010   if (ok && !validate_only)
05011     logs_set_domain_logging(options->LogMessageDomains);
05012 
05013   return ok?0:-1;
05014 }
05015 
05020 static int
05021 parse_bridge_line(const char *line, int validate_only)
05022 {
05023   smartlist_t *items = NULL;
05024   int r;
05025   char *addrport=NULL, *fingerprint=NULL;
05026   char *transport_name=NULL;
05027   char *field1=NULL;
05028   tor_addr_t addr;
05029   uint16_t port = 0;
05030   char digest[DIGEST_LEN];
05031 
05032   items = smartlist_new();
05033   smartlist_split_string(items, line, NULL,
05034                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
05035   if (smartlist_len(items) < 1) {
05036     log_warn(LD_CONFIG, "Too few arguments to Bridge line.");
05037     goto err;
05038   }
05039 
05040   /* field1 is either a transport name or addrport */
05041   field1 = smartlist_get(items, 0);
05042   smartlist_del_keeporder(items, 0);
05043 
05044   if (!(strstr(field1, ".") || strstr(field1, ":"))) {
05045     /* new-style bridge line */
05046     transport_name = field1;
05047     if (smartlist_len(items) < 1) {
05048       log_warn(LD_CONFIG, "Too few items to Bridge line.");
05049       goto err;
05050     }
05051     addrport = smartlist_get(items, 0);
05052     smartlist_del_keeporder(items, 0);
05053   } else {
05054     addrport = field1;
05055   }
05056 
05057   if (tor_addr_port_lookup(addrport, &addr, &port)<0) {
05058     log_warn(LD_CONFIG, "Error parsing Bridge address '%s'", addrport);
05059     goto err;
05060   }
05061   if (!port) {
05062     log_info(LD_CONFIG,
05063              "Bridge address '%s' has no port; using default port 443.",
05064              addrport);
05065     port = 443;
05066   }
05067 
05068   if (smartlist_len(items)) {
05069     fingerprint = smartlist_join_strings(items, "", 0, NULL);
05070     if (strlen(fingerprint) != HEX_DIGEST_LEN) {
05071       log_warn(LD_CONFIG, "Key digest for Bridge is wrong length.");
05072       goto err;
05073     }
05074     if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) {
05075       log_warn(LD_CONFIG, "Unable to decode Bridge key digest.");
05076       goto err;
05077     }
05078   }
05079 
05080   if (!validate_only) {
05081     log_debug(LD_DIR, "Bridge at %s:%d (transport: %s) (%s)",
05082               fmt_addr(&addr), (int)port,
05083               transport_name ? transport_name : "no transport",
05084               fingerprint ? fingerprint : "no key listed");
05085     bridge_add_from_config(&addr, port,
05086                            fingerprint ? digest : NULL, transport_name);
05087   }
05088 
05089   r = 0;
05090   goto done;
05091 
05092  err:
05093   r = -1;
05094 
05095  done:
05096   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
05097   smartlist_free(items);
05098   tor_free(addrport);
05099   tor_free(transport_name);
05100   tor_free(fingerprint);
05101   return r;
05102 }
05103 
05112 static int
05113 parse_client_transport_line(const char *line, int validate_only)
05114 {
05115   smartlist_t *items = NULL;
05116   int r;
05117   char *field2=NULL;
05118 
05119   const char *transports=NULL;
05120   smartlist_t *transport_list=NULL;
05121   char *addrport=NULL;
05122   tor_addr_t addr;
05123   uint16_t port = 0;
05124   int socks_ver=PROXY_NONE;
05125 
05126   /* managed proxy options */
05127   int is_managed=0;
05128   char **proxy_argv=NULL;
05129   char **tmp=NULL;
05130   int proxy_argc,i;
05131 
05132   int line_length;
05133 
05134   items = smartlist_new();
05135   smartlist_split_string(items, line, NULL,
05136                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
05137 
05138   line_length =  smartlist_len(items);
05139   if (line_length < 3) {
05140     log_warn(LD_CONFIG, "Too few arguments on ClientTransportPlugin line.");
05141     goto err;
05142   }
05143 
05144   /* Get the first line element, split it to commas into
05145      transport_list (in case it's multiple transports) and validate
05146      the transport names. */
05147   transports = smartlist_get(items, 0);
05148   transport_list = smartlist_new();
05149   smartlist_split_string(transport_list, transports, ",",
05150                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
05151   SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) {
05152     if (!string_is_C_identifier(transport_name)) {
05153       log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
05154                transport_name);
05155       goto err;
05156     }
05157   } SMARTLIST_FOREACH_END(transport_name);
05158 
05159   /* field2 is either a SOCKS version or "exec" */
05160   field2 = smartlist_get(items, 1);
05161 
05162   if (!strcmp(field2,"socks4")) {
05163     socks_ver = PROXY_SOCKS4;
05164   } else if (!strcmp(field2,"socks5")) {
05165     socks_ver = PROXY_SOCKS5;
05166   } else if (!strcmp(field2,"exec")) {
05167     is_managed=1;
05168   } else {
05169     log_warn(LD_CONFIG, "Strange ClientTransportPlugin field '%s'.",
05170              field2);
05171     goto err;
05172   }
05173 
05174   if (is_managed) { /* managed */
05175     if (!validate_only) {  /* if we are not just validating, use the
05176                              rest of the line as the argv of the proxy
05177                              to be launched */
05178       proxy_argc = line_length-2;
05179       tor_assert(proxy_argc > 0);
05180       proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1));
05181       tmp = proxy_argv;
05182       for (i=0;i<proxy_argc;i++) { /* store arguments */
05183         *tmp++ = smartlist_get(items, 2);
05184         smartlist_del_keeporder(items, 2);
05185       }
05186       *tmp = NULL; /*terminated with NULL, just like execve() likes it*/
05187 
05188       /* kickstart the thing */
05189       pt_kickstart_client_proxy(transport_list, proxy_argv);
05190     }
05191   } else { /* external */
05192     if (smartlist_len(transport_list) != 1) {
05193       log_warn(LD_CONFIG, "You can't have an external proxy with "
05194                "more than one transports.");
05195       goto err;
05196     }
05197 
05198     addrport = smartlist_get(items, 2);
05199 
05200     if (tor_addr_port_lookup(addrport, &addr, &port)<0) {
05201       log_warn(LD_CONFIG, "Error parsing transport "
05202                "address '%s'", addrport);
05203       goto err;
05204     }
05205     if (!port) {
05206       log_warn(LD_CONFIG,
05207                "Transport address '%s' has no port.", addrport);
05208       goto err;
05209     }
05210 
05211     if (!validate_only) {
05212       transport_add_from_config(&addr, port, smartlist_get(transport_list, 0),
05213                                 socks_ver);
05214 
05215       log_info(LD_DIR, "Transport '%s' found at %s:%d",
05216                transports, fmt_addr(&addr), (int)port);
05217     }
05218   }
05219 
05220   r = 0;
05221   goto done;
05222 
05223  err:
05224   r = -1;
05225 
05226  done:
05227   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
05228   smartlist_free(items);
05229   if (transport_list) {
05230     SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s));
05231     smartlist_free(transport_list);
05232   }
05233 
05234   return r;
05235 }
05236 
05242 static int
05243 parse_server_transport_line(const char *line, int validate_only)
05244 {
05245   smartlist_t *items = NULL;
05246   int r;
05247   const char *transports=NULL;
05248   smartlist_t *transport_list=NULL;
05249   char *type=NULL;
05250   char *addrport=NULL;
05251   tor_addr_t addr;
05252   uint16_t port = 0;
05253 
05254   /* managed proxy options */
05255   int is_managed=0;
05256   char **proxy_argv=NULL;
05257   char **tmp=NULL;
05258   int proxy_argc,i;
05259 
05260   int line_length;
05261 
05262   items = smartlist_new();
05263   smartlist_split_string(items, line, NULL,
05264                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
05265 
05266   line_length =  smartlist_len(items);
05267   if (line_length < 3) {
05268     log_warn(LD_CONFIG, "Too few arguments on ServerTransportPlugin line.");
05269     goto err;
05270   }
05271 
05272   /* Get the first line element, split it to commas into
05273      transport_list (in case it's multiple transports) and validate
05274      the transport names. */
05275   transports = smartlist_get(items, 0);
05276   transport_list = smartlist_new();
05277   smartlist_split_string(transport_list, transports, ",",
05278                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
05279   SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) {
05280     if (!string_is_C_identifier(transport_name)) {
05281       log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
05282                transport_name);
05283       goto err;
05284     }
05285   } SMARTLIST_FOREACH_END(transport_name);
05286 
05287   type = smartlist_get(items, 1);
05288 
05289   if (!strcmp(type, "exec")) {
05290     is_managed=1;
05291   } else if (!strcmp(type, "proxy")) {
05292     is_managed=0;
05293   } else {
05294     log_warn(LD_CONFIG, "Strange ServerTransportPlugin type '%s'", type);
05295     goto err;
05296   }
05297 
05298   if (is_managed) { /* managed */
05299     if (!validate_only) {
05300       proxy_argc = line_length-2;
05301       tor_assert(proxy_argc > 0);
05302       proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1));
05303       tmp = proxy_argv;
05304 
05305       for (i=0;i<proxy_argc;i++) { /* store arguments */
05306         *tmp++ = smartlist_get(items, 2);
05307         smartlist_del_keeporder(items, 2);
05308       }
05309       *tmp = NULL; /*terminated with NULL, just like execve() likes it*/
05310 
05311       /* kickstart the thing */
05312       pt_kickstart_server_proxy(transport_list, proxy_argv);
05313     }
05314   } else { /* external */
05315     if (smartlist_len(transport_list) != 1) {
05316       log_warn(LD_CONFIG, "You can't have an external proxy with "
05317                "more than one transports.");
05318       goto err;
05319     }
05320 
05321     addrport = smartlist_get(items, 2);
05322 
05323     if (tor_addr_port_lookup(addrport, &addr, &port)<0) {
05324       log_warn(LD_CONFIG, "Error parsing transport "
05325                "address '%s'", addrport);
05326       goto err;
05327     }
05328     if (!port) {
05329       log_warn(LD_CONFIG,
05330                "Transport address '%s' has no port.", addrport);
05331       goto err;
05332     }
05333 
05334     if (!validate_only) {
05335       log_info(LD_DIR, "Server transport '%s' at %s:%d.",
05336                transports, fmt_addr(&addr), (int)port);
05337     }
05338   }
05339 
05340   r = 0;
05341   goto done;
05342 
05343  err:
05344   r = -1;
05345 
05346  done:
05347   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
05348   smartlist_free(items);
05349   if (transport_list) {
05350     SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s));
05351     smartlist_free(transport_list);
05352   }
05353 
05354   return r;
05355 }
05356 
05363 static int
05364 parse_dir_server_line(const char *line, dirinfo_type_t required_type,
05365                       int validate_only)
05366 {
05367   smartlist_t *items = NULL;
05368   int r;
05369   char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
05370   uint16_t dir_port = 0, or_port = 0;
05371   char digest[DIGEST_LEN];
05372   char v3_digest[DIGEST_LEN];
05373   dirinfo_type_t type = V2_DIRINFO;
05374   int is_not_hidserv_authority = 0, is_not_v2_authority = 0;
05375 
05376   items = smartlist_new();
05377   smartlist_split_string(items, line, NULL,
05378                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
05379   if (smartlist_len(items) < 1) {
05380     log_warn(LD_CONFIG, "No arguments on DirServer line.");
05381     goto err;
05382   }
05383 
05384   if (is_legal_nickname(smartlist_get(items, 0))) {
05385     nickname = smartlist_get(items, 0);
05386     smartlist_del_keeporder(items, 0);
05387   }
05388 
05389   while (smartlist_len(items)) {
05390     char *flag = smartlist_get(items, 0);
05391     if (TOR_ISDIGIT(flag[0]))
05392       break;
05393     if (!strcasecmp(flag, "v1")) {
05394       type |= (V1_DIRINFO | HIDSERV_DIRINFO);
05395     } else if (!strcasecmp(flag, "hs")) {
05396       type |= HIDSERV_DIRINFO;
05397     } else if (!strcasecmp(flag, "no-hs")) {
05398       is_not_hidserv_authority = 1;
05399     } else if (!strcasecmp(flag, "bridge")) {
05400       type |= BRIDGE_DIRINFO;
05401     } else if (!strcasecmp(flag, "no-v2")) {
05402       is_not_v2_authority = 1;
05403     } else if (!strcasecmpstart(flag, "orport=")) {
05404       int ok;
05405       char *portstring = flag + strlen("orport=");
05406       or_port = (uint16_t) tor_parse_long(portstring, 10, 1, 65535, &ok, NULL);
05407       if (!ok)
05408         log_warn(LD_CONFIG, "Invalid orport '%s' on DirServer line.",
05409                  portstring);
05410     } else if (!strcasecmpstart(flag, "v3ident=")) {
05411       char *idstr = flag + strlen("v3ident=");
05412       if (strlen(idstr) != HEX_DIGEST_LEN ||
05413           base16_decode(v3_digest, DIGEST_LEN, idstr, HEX_DIGEST_LEN)<0) {
05414         log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line",
05415                  flag);
05416       } else {
05417         type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO;
05418       }
05419     } else {
05420       log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
05421                flag);
05422     }
05423     tor_free(flag);
05424     smartlist_del_keeporder(items, 0);
05425   }
05426   if (is_not_hidserv_authority)
05427     type &= ~HIDSERV_DIRINFO;
05428   if (is_not_v2_authority)
05429     type &= ~V2_DIRINFO;
05430 
05431   if (smartlist_len(items) < 2) {
05432     log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
05433     goto err;
05434   }
05435   addrport = smartlist_get(items, 0);
05436   smartlist_del_keeporder(items, 0);
05437   if (addr_port_lookup(LOG_WARN, addrport, &address, NULL, &dir_port)<0) {
05438     log_warn(LD_CONFIG, "Error parsing DirServer address '%s'", addrport);
05439     goto err;
05440   }
05441   if (!dir_port) {
05442     log_warn(LD_CONFIG, "Missing port in DirServer address '%s'",addrport);
05443     goto err;
05444   }
05445 
05446   fingerprint = smartlist_join_strings(items, "", 0, NULL);
05447   if (strlen(fingerprint) != HEX_DIGEST_LEN) {
05448     log_warn(LD_CONFIG, "Key digest for DirServer is wrong length %d.",
05449              (int)strlen(fingerprint));
05450     goto err;
05451   }
05452   if (!strcmp(fingerprint, "E623F7625FBE0C87820F11EC5F6D5377ED816294")) {
05453     /* a known bad fingerprint. refuse to use it. We can remove this
05454      * clause once Tor 0.1.2.17 is obsolete. */
05455     log_warn(LD_CONFIG, "Dangerous dirserver line. To correct, erase your "
05456              "torrc file (%s), or reinstall Tor and use the default torrc.",
05457              get_torrc_fname(0));
05458     goto err;
05459   }
05460   if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) {
05461     log_warn(LD_CONFIG, "Unable to decode DirServer key digest.");
05462     goto err;
05463   }
05464 
05465   if (!validate_only && (!required_type || required_type & type)) {
05466     if (required_type)
05467       type &= required_type; /* pare down what we think of them as an
05468                               * authority for. */
05469     log_debug(LD_DIR, "Trusted %d dirserver at %s:%d (%s)", (int)type,
05470               address, (int)dir_port, (char*)smartlist_get(items,0));
05471     if (!add_trusted_dir_server(nickname, address, dir_port, or_port,
05472                                 digest, v3_digest, type))
05473       goto err;
05474   }
05475 
05476   r = 0;
05477   goto done;
05478 
05479   err:
05480   r = -1;
05481 
05482   done:
05483   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
05484   smartlist_free(items);
05485   tor_free(addrport);
05486   tor_free(address);
05487   tor_free(nickname);
05488   tor_free(fingerprint);
05489   return r;
05490 }
05491 
05493 static void
05494 port_cfg_free(port_cfg_t *port)
05495 {
05496   tor_free(port);
05497 }
05498 
05501 static void
05502 warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname)
05503 {
05504   SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
05505     if (port->is_unix_addr) {
05506       /* Unix sockets aren't accessible over a network. */
05507     } else if (!tor_addr_is_internal(&port->addr, 1)) {
05508       log_warn(LD_CONFIG, "You specified a public address for %sPort. "
05509                "Other people on the Internet might find your computer and "
05510                "use it as an open proxy. Please don't allow this unless you "
05511                "have a good reason.", portname);
05512     } else if (!tor_addr_is_loopback(&port->addr)) {
05513       log_notice(LD_CONFIG, "You configured a non-loopback address for "
05514                  "%sPort. This allows everybody on your local network to use "
05515                  "your machine as a proxy. Make sure this is what you wanted.",
05516                  portname);
05517     }
05518   } SMARTLIST_FOREACH_END(port);
05519 }
05520 
05525 static void
05526 warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid)
05527 {
05528   int warned = 0;
05529   SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) {
05530     if (port->type != CONN_TYPE_CONTROL_LISTENER)
05531       continue;
05532     if (port->is_unix_addr)
05533       continue;
05534     if (!tor_addr_is_loopback(&port->addr)) {
05535       if (forbid) {
05536         if (!warned)
05537           log_warn(LD_CONFIG,
05538                  "You have a ControlPort set to accept "
05539                  "unauthenticated connections from a non-local address.  "
05540                  "This means that programs not running on your computer "
05541                  "can reconfigure your Tor, without even having to guess a "
05542                  "password.  That's so bad that I'm closing your ControlPort "
05543                  "for you.  If you need to control your Tor remotely, try "
05544                  "enabling authentication and using a tool like stunnel or "
05545                  "ssh to encrypt remote access.");
05546         warned = 1;
05547         port_cfg_free(port);
05548         SMARTLIST_DEL_CURRENT(ports, port);
05549       } else {
05550         log_warn(LD_CONFIG, "You have a ControlPort set to accept "
05551                  "connections from a non-local address.  This means that "
05552                  "programs not running on your computer can reconfigure your "
05553                  "Tor.  That's pretty bad, since the controller "
05554                  "protocol isn't encrypted!  Maybe you should just listen on "
05555                  "127.0.0.1 and use a tool like stunnel or ssh to encrypt "
05556                  "remote connections to your control port.");
05557         return; /* No point in checking the rest */
05558       }
05559     }
05560   } SMARTLIST_FOREACH_END(port);
05561 }
05562 
05563 #define CL_PORT_NO_OPTIONS (1u<<0)
05564 #define CL_PORT_WARN_NONLOCAL (1u<<1)
05565 #define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2)
05566 #define CL_PORT_SERVER_OPTIONS (1u<<3)
05567 #define CL_PORT_FORBID_NONLOCAL (1u<<4)
05568 
05604 static int
05605 parse_port_config(smartlist_t *out,
05606                          const config_line_t *ports,
05607                          const config_line_t *listenaddrs,
05608                          const char *portname,
05609                          int listener_type,
05610                          const char *defaultaddr,
05611                          int defaultport,
05612                          unsigned flags)
05613 {
05614   smartlist_t *elts;
05615   int retval = -1;
05616   const unsigned is_control = (listener_type == CONN_TYPE_CONTROL_LISTENER);
05617   const unsigned allow_no_options = flags & CL_PORT_NO_OPTIONS;
05618   const unsigned use_server_options = flags & CL_PORT_SERVER_OPTIONS;
05619   const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL;
05620   const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL;
05621   const unsigned allow_spurious_listenaddr =
05622     flags & CL_PORT_ALLOW_EXTRA_LISTENADDR;
05623 
05624   /* FooListenAddress is deprecated; let's make it work like it used to work,
05625    * though. */
05626   if (listenaddrs) {
05627     int mainport = defaultport;
05628 
05629     if (ports && ports->next) {
05630       log_warn(LD_CONFIG, "%sListenAddress can't be used when there are "
05631                "multiple %sPort lines", portname, portname);
05632       return -1;
05633     } else if (ports) {
05634       if (!strcmp(ports->value, "auto")) {
05635         mainport = CFG_AUTO_PORT;
05636       } else {
05637         int ok;
05638         mainport = (int)tor_parse_long(ports->value, 10, 0, 65535, &ok, NULL);
05639         if (!ok) {
05640           log_warn(LD_CONFIG, "%sListenAddress can only be used with a single "
05641                    "%sPort with value \"auto\" or 1-65535.",
05642                    portname, portname);
05643           return -1;
05644         }
05645       }
05646     }
05647 
05648     if (mainport == 0) {
05649       if (allow_spurious_listenaddr)
05650         return 1;
05651       log_warn(LD_CONFIG, "%sPort must be defined if %sListenAddress is used",
05652                portname, portname);
05653       return -1;
05654     }
05655 
05656     if (use_server_options && out) {
05657       /* Add a no_listen port. */
05658       port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
05659       cfg->type = listener_type;
05660       cfg->port = mainport;
05661       tor_addr_make_unspec(&cfg->addr); /* Server ports default to 0.0.0.0 */
05662       cfg->no_listen = 1;
05663       cfg->ipv4_only = 1;
05664       smartlist_add(out, cfg);
05665     }
05666 
05667     for (; listenaddrs; listenaddrs = listenaddrs->next) {
05668       tor_addr_t addr;
05669       uint16_t port = 0;
05670       if (tor_addr_port_lookup(listenaddrs->value, &addr, &port) < 0) {
05671         log_warn(LD_CONFIG, "Unable to parse %sListenAddress '%s'",
05672                  portname, listenaddrs->value);
05673         return -1;
05674       }
05675       if (out) {
05676         port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
05677         cfg->type = listener_type;
05678         cfg->port = port ? port : mainport;
05679         tor_addr_copy(&cfg->addr, &addr);
05680         cfg->session_group = SESSION_GROUP_UNSET;
05681         cfg->isolation_flags = ISO_DEFAULT;
05682         cfg->no_advertise = 1;
05683         smartlist_add(out, cfg);
05684       }
05685     }
05686 
05687     if (warn_nonlocal && out) {
05688       if (is_control)
05689         warn_nonlocal_controller_ports(out, forbid_nonlocal);
05690       else
05691         warn_nonlocal_client_ports(out, portname);
05692     }
05693     return 0;
05694   } /* end if (listenaddrs) */
05695 
05696   /* No ListenAddress lines. If there's no FooPort, then maybe make a default
05697    * one. */
05698   if (! ports) {
05699     if (defaultport && out) {
05700        port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
05701        cfg->type = listener_type;
05702        cfg->port = defaultport;
05703        tor_addr_parse(&cfg->addr, defaultaddr);
05704        cfg->session_group = SESSION_GROUP_UNSET;
05705        cfg->isolation_flags = ISO_DEFAULT;
05706        smartlist_add(out, cfg);
05707     }
05708     return 0;
05709   }
05710 
05711   /* At last we can actually parse the FooPort lines.  The syntax is:
05712    * [Addr:](Port|auto) [Options].*/
05713   elts = smartlist_new();
05714 
05715   for (; ports; ports = ports->next) {
05716     tor_addr_t addr;
05717     int port;
05718     int sessiongroup = SESSION_GROUP_UNSET;
05719     unsigned isolation = ISO_DEFAULT;
05720 
05721     char *addrport;
05722     uint16_t ptmp=0;
05723     int ok;
05724     int no_listen = 0, no_advertise = 0, all_addrs = 0,
05725       ipv4_only = 0, ipv6_only = 0;
05726 
05727     smartlist_split_string(elts, ports->value, NULL,
05728                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
05729     if (smartlist_len(elts) == 0) {
05730       log_warn(LD_CONFIG, "Invalid %sPort line with no value", portname);
05731       goto err;
05732     }
05733 
05734     if (allow_no_options && smartlist_len(elts) > 1) {
05735       log_warn(LD_CONFIG, "Too many options on %sPort line", portname);
05736       goto err;
05737     }
05738 
05739     /* Now parse the addr/port value */
05740     addrport = smartlist_get(elts, 0);
05741     if (!strcmp(addrport, "auto")) {
05742       port = CFG_AUTO_PORT;
05743       tor_addr_parse(&addr, defaultaddr);
05744     } else if (!strcasecmpend(addrport, ":auto")) {
05745       char *addrtmp = tor_strndup(addrport, strlen(addrport)-5);
05746       port = CFG_AUTO_PORT;
05747       if (tor_addr_port_lookup(addrtmp, &addr, &ptmp)<0 || ptmp) {
05748         log_warn(LD_CONFIG, "Invalid address '%s' for %sPort",
05749                  escaped(addrport), portname);
05750         tor_free(addrtmp);
05751         goto err;
05752       }
05753     } else {
05754       /* Try parsing integer port before address, because, who knows?
05755          "9050" might be a valid address. */
05756       port = (int) tor_parse_long(addrport, 10, 0, 65535, &ok, NULL);
05757       if (ok) {
05758         tor_addr_parse(&addr, defaultaddr);
05759       } else if (tor_addr_port_lookup(addrport, &addr, &ptmp) == 0) {
05760         if (ptmp == 0) {
05761           log_warn(LD_CONFIG, "%sPort line has address but no port", portname);
05762           goto err;
05763         }
05764         port = ptmp;
05765       } else {
05766         log_warn(LD_CONFIG, "Couldn't parse address '%s' for %sPort",
05767                  escaped(addrport), portname);
05768         goto err;
05769       }
05770     }
05771 
05772     /* Now parse the rest of the options, if any. */
05773     if (use_server_options) {
05774       /* This is a server port; parse advertising options */
05775       SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
05776         if (elt_sl_idx == 0)
05777           continue; /* Skip addr:port */
05778 
05779         if (!strcasecmp(elt, "NoAdvertise")) {
05780           no_advertise = 1;
05781         } else if (!strcasecmp(elt, "NoListen")) {
05782           no_listen = 1;
05783 #if 0
05784         /* not implemented yet. */
05785         } else if (!strcasecmp(elt, "AllAddrs")) {
05786 
05787           all_addrs = 1;
05788 #endif
05789         } else if (!strcasecmp(elt, "IPv4Only")) {
05790           ipv4_only = 1;
05791         } else if (!strcasecmp(elt, "IPv6Only")) {
05792           ipv6_only = 1;
05793         } else {
05794           log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
05795                    portname, escaped(elt));
05796         }
05797       } SMARTLIST_FOREACH_END(elt);
05798 
05799       if (no_advertise && no_listen) {
05800         log_warn(LD_CONFIG, "Tried to set both NoListen and NoAdvertise "
05801                  "on %sPort line '%s'",
05802                  portname, escaped(ports->value));
05803         goto err;
05804       }
05805       if (ipv4_only && ipv6_only) {
05806         log_warn(LD_CONFIG, "Tried to set both IPv4Only and IPv6Only "
05807                  "on %sPort line '%s'",
05808                  portname, escaped(ports->value));
05809         goto err;
05810       }
05811       if (ipv4_only && tor_addr_family(&addr) == AF_INET6) {
05812         log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
05813                  portname);
05814         goto err;
05815       }
05816       if (ipv6_only && tor_addr_family(&addr) == AF_INET) {
05817         log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
05818                  portname);
05819         goto err;
05820       }
05821     } else {
05822       /* This is a client port; parse isolation options */
05823       SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
05824         int no = 0, isoflag = 0;
05825         const char *elt_orig = elt;
05826         if (elt_sl_idx == 0)
05827           continue; /* Skip addr:port */
05828         if (!strcasecmpstart(elt, "SessionGroup=")) {
05829           int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
05830                                           10, 0, INT_MAX, &ok, NULL);
05831           if (!ok) {
05832             log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
05833                      portname, escaped(elt));
05834             goto err;
05835           }
05836           if (sessiongroup >= 0) {
05837             log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort",
05838                      portname);
05839             goto err;
05840           }
05841           sessiongroup = group;
05842           continue;
05843         }
05844 
05845         if (!strcasecmpstart(elt, "No")) {
05846           no = 1;
05847           elt += 2;
05848         }
05849         if (!strcasecmpend(elt, "s"))
05850           elt[strlen(elt)-1] = '\0'; /* kill plurals. */
05851 
05852         if (!strcasecmp(elt, "IsolateDestPort")) {
05853           isoflag = ISO_DESTPORT;
05854         } else if (!strcasecmp(elt, "IsolateDestAddr")) {
05855           isoflag = ISO_DESTADDR;
05856         } else if (!strcasecmp(elt, "IsolateSOCKSAuth")) {
05857           isoflag = ISO_SOCKSAUTH;
05858         } else if (!strcasecmp(elt, "IsolateClientProtocol")) {
05859           isoflag = ISO_CLIENTPROTO;
05860         } else if (!strcasecmp(elt, "IsolateClientAddr")) {
05861           isoflag = ISO_CLIENTADDR;
05862         } else {
05863           log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
05864                    portname, escaped(elt_orig));
05865         }
05866 
05867         if (no) {
05868           isolation &= ~isoflag;
05869         } else {
05870           isolation |= isoflag;
05871         }
05872       } SMARTLIST_FOREACH_END(elt);
05873     }
05874 
05875     if (out && port) {
05876       port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
05877       tor_addr_copy(&cfg->addr, &addr);
05878       cfg->port = port;
05879       cfg->type = listener_type;
05880       cfg->isolation_flags = isolation;
05881       cfg->session_group = sessiongroup;
05882       cfg->no_advertise = no_advertise;
05883       cfg->no_listen = no_listen;
05884       cfg->all_addrs = all_addrs;
05885       cfg->ipv4_only = ipv4_only;
05886       cfg->ipv6_only = ipv6_only;
05887 
05888       smartlist_add(out, cfg);
05889     }
05890     SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
05891     smartlist_clear(elts);
05892   }
05893 
05894   if (warn_nonlocal && out) {
05895     if (is_control)
05896       warn_nonlocal_controller_ports(out, forbid_nonlocal);
05897     else
05898       warn_nonlocal_client_ports(out, portname);
05899   }
05900 
05901   retval = 0;
05902  err:
05903   SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
05904   smartlist_free(elts);
05905   return retval;
05906 }
05907 
05911 static int
05912 parse_unix_socket_config(smartlist_t *out, const config_line_t *cfg,
05913                          int listener_type)
05914 {
05915 
05916   if (!out)
05917     return 0;
05918 
05919   for ( ; cfg; cfg = cfg->next) {
05920     size_t len = strlen(cfg->value);
05921     port_cfg_t *port = tor_malloc_zero(sizeof(port_cfg_t) + len + 1);
05922     port->is_unix_addr = 1;
05923     memcpy(port->unix_addr, cfg->value, len+1);
05924     port->type = listener_type;
05925     smartlist_add(out, port);
05926   }
05927 
05928   return 0;
05929 }
05930 
05939 static int
05940 parse_ports(const or_options_t *options, int validate_only,
05941             char **msg, int *n_ports_out)
05942 {
05943   smartlist_t *ports;
05944   int retval = -1;
05945 
05946   ports = smartlist_new();
05947 
05948   *n_ports_out = 0;
05949 
05950   if (parse_port_config(ports,
05951              options->SocksPort, options->SocksListenAddress,
05952              "Socks", CONN_TYPE_AP_LISTENER,
05953              "127.0.0.1", 9050,
05954              CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR) < 0) {
05955     *msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration");
05956     goto err;
05957   }
05958   if (parse_port_config(ports,
05959                                options->DNSPort, options->DNSListenAddress,
05960                                "DNS", CONN_TYPE_AP_DNS_LISTENER,
05961                                "127.0.0.1", 0,
05962                                CL_PORT_WARN_NONLOCAL) < 0) {
05963     *msg = tor_strdup("Invalid DNSPort/DNSListenAddress configuration");
05964     goto err;
05965   }
05966   if (parse_port_config(ports,
05967                                options->TransPort, options->TransListenAddress,
05968                                "Trans", CONN_TYPE_AP_TRANS_LISTENER,
05969                                "127.0.0.1", 0,
05970                                CL_PORT_WARN_NONLOCAL) < 0) {
05971     *msg = tor_strdup("Invalid TransPort/TransListenAddress configuration");
05972     goto err;
05973   }
05974   if (parse_port_config(ports,
05975                                options->NATDPort, options->NATDListenAddress,
05976                                "NATD", CONN_TYPE_AP_NATD_LISTENER,
05977                                "127.0.0.1", 0,
05978                                CL_PORT_WARN_NONLOCAL) < 0) {
05979     *msg = tor_strdup("Invalid NatdPort/NatdListenAddress configuration");
05980     goto err;
05981   }
05982   {
05983     unsigned control_port_flags = CL_PORT_NO_OPTIONS | CL_PORT_WARN_NONLOCAL;
05984     const int any_passwords = (options->HashedControlPassword ||
05985                                options->HashedControlSessionPassword ||
05986                                options->CookieAuthentication);
05987     if (! any_passwords)
05988       control_port_flags |= CL_PORT_FORBID_NONLOCAL;
05989 
05990     if (parse_port_config(ports,
05991                           options->ControlPort, options->ControlListenAddress,
05992                           "Control", CONN_TYPE_CONTROL_LISTENER,
05993                           "127.0.0.1", 0,
05994                           control_port_flags) < 0) {
05995       *msg = tor_strdup("Invalid ControlPort/ControlListenAddress "
05996                         "configuration");
05997       goto err;
05998     }
05999     if (parse_unix_socket_config(ports,
06000                                  options->ControlSocket,
06001                                  CONN_TYPE_CONTROL_LISTENER) < 0) {
06002       *msg = tor_strdup("Invalid ControlSocket configuration");
06003       goto err;
06004     }
06005   }
06006   if (! options->ClientOnly) {
06007     if (parse_port_config(ports,
06008                           options->ORPort, options->ORListenAddress,
06009                           "OR", CONN_TYPE_OR_LISTENER,
06010                           "0.0.0.0", 0,
06011                           CL_PORT_SERVER_OPTIONS) < 0) {
06012       *msg = tor_strdup("Invalid ORPort/ORListenAddress configuration");
06013       goto err;
06014     }
06015     if (parse_port_config(ports,
06016                           options->DirPort, options->DirListenAddress,
06017                           "Dir", CONN_TYPE_DIR_LISTENER,
06018                           "0.0.0.0", 0,
06019                           CL_PORT_SERVER_OPTIONS) < 0) {
06020       *msg = tor_strdup("Invalid DirPort/DirListenAddress configuration");
06021       goto err;
06022     }
06023   }
06024 
06025   if (check_server_ports(ports, options) < 0) {
06026     *msg = tor_strdup("Misconfigured server ports");
06027     goto err;
06028   }
06029 
06030   *n_ports_out = smartlist_len(ports);
06031 
06032   if (!validate_only) {
06033     if (configured_ports) {
06034       SMARTLIST_FOREACH(configured_ports,
06035                         port_cfg_t *, p, port_cfg_free(p));
06036       smartlist_free(configured_ports);
06037     }
06038     configured_ports = ports;
06039     ports = NULL; /* prevent free below. */
06040   }
06041 
06042   retval = 0;
06043  err:
06044   if (ports) {
06045     SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p));
06046     smartlist_free(ports);
06047   }
06048   return retval;
06049 }
06050 
06053 static int
06054 check_server_ports(const smartlist_t *ports,
06055                    const or_options_t *options)
06056 {
06057   int n_orport_advertised = 0;
06058   int n_orport_advertised_ipv4 = 0;
06059   int n_orport_listeners = 0;
06060   int n_dirport_advertised = 0;
06061   int n_dirport_listeners = 0;
06062   int n_low_port = 0;
06063   int r = 0;
06064 
06065   SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
06066     if (port->type == CONN_TYPE_DIR_LISTENER) {
06067       if (! port->no_advertise)
06068         ++n_dirport_advertised;
06069       if (! port->no_listen)
06070         ++n_dirport_listeners;
06071     } else if (port->type == CONN_TYPE_OR_LISTENER) {
06072       if (! port->no_advertise) {
06073         ++n_orport_advertised;
06074         if (tor_addr_family(&port->addr) == AF_INET ||
06075             (tor_addr_family(&port->addr) == AF_UNSPEC && !port->ipv6_only))
06076           ++n_orport_advertised_ipv4;
06077       }
06078       if (! port->no_listen)
06079         ++n_orport_listeners;
06080     } else {
06081       continue;
06082     }
06083 #ifndef _WIN32
06084     if (!port->no_advertise && port->port < 1024)
06085       ++n_low_port;
06086 #endif
06087   } SMARTLIST_FOREACH_END(port);
06088 
06089   if (n_orport_advertised && !n_orport_listeners) {
06090     log_warn(LD_CONFIG, "We are advertising an ORPort, but not actually "
06091              "listening on one.");
06092     r = -1;
06093   }
06094   if (n_dirport_advertised && !n_dirport_listeners) {
06095     log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually "
06096              "listening on one.");
06097     r = -1;
06098   }
06099   if (n_dirport_advertised > 1) {
06100     log_warn(LD_CONFIG, "Can't advertise more than one DirPort.");
06101     r = -1;
06102   }
06103   if (n_orport_advertised && !n_orport_advertised_ipv4 &&
06104       !options->BridgeRelay) {
06105     log_warn(LD_CONFIG, "Configured non-bridge only to listen on an IPv6 "
06106              "address.");
06107     r = -1;
06108   }
06109 
06110   if (n_low_port && options->AccountingMax) {
06111     log(LOG_WARN, LD_CONFIG,
06112           "You have set AccountingMax to use hibernation. You have also "
06113           "chosen a low DirPort or OrPort. This combination can make Tor stop "
06114           "working when it tries to re-attach the port after a period of "
06115           "hibernation. Please choose a different port or turn off "
06116           "hibernation unless you know this combination will work on your "
06117           "platform.");
06118   }
06119 
06120   return r;
06121 }
06122 
06125 const smartlist_t *
06126 get_configured_ports(void)
06127 {
06128   if (!configured_ports)
06129     configured_ports = smartlist_new();
06130   return configured_ports;
06131 }
06132 
06142 char *
06143 get_first_listener_addrport_string(int listener_type)
06144 {
06145   static const char *ipv4_localhost = "127.0.0.1";
06146   static const char *ipv6_localhost = "[::1]";
06147   const char *address;
06148   uint16_t port;
06149   char *string = NULL;
06150 
06151   if (!configured_ports)
06152     return NULL;
06153 
06154   SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
06155     if (cfg->no_listen)
06156       continue;
06157 
06158     if (cfg->type == listener_type &&
06159         tor_addr_family(&cfg->addr) != AF_UNSPEC) {
06160 
06161       /* We found the first listener of the type we are interested in! */
06162 
06163       /* If a listener is listening on INADDR_ANY, assume that it's
06164          also listening on 127.0.0.1, and point the transport proxy
06165          there: */
06166       if (tor_addr_is_null(&cfg->addr))
06167         address = tor_addr_is_v4(&cfg->addr) ? ipv4_localhost : ipv6_localhost;
06168       else
06169         address = fmt_and_decorate_addr(&cfg->addr);
06170 
06171       /* If a listener is configured with port 'auto', we are forced
06172          to iterate all listener connections and find out in which
06173          port it ended up listening: */
06174       if (cfg->port == CFG_AUTO_PORT) {
06175         port = router_get_active_listener_port_by_type(listener_type);
06176         if (!port)
06177           return NULL;
06178       } else {
06179         port = cfg->port;
06180       }
06181 
06182       tor_asprintf(&string, "%s:%u", address, port);
06183 
06184       return string;
06185     }
06186 
06187   } SMARTLIST_FOREACH_END(cfg);
06188 
06189   return NULL;
06190 }
06191 
06194 int
06195 get_first_advertised_port_by_type_af(int listener_type, int address_family)
06196 {
06197   if (!configured_ports)
06198     return 0;
06199   SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
06200     if (cfg->type == listener_type &&
06201         !cfg->no_advertise &&
06202         (tor_addr_family(&cfg->addr) == address_family ||
06203          tor_addr_family(&cfg->addr) == AF_UNSPEC)) {
06204       if (tor_addr_family(&cfg->addr) != AF_UNSPEC ||
06205           (address_family == AF_INET && !cfg->ipv6_only) ||
06206           (address_family == AF_INET6 && !cfg->ipv4_only)) {
06207         return cfg->port;
06208       }
06209     }
06210   } SMARTLIST_FOREACH_END(cfg);
06211   return 0;
06212 }
06213 
06216 static int
06217 normalize_data_directory(or_options_t *options)
06218 {
06219 #ifdef _WIN32
06220   char *p;
06221   if (options->DataDirectory)
06222     return 0; /* all set */
06223   p = tor_malloc(MAX_PATH);
06224   strlcpy(p,get_windows_conf_root(),MAX_PATH);
06225   options->DataDirectory = p;
06226   return 0;
06227 #else
06228   const char *d = options->DataDirectory;
06229   if (!d)
06230     d = "~/.tor";
06231 
06232  if (strncmp(d,"~/",2) == 0) {
06233    char *fn = expand_filename(d);
06234    if (!fn) {
06235      log_warn(LD_CONFIG,"Failed to expand filename \"%s\".", d);
06236      return -1;
06237    }
06238    if (!options->DataDirectory && !strcmp(fn,"/.tor")) {
06239      /* If our homedir is /, we probably don't want to use it. */
06240      /* Default to LOCALSTATEDIR/tor which is probably closer to what we
06241       * want. */
06242      log_warn(LD_CONFIG,
06243               "Default DataDirectory is \"~/.tor\".  This expands to "
06244               "\"%s\", which is probably not what you want.  Using "
06245               "\"%s"PATH_SEPARATOR"tor\" instead", fn, LOCALSTATEDIR);
06246      tor_free(fn);
06247      fn = tor_strdup(LOCALSTATEDIR PATH_SEPARATOR "tor");
06248    }
06249    tor_free(options->DataDirectory);
06250    options->DataDirectory = fn;
06251  }
06252  return 0;
06253 #endif
06254 }
06255 
06258 static int
06259 validate_data_directory(or_options_t *options)
06260 {
06261   if (normalize_data_directory(options) < 0)
06262     return -1;
06263   tor_assert(options->DataDirectory);
06264   if (strlen(options->DataDirectory) > (512-128)) {
06265     log_warn(LD_CONFIG, "DataDirectory is too long.");
06266     return -1;
06267   }
06268   return 0;
06269 }
06270 
06273 #define GENERATED_FILE_PREFIX "# This file was generated by Tor; " \
06274   "if you edit it, comments will not be preserved"
06275 
06277 #define GENERATED_FILE_COMMENT "# The old torrc file was renamed " \
06278   "to torrc.orig.1 or similar, and Tor will ignore it"
06279 
06284 static int
06285 write_configuration_file(const char *fname, const or_options_t *options)
06286 {
06287   char *old_val=NULL, *new_val=NULL, *new_conf=NULL;
06288   int rename_old = 0, r;
06289 
06290   tor_assert(fname);
06291 
06292   switch (file_status(fname)) {
06293     case FN_FILE:
06294       old_val = read_file_to_str(fname, 0, NULL);
06295       if (!old_val || strcmpstart(old_val, GENERATED_FILE_PREFIX)) {
06296         rename_old = 1;
06297       }
06298       tor_free(old_val);
06299       break;
06300     case FN_NOENT:
06301       break;
06302     case FN_ERROR:
06303     case FN_DIR:
06304     default:
06305       log_warn(LD_CONFIG,
06306                "Config file \"%s\" is not a file? Failing.", fname);
06307       return -1;
06308   }
06309 
06310   if (!(new_conf = options_dump(options, 1))) {
06311     log_warn(LD_BUG, "Couldn't get configuration string");
06312     goto err;
06313   }
06314 
06315   tor_asprintf(&new_val, "%s\n%s\n\n%s",
06316                GENERATED_FILE_PREFIX, GENERATED_FILE_COMMENT, new_conf);
06317 
06318   if (rename_old) {
06319     int i = 1;
06320     char *fn_tmp = NULL;
06321     while (1) {
06322       tor_asprintf(&fn_tmp, "%s.orig.%d", fname, i);
06323       if (file_status(fn_tmp) == FN_NOENT)
06324         break;
06325       tor_free(fn_tmp);
06326       ++i;
06327     }
06328     log_notice(LD_CONFIG, "Renaming old configuration file to \"%s\"", fn_tmp);
06329     if (rename(fname, fn_tmp) < 0) {
06330       log_warn(LD_FS,
06331                "Couldn't rename configuration file \"%s\" to \"%s\": %s",
06332                fname, fn_tmp, strerror(errno));
06333       tor_free(fn_tmp);
06334       goto err;
06335     }
06336     tor_free(fn_tmp);
06337   }
06338 
06339   if (write_str_to_file(fname, new_val, 0) < 0)
06340     goto err;
06341 
06342   r = 0;
06343   goto done;
06344  err:
06345   r = -1;
06346  done:
06347   tor_free(new_val);
06348   tor_free(new_conf);
06349   return r;
06350 }
06351 
06356 int
06357 options_save_current(void)
06358 {
06359   /* This fails if we can't write to our configuration file.
06360    *
06361    * If we try falling back to datadirectory or something, we have a better
06362    * chance of saving the configuration, but a better chance of doing
06363    * something the user never expected. */
06364   return write_configuration_file(get_torrc_fname(0), get_options());
06365 }
06366 
06369 struct unit_table_t {
06370   const char *unit; 
06371   uint64_t multiplier; 
06372 };
06373 
06376 static struct unit_table_t memory_units[] = {
06377   { "",          1 },
06378   { "b",         1<< 0 },
06379   { "byte",      1<< 0 },
06380   { "bytes",     1<< 0 },
06381   { "kb",        1<<10 },
06382   { "kbyte",     1<<10 },
06383   { "kbytes",    1<<10 },
06384   { "kilobyte",  1<<10 },
06385   { "kilobytes", 1<<10 },
06386   { "m",         1<<20 },
06387   { "mb",        1<<20 },
06388   { "mbyte",     1<<20 },
06389   { "mbytes",    1<<20 },
06390   { "megabyte",  1<<20 },
06391   { "megabytes", 1<<20 },
06392   { "gb",        1<<30 },
06393   { "gbyte",     1<<30 },
06394   { "gbytes",    1<<30 },
06395   { "gigabyte",  1<<30 },
06396   { "gigabytes", 1<<30 },
06397   { "tb",        U64_LITERAL(1)<<40 },
06398   { "terabyte",  U64_LITERAL(1)<<40 },
06399   { "terabytes", U64_LITERAL(1)<<40 },
06400   { NULL, 0 },
06401 };
06402 
06405 static struct unit_table_t time_units[] = {
06406   { "",         1 },
06407   { "second",   1 },
06408   { "seconds",  1 },
06409   { "minute",   60 },
06410   { "minutes",  60 },
06411   { "hour",     60*60 },
06412   { "hours",    60*60 },
06413   { "day",      24*60*60 },
06414   { "days",     24*60*60 },
06415   { "week",     7*24*60*60 },
06416   { "weeks",    7*24*60*60 },
06417   { NULL, 0 },
06418 };
06419 
06422 static struct unit_table_t time_msec_units[] = {
06423   { "",         1 },
06424   { "msec",     1 },
06425   { "millisecond", 1 },
06426   { "milliseconds", 1 },
06427   { "second",   1000 },
06428   { "seconds",  1000 },
06429   { "minute",   60*1000 },
06430   { "minutes",  60*1000 },
06431   { "hour",     60*60*1000 },
06432   { "hours",    60*60*1000 },
06433   { "day",      24*60*60*1000 },
06434   { "days",     24*60*60*1000 },
06435   { "week",     7*24*60*60*1000 },
06436   { "weeks",    7*24*60*60*1000 },
06437   { NULL, 0 },
06438 };
06439 
06446 static uint64_t
06447 config_parse_units(const char *val, struct unit_table_t *u, int *ok)
06448 {
06449   uint64_t v = 0;
06450   double d = 0;
06451   int use_float = 0;
06452   char *cp;
06453 
06454   tor_assert(ok);
06455 
06456   v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
06457   if (!*ok || (cp && *cp == '.')) {
06458     d = tor_parse_double(val, 0, UINT64_MAX, ok, &cp);
06459     if (!*ok)
06460       goto done;
06461     use_float = 1;
06462   }
06463 
06464   if (!cp) {
06465     *ok = 1;
06466     v = use_float ? DBL_TO_U64(d) :  v;
06467     goto done;
06468   }
06469 
06470   cp = (char*) eat_whitespace(cp);
06471 
06472   for ( ;u->unit;++u) {
06473     if (!strcasecmp(u->unit, cp)) {
06474       if (use_float)
06475         v = u->multiplier * d;
06476       else
06477         v *= u->multiplier;
06478       *ok = 1;
06479       goto done;
06480     }
06481   }
06482   log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
06483   *ok = 0;
06484  done:
06485 
06486   if (*ok)
06487     return v;
06488   else
06489     return 0;
06490 }
06491 
06496 static uint64_t
06497 config_parse_memunit(const char *s, int *ok)
06498 {
06499   uint64_t u = config_parse_units(s, memory_units, ok);
06500   return u;
06501 }
06502 
06507 static int
06508 config_parse_msec_interval(const char *s, int *ok)
06509 {
06510   uint64_t r;
06511   r = config_parse_units(s, time_msec_units, ok);
06512   if (!ok)
06513     return -1;
06514   if (r > INT_MAX) {
06515     log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
06516     *ok = 0;
06517     return -1;
06518   }
06519   return (int)r;
06520 }
06521 
06526 static int
06527 config_parse_interval(const char *s, int *ok)
06528 {
06529   uint64_t r;
06530   r = config_parse_units(s, time_units, ok);
06531   if (!ok)
06532     return -1;
06533   if (r > INT_MAX) {
06534     log_warn(LD_CONFIG, "Interval '%s' is too long", s);
06535     *ok = 0;
06536     return -1;
06537   }
06538   return (int)r;
06539 }
06540 
06543 int
06544 get_num_cpus(const or_options_t *options)
06545 {
06546   if (options->NumCPUs == 0) {
06547     int n = compute_num_cpus();
06548     return (n >= 1) ? n : 1;
06549   } else {
06550     return options->NumCPUs;
06551   }
06552 }
06553 
06557 static void
06558 init_libevent(const or_options_t *options)
06559 {
06560   const char *badness=NULL;
06561   tor_libevent_cfg cfg;
06562 
06563   tor_assert(options);
06564 
06565   configure_libevent_logging();
06566   /* If the kernel complains that some method (say, epoll) doesn't
06567    * exist, we don't care about it, since libevent will cope.
06568    */
06569   suppress_libevent_log_msg("Function not implemented");
06570 
06571   tor_check_libevent_header_compatibility();
06572 
06573   memset(&cfg, 0, sizeof(cfg));
06574   cfg.disable_iocp = options->DisableIOCP;
06575   cfg.num_cpus = get_num_cpus(options);
06576   cfg.msec_per_tick = options->TokenBucketRefillInterval;
06577 
06578   tor_libevent_initialize(&cfg);
06579 
06580   suppress_libevent_log_msg(NULL);
06581 
06582   tor_check_libevent_version(tor_libevent_get_method(),
06583                              get_options()->ORPort != NULL,
06584                              &badness);
06585   if (badness) {
06586     const char *v = tor_libevent_get_version_str();
06587     const char *m = tor_libevent_get_method();
06588     control_event_general_status(LOG_WARN,
06589         "BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO",
06590                                  v, m, badness);
06591   }
06592 }
06593 
06595 or_state_t *
06596 get_or_state(void)
06597 {
06598   tor_assert(global_state);
06599   return global_state;
06600 }
06601 
06616 char *
06617 options_get_datadir_fname2_suffix(const or_options_t *options,
06618                                   const char *sub1, const char *sub2,
06619                                   const char *suffix)
06620 {
06621   char *fname = NULL;
06622   size_t len;
06623   tor_assert(options);
06624   tor_assert(options->DataDirectory);
06625   tor_assert(sub1 || !sub2); /* If sub2 is present, sub1 must be present. */
06626   len = strlen(options->DataDirectory);
06627   if (sub1) {
06628     len += strlen(sub1)+1;
06629     if (sub2)
06630       len += strlen(sub2)+1;
06631   }
06632   if (suffix)
06633     len += strlen(suffix);
06634   len++;
06635   fname = tor_malloc(len);
06636   if (sub1) {
06637     if (sub2) {
06638       tor_snprintf(fname, len, "%s"PATH_SEPARATOR"%s"PATH_SEPARATOR"%s",
06639                    options->DataDirectory, sub1, sub2);
06640     } else {
06641       tor_snprintf(fname, len, "%s"PATH_SEPARATOR"%s",
06642                    options->DataDirectory, sub1);
06643     }
06644   } else {
06645     strlcpy(fname, options->DataDirectory, len);
06646   }
06647   if (suffix)
06648     strlcat(fname, suffix, len);
06649   return fname;
06650 }
06651 
06654 static int
06655 state_transport_line_is_valid(const char *line)
06656 {
06657   smartlist_t *items = NULL;
06658   char *addrport=NULL;
06659   tor_addr_t addr;
06660   uint16_t port = 0;
06661   int r;
06662 
06663   items = smartlist_new();
06664   smartlist_split_string(items, line, NULL,
06665                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
06666 
06667   if (smartlist_len(items) != 2) {
06668     log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line.");
06669     goto err;
06670   }
06671 
06672   addrport = smartlist_get(items, 1);
06673   if (tor_addr_port_lookup(addrport, &addr, &port) < 0) {
06674     log_warn(LD_CONFIG, "state: Could not parse addrport.");
06675     goto err;
06676   }
06677 
06678   if (!port) {
06679     log_warn(LD_CONFIG, "state: Transport line did not contain port.");
06680     goto err;
06681   }
06682 
06683   r = 1;
06684   goto done;
06685 
06686  err:
06687   r = 0;
06688 
06689  done:
06690   SMARTLIST_FOREACH(items, char*, s, tor_free(s));
06691   smartlist_free(items);
06692   return r;
06693 }
06694 
06697 static int
06698 validate_transports_in_state(or_state_t *state)
06699 {
06700   int broken = 0;
06701   config_line_t *line;
06702 
06703   for (line = state->TransportProxies ; line ; line = line->next) {
06704     tor_assert(!strcmp(line->key, "TransportProxy"));
06705     if (!state_transport_line_is_valid(line->value))
06706       broken = 1;
06707   }
06708 
06709   if (broken)
06710     log_warn(LD_CONFIG, "state: State file seems to be broken.");
06711 
06712   return 0;
06713 }
06714 
06720 /* XXX from_setconf is here because of bug 238 */
06721 static int
06722 or_state_validate(or_state_t *old_state, or_state_t *state,
06723                   int from_setconf, char **msg)
06724 {
06725   /* We don't use these; only options do. Still, we need to match that
06726    * signature. */
06727   (void) from_setconf;
06728   (void) old_state;
06729 
06730   if (entry_guards_parse_state(state, 0, msg)<0)
06731     return -1;
06732 
06733   if (validate_transports_in_state(state)<0)
06734     return -1;
06735 
06736   return 0;
06737 }
06738 
06740 static int
06741 or_state_set(or_state_t *new_state)
06742 {
06743   char *err = NULL;
06744   int ret = 0;
06745   tor_assert(new_state);
06746   config_free(&state_format, global_state);
06747   global_state = new_state;
06748   if (entry_guards_parse_state(global_state, 1, &err)<0) {
06749     log_warn(LD_GENERAL,"%s",err);
06750     tor_free(err);
06751     ret = -1;
06752   }
06753   if (rep_hist_load_state(global_state, &err)<0) {
06754     log_warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err);
06755     tor_free(err);
06756     ret = -1;
06757   }
06758   if (circuit_build_times_parse_state(&circ_times, global_state) < 0) {
06759     ret = -1;
06760   }
06761   return ret;
06762 }
06763 
06767 static void
06768 or_state_save_broken(char *fname)
06769 {
06770   int i;
06771   file_status_t status;
06772   char *fname2 = NULL;
06773   for (i = 0; i < 100; ++i) {
06774     tor_asprintf(&fname2, "%s.%d", fname, i);
06775     status = file_status(fname2);
06776     if (status == FN_NOENT)
06777       break;
06778     tor_free(fname2);
06779   }
06780   if (i == 100) {
06781     log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad "
06782              "state files to move aside. Discarding the old state file.",
06783              fname);
06784     unlink(fname);
06785   } else {
06786     log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside "
06787              "to \"%s\".  This could be a bug in Tor; please tell "
06788              "the developers.", fname, fname2);
06789     if (rename(fname, fname2) < 0) {
06790       log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The "
06791                "OS gave an error of %s", strerror(errno));
06792     }
06793   }
06794   tor_free(fname2);
06795 }
06796 
06800 static int
06801 or_state_load(void)
06802 {
06803   or_state_t *new_state = NULL;
06804   char *contents = NULL, *fname;
06805   char *errmsg = NULL;
06806   int r = -1, badstate = 0;
06807 
06808   fname = get_datadir_fname("state");
06809   switch (file_status(fname)) {
06810     case FN_FILE:
06811       if (!(contents = read_file_to_str(fname, 0, NULL))) {
06812         log_warn(LD_FS, "Unable to read state file \"%s\"", fname);
06813         goto done;
06814       }
06815       break;
06816     case FN_NOENT:
06817       break;
06818     case FN_ERROR:
06819     case FN_DIR:
06820     default:
06821       log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname);
06822       goto done;
06823   }
06824   new_state = tor_malloc_zero(sizeof(or_state_t));
06825   new_state->_magic = OR_STATE_MAGIC;
06826   config_init(&state_format, new_state);
06827   if (contents) {
06828     config_line_t *lines=NULL;
06829     int assign_retval;
06830     if (config_get_lines(contents, &lines, 0)<0)
06831       goto done;
06832     assign_retval = config_assign(&state_format, new_state,
06833                                   lines, 0, 0, &errmsg);
06834     config_free_lines(lines);
06835     if (assign_retval<0)
06836       badstate = 1;
06837     if (errmsg) {
06838       log_warn(LD_GENERAL, "%s", errmsg);
06839       tor_free(errmsg);
06840     }
06841   }
06842 
06843   if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0)
06844     badstate = 1;
06845 
06846   if (errmsg) {
06847     log_warn(LD_GENERAL, "%s", errmsg);
06848     tor_free(errmsg);
06849   }
06850 
06851   if (badstate && !contents) {
06852     log_warn(LD_BUG, "Uh oh.  We couldn't even validate our own default state."
06853              " This is a bug in Tor.");
06854     goto done;
06855   } else if (badstate && contents) {
06856     or_state_save_broken(fname);
06857 
06858     tor_free(contents);
06859     config_free(&state_format, new_state);
06860 
06861     new_state = tor_malloc_zero(sizeof(or_state_t));
06862     new_state->_magic = OR_STATE_MAGIC;
06863     config_init(&state_format, new_state);
06864   } else if (contents) {
06865     log_info(LD_GENERAL, "Loaded state from \"%s\"", fname);
06866   } else {
06867     log_info(LD_GENERAL, "Initialized state");
06868   }
06869   if (or_state_set(new_state) == -1) {
06870     or_state_save_broken(fname);
06871   }
06872   new_state = NULL;
06873   if (!contents) {
06874     global_state->next_write = 0;
06875     or_state_save(time(NULL));
06876   }
06877   r = 0;
06878 
06879  done:
06880   tor_free(fname);
06881   tor_free(contents);
06882   if (new_state)
06883     config_free(&state_format, new_state);
06884 
06885   return r;
06886 }
06887 
06891 static int last_state_file_write_failed = 0;
06892 
06894 int
06895 did_last_state_file_write_fail(void)
06896 {
06897   return last_state_file_write_failed;
06898 }
06899 
06901 #define STATE_WRITE_RETRY_INTERVAL 3600
06902 
06906 #define STATE_RELAY_CHECKPOINT_INTERVAL (12*60*60)
06907 
06909 int
06910 or_state_save(time_t now)
06911 {
06912   char *state, *contents;
06913   char tbuf[ISO_TIME_LEN+1];
06914   char *fname;
06915 
06916   tor_assert(global_state);
06917 
06918   if (global_state->next_write > now)
06919     return 0;
06920 
06921   /* Call everything else that might dirty the state even more, in order
06922    * to avoid redundant writes. */
06923   entry_guards_update_state(global_state);
06924   rep_hist_update_state(global_state);
06925   circuit_build_times_update_state(&circ_times, global_state);
06926   if (accounting_is_enabled(get_options()))
06927     accounting_run_housekeeping(now);
06928 
06929   global_state->LastWritten = now;
06930 
06931   tor_free(global_state->TorVersion);
06932   tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
06933 
06934   state = config_dump(&state_format, NULL, global_state, 1, 0);
06935   format_local_iso_time(tbuf, now);
06936   tor_asprintf(&contents,
06937                "# Tor state file last generated on %s local time\n"
06938                "# Other times below are in GMT\n"
06939                "# You *do not* need to edit this file.\n\n%s",
06940                tbuf, state);
06941   tor_free(state);
06942   fname = get_datadir_fname("state");
06943   if (write_str_to_file(fname, contents, 0)<0) {
06944     log_warn(LD_FS, "Unable to write state to file \"%s\"; "
06945              "will try again later", fname);
06946     last_state_file_write_failed = 1;
06947     tor_free(fname);
06948     tor_free(contents);
06949     /* Try again after STATE_WRITE_RETRY_INTERVAL (or sooner, if the state
06950      * changes sooner). */
06951     global_state->next_write = now + STATE_WRITE_RETRY_INTERVAL;
06952     return -1;
06953   }
06954 
06955   last_state_file_write_failed = 0;
06956   log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
06957   tor_free(fname);
06958   tor_free(contents);
06959 
06960   if (server_mode(get_options()))
06961     global_state->next_write = now + STATE_RELAY_CHECKPOINT_INTERVAL;
06962   else
06963     global_state->next_write = TIME_MAX;
06964 
06965   return 0;
06966 }
06967 
06970 static config_line_t *
06971 get_transport_in_state_by_name(const char *transport)
06972 {
06973   or_state_t *or_state = get_or_state();
06974   config_line_t *line;
06975   config_line_t *ret = NULL;
06976   smartlist_t *items = NULL;
06977 
06978   for (line = or_state->TransportProxies ; line ; line = line->next) {
06979     tor_assert(!strcmp(line->key, "TransportProxy"));
06980 
06981     items = smartlist_new();
06982     smartlist_split_string(items, line->value, NULL,
06983                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
06984     if (smartlist_len(items) != 2) /* broken state */
06985       goto done;
06986 
06987     if (!strcmp(smartlist_get(items, 0), transport)) {
06988       ret = line;
06989       goto done;
06990     }
06991 
06992     SMARTLIST_FOREACH(items, char*, s, tor_free(s));
06993     smartlist_free(items);
06994     items = NULL;
06995   }
06996 
06997  done:
06998   if (items) {
06999     SMARTLIST_FOREACH(items, char*, s, tor_free(s));
07000     smartlist_free(items);
07001   }
07002   return ret;
07003 }
07004 
07008 static const char *
07009 get_transport_bindaddr(const char *line, const char *transport)
07010 {
07011   char *line_tmp = NULL;
07012 
07013   if (strlen(line) < strlen(transport) + 2) {
07014     goto broken_state;
07015   } else {
07016     /* line should start with the name of the transport and a space.
07017        (for example, "obfs2 127.0.0.1:47245") */
07018     tor_asprintf(&line_tmp, "%s ", transport);
07019     if (strcmpstart(line, line_tmp))
07020       goto broken_state;
07021 
07022     tor_free(line_tmp);
07023     return (line+strlen(transport)+1);
07024   }
07025 
07026  broken_state:
07027   tor_free(line_tmp);
07028   return NULL;
07029 }
07030 
07034 char *
07035 get_stored_bindaddr_for_server_transport(const char *transport)
07036 {
07037   char *default_addrport = NULL;
07038   const char *stored_bindaddr = NULL;
07039 
07040   config_line_t *line = get_transport_in_state_by_name(transport);
07041   if (!line) /* Found no references in state for this transport. */
07042     goto no_bindaddr_found;
07043 
07044   stored_bindaddr = get_transport_bindaddr(line->value, transport);
07045   if (stored_bindaddr) /* found stored bindaddr in state file. */
07046     return tor_strdup(stored_bindaddr);
07047 
07048  no_bindaddr_found:
07052   tor_asprintf(&default_addrport, "%s:%s", fmt_addr32(INADDR_ANY), "0");
07053   return default_addrport;
07054 }
07055 
07058 void
07059 save_transport_to_state(const char *transport,
07060                         const tor_addr_t *addr, uint16_t port)
07061 {
07062   or_state_t *state = get_or_state();
07063 
07064   char *transport_addrport=NULL;
07065 
07067   config_line_t **next, *line;
07068 
07069   /* see if this transport is already stored in state */
07070   config_line_t *transport_line =
07071     get_transport_in_state_by_name(transport);
07072 
07073   if (transport_line) { /* if transport already exists in state... */
07074     const char *prev_bindaddr = /* get its addrport... */
07075       get_transport_bindaddr(transport_line->value, transport);
07076     tor_asprintf(&transport_addrport, "%s:%d", fmt_addr(addr), (int)port);
07077 
07078     /* if transport in state has the same address as this one, life is good */
07079     if (!strcmp(prev_bindaddr, transport_addrport)) {
07080       log_info(LD_CONFIG, "Transport seems to have spawned on its usual "
07081                "address:port.");
07082       goto done;
07083     } else { /* if addrport in state is different than the one we got */
07084       log_info(LD_CONFIG, "Transport seems to have spawned on different "
07085                "address:port. Let's update the state file with the new "
07086                "address:port");
07087       tor_free(transport_line->value); /* free the old line */
07088       tor_asprintf(&transport_line->value, "%s %s:%d", transport,
07089                    fmt_addr(addr),
07090                    (int) port); /* replace old addrport line with new line */
07091     }
07092   } else { /* never seen this one before; save it in state for next time */
07093     log_info(LD_CONFIG, "It's the first time we see this transport. "
07094              "Let's save its address:port");
07095     next = &state->TransportProxies;
07096     /* find the last TransportProxy line in the state and point 'next'
07097        right after it  */
07098     line = state->TransportProxies;
07099     while (line) {
07100       next = &(line->next);
07101       line = line->next;
07102     }
07103 
07104     /* allocate space for the new line and fill it in */
07105     *next = line = tor_malloc_zero(sizeof(config_line_t));
07106     line->key = tor_strdup("TransportProxy");
07107     tor_asprintf(&line->value, "%s %s:%d", transport,
07108                  fmt_addr(addr), (int) port);
07109 
07110     next = &(line->next);
07111   }
07112 
07113   if (!get_options()->AvoidDiskWrites)
07114     or_state_mark_dirty(state, 0);
07115 
07116  done:
07117   tor_free(transport_addrport);
07118 }
07119 
07122 void
07123 remove_file_if_very_old(const char *fname, time_t now)
07124 {
07125 #define VERY_OLD_FILE_AGE (28*24*60*60)
07126   struct stat st;
07127 
07128   if (stat(fname, &st)==0 && st.st_mtime < now-VERY_OLD_FILE_AGE) {
07129     char buf[ISO_TIME_LEN+1];
07130     format_local_iso_time(buf, st.st_mtime);
07131     log_notice(LD_GENERAL, "Obsolete file %s hasn't been modified since %s. "
07132                "Removing it.", fname, buf);
07133     unlink(fname);
07134   }
07135 }
07136 
07141 int
07142 getinfo_helper_config(control_connection_t *conn,
07143                       const char *question, char **answer,
07144                       const