/src/tor/src/app/config/config.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (c) 2001 Matej Pfajfar. |
2 | | * Copyright (c) 2001-2004, Roger Dingledine. |
3 | | * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. |
4 | | * Copyright (c) 2007-2021, The Tor Project, Inc. */ |
5 | | /* See LICENSE for licensing information */ |
6 | | |
7 | | /** |
8 | | * \file config.c |
9 | | * \brief Code to interpret the user's configuration of Tor. |
10 | | * |
11 | | * This module handles torrc configuration file, including parsing it, |
12 | | * combining it with torrc.defaults and the command line, allowing |
13 | | * user changes to it (via editing and SIGHUP or via the control port), |
14 | | * writing it back to disk (because of SAVECONF from the control port), |
15 | | * and -- most importantly, acting on it. |
16 | | * |
17 | | * The module additionally has some tools for manipulating and |
18 | | * inspecting values that are calculated as a result of the |
19 | | * configured options. |
20 | | * |
21 | | * <h3>How to add new options</h3> |
22 | | * |
23 | | * To add new items to the torrc, there are a minimum of three places to edit: |
24 | | * <ul> |
25 | | * <li>The or_options_t structure in or_options_st.h, where the options are |
26 | | * stored. |
27 | | * <li>The option_vars_ array below in this module, which configures |
28 | | * the names of the torrc options, their types, their multiplicities, |
29 | | * and their mappings to fields in or_options_t. |
30 | | * <li>The manual in doc/man/tor.1.txt, to document what the new option |
31 | | * is, and how it works. |
32 | | * </ul> |
33 | | * |
34 | | * Additionally, you might need to edit these places too: |
35 | | * <ul> |
36 | | * <li>options_validate_cb() below, in case you want to reject some possible |
37 | | * values of the new configuration option. |
38 | | * <li>options_transition_allowed() below, in case you need to |
39 | | * forbid some or all changes in the option while Tor is |
40 | | * running. |
41 | | * <li>options_transition_affects_workers(), in case changes in the option |
42 | | * might require Tor to relaunch or reconfigure its worker threads. |
43 | | * (This function is now in the relay module.) |
44 | | * <li>options_transition_affects_descriptor(), in case changes in the |
45 | | * option might require a Tor relay to build and publish a new server |
46 | | * descriptor. |
47 | | * (This function is now in the relay module.) |
48 | | * <li>options_act() and/or options_act_reversible(), in case there's some |
49 | | * action that needs to be taken immediately based on the option's |
50 | | * value. |
51 | | * </ul> |
52 | | * |
53 | | * <h3>Changing the value of an option</h3> |
54 | | * |
55 | | * Because of the SAVECONF command from the control port, it's a bad |
56 | | * idea to change the value of any user-configured option in the |
57 | | * or_options_t. If you want to sometimes do this anyway, we recommend |
58 | | * that you create a secondary field in or_options_t; that you have the |
59 | | * user option linked only to the secondary field; that you use the |
60 | | * secondary field to initialize the one that Tor actually looks at; and that |
61 | | * you use the one Tor looks as the one that you modify. |
62 | | **/ |
63 | | |
64 | | #define CONFIG_PRIVATE |
65 | | #include "core/or/or.h" |
66 | | #include "app/config/config.h" |
67 | | #include "lib/confmgt/confmgt.h" |
68 | | #include "app/config/statefile.h" |
69 | | #include "app/main/main.h" |
70 | | #include "app/main/subsysmgr.h" |
71 | | #include "core/mainloop/connection.h" |
72 | | #include "core/mainloop/mainloop.h" |
73 | | #include "core/mainloop/netstatus.h" |
74 | | #include "core/or/channel.h" |
75 | | #include "core/or/circuitlist.h" |
76 | | #include "core/or/circuitmux.h" |
77 | | #include "core/or/circuitmux_ewma.h" |
78 | | #include "core/or/circuitstats.h" |
79 | | #include "core/or/connection_edge.h" |
80 | | #include "trunnel/conflux.h" |
81 | | #include "core/or/dos.h" |
82 | | #include "core/or/policies.h" |
83 | | #include "core/or/relay.h" |
84 | | #include "core/or/scheduler.h" |
85 | | #include "feature/client/addressmap.h" |
86 | | #include "feature/client/bridges.h" |
87 | | #include "feature/client/entrynodes.h" |
88 | | #include "feature/client/transports.h" |
89 | | #include "feature/control/control.h" |
90 | | #include "feature/control/control_auth.h" |
91 | | #include "feature/control/control_events.h" |
92 | | #include "feature/dircache/dirserv.h" |
93 | | #include "feature/dirclient/dirclient_modes.h" |
94 | | #include "feature/hibernate/hibernate.h" |
95 | | #include "feature/hs/hs_config.h" |
96 | | #include "feature/hs/hs_pow.h" |
97 | | #include "feature/metrics/metrics.h" |
98 | | #include "feature/nodelist/dirlist.h" |
99 | | #include "feature/nodelist/networkstatus.h" |
100 | | #include "feature/nodelist/nickname.h" |
101 | | #include "feature/nodelist/nodelist.h" |
102 | | #include "feature/nodelist/routerlist.h" |
103 | | #include "feature/nodelist/routerset.h" |
104 | | #include "feature/relay/dns.h" |
105 | | #include "feature/relay/ext_orport.h" |
106 | | #include "feature/relay/routermode.h" |
107 | | #include "feature/relay/relay_config.h" |
108 | | #include "feature/relay/transport_config.h" |
109 | | #include "lib/geoip/geoip.h" |
110 | | #include "feature/stats/geoip_stats.h" |
111 | | #include "lib/compress/compress.h" |
112 | | #include "lib/confmgt/structvar.h" |
113 | | #include "lib/crypt_ops/crypto_init.h" |
114 | | #include "lib/crypt_ops/crypto_rand.h" |
115 | | #include "lib/crypt_ops/crypto_util.h" |
116 | | #include "lib/encoding/confline.h" |
117 | | #include "lib/net/resolve.h" |
118 | | #include "lib/sandbox/sandbox.h" |
119 | | #include "lib/version/torversion.h" |
120 | | |
121 | | #ifdef ENABLE_NSS |
122 | | #include "lib/crypt_ops/crypto_nss_mgt.h" |
123 | | #else |
124 | | #include "lib/crypt_ops/crypto_openssl_mgt.h" |
125 | | #endif |
126 | | |
127 | | #ifdef _WIN32 |
128 | | #include <shlobj.h> |
129 | | #endif |
130 | | #ifdef HAVE_FCNTL_H |
131 | | #include <fcntl.h> |
132 | | #endif |
133 | | #ifdef HAVE_SYS_STAT_H |
134 | | #include <sys/stat.h> |
135 | | #endif |
136 | | #ifdef HAVE_SYS_PARAM_H |
137 | | #include <sys/param.h> |
138 | | #endif |
139 | | #ifdef HAVE_UNISTD_H |
140 | | #include <unistd.h> |
141 | | #endif |
142 | | |
143 | | #include "lib/meminfo/meminfo.h" |
144 | | #include "lib/osinfo/uname.h" |
145 | | #include "lib/osinfo/libc.h" |
146 | | #include "lib/process/daemon.h" |
147 | | #include "lib/process/pidfile.h" |
148 | | #include "lib/process/restrict.h" |
149 | | #include "lib/process/setuid.h" |
150 | | #include "lib/process/process.h" |
151 | | #include "lib/net/gethostname.h" |
152 | | #include "lib/thread/numcpus.h" |
153 | | |
154 | | #include "lib/encoding/keyval.h" |
155 | | #include "lib/fs/conffile.h" |
156 | | #include "lib/evloop/procmon.h" |
157 | | |
158 | | #include "feature/dirauth/authmode.h" |
159 | | #include "feature/dirauth/dirauth_config.h" |
160 | | |
161 | | #include "core/or/connection_st.h" |
162 | | #include "core/or/port_cfg_st.h" |
163 | | |
164 | | #ifdef HAVE_SYSTEMD |
165 | | # if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) |
166 | | /* Systemd's use of gcc's __INCLUDE_LEVEL__ extension macro appears to confuse |
167 | | * Coverity. Here's a kludge to unconfuse it. |
168 | | */ |
169 | | # define __INCLUDE_LEVEL__ 2 |
170 | | #endif /* defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) */ |
171 | | #include <systemd/sd-daemon.h> |
172 | | #endif /* defined(HAVE_SYSTEMD) */ |
173 | | |
174 | | /* Prefix used to indicate a Unix socket in a FooPort configuration. */ |
175 | | static const char unix_socket_prefix[] = "unix:"; |
176 | | /* Prefix used to indicate a Unix socket with spaces in it, in a FooPort |
177 | | * configuration. */ |
178 | | static const char unix_q_socket_prefix[] = "unix:\""; |
179 | | |
180 | | /* limits for TCP send and recv buffer size used for constrained sockets */ |
181 | 0 | #define MIN_CONSTRAINED_TCP_BUFFER 2048 |
182 | 0 | #define MAX_CONSTRAINED_TCP_BUFFER 262144 /* 256k */ |
183 | | |
184 | | /** macro to help with the bulk rename of *DownloadSchedule to |
185 | | * *DownloadInitialDelay . */ |
186 | | #ifndef COCCI |
187 | | #define DOWNLOAD_SCHEDULE(name) \ |
188 | | { (#name "DownloadSchedule"), (#name "DownloadInitialDelay"), 0, 1 } |
189 | | #else |
190 | | #define DOWNLOAD_SCHEDULE(name) { NULL, NULL, 0, 1 } |
191 | | #endif /* !defined(COCCI) */ |
192 | | |
193 | | /** A list of abbreviations and aliases to map command-line options, obsolete |
194 | | * option names, or alternative option names, to their current values. */ |
195 | | static const config_abbrev_t option_abbrevs_[] = { |
196 | | PLURAL(AuthDirBadDirCC), |
197 | | PLURAL(AuthDirBadExitCC), |
198 | | PLURAL(AuthDirInvalidCC), |
199 | | PLURAL(AuthDirMiddleOnlyCC), |
200 | | PLURAL(AuthDirRejectCC), |
201 | | PLURAL(EntryNode), |
202 | | PLURAL(ExcludeNode), |
203 | | PLURAL(FirewallPort), |
204 | | PLURAL(LongLivedPort), |
205 | | PLURAL(HiddenServiceNode), |
206 | | PLURAL(HiddenServiceExcludeNode), |
207 | | PLURAL(NumCPU), |
208 | | PLURAL(RendNode), |
209 | | PLURAL(RecommendedPackage), |
210 | | PLURAL(RendExcludeNode), |
211 | | PLURAL(StrictEntryNode), |
212 | | PLURAL(StrictExitNode), |
213 | | PLURAL(StrictNode), |
214 | | { "l", "Log", 1, 0}, |
215 | | { "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0}, |
216 | | { "AutomapHostSuffixes", "AutomapHostsSuffixes", 0, 0}, |
217 | | { "AutomapHostOnResolve", "AutomapHostsOnResolve", 0, 0}, |
218 | | { "BandwidthRateBytes", "BandwidthRate", 0, 0}, |
219 | | { "BandwidthBurstBytes", "BandwidthBurst", 0, 0}, |
220 | | { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0}, |
221 | | { "DirServer", "DirAuthority", 0, 0}, /* XXXX later, make this warn? */ |
222 | | { "MaxConn", "ConnLimit", 0, 1}, |
223 | | { "MaxMemInCellQueues", "MaxMemInQueues", 0, 0}, |
224 | | { "ORBindAddress", "ORListenAddress", 0, 0}, |
225 | | { "DirBindAddress", "DirListenAddress", 0, 0}, |
226 | | { "SocksBindAddress", "SocksListenAddress", 0, 0}, |
227 | | { "UseHelperNodes", "UseEntryGuards", 0, 0}, |
228 | | { "NumHelperNodes", "NumEntryGuards", 0, 0}, |
229 | | { "UseEntryNodes", "UseEntryGuards", 0, 0}, |
230 | | { "NumEntryNodes", "NumEntryGuards", 0, 0}, |
231 | | { "ResolvConf", "ServerDNSResolvConfFile", 0, 1}, |
232 | | { "SearchDomains", "ServerDNSSearchDomains", 0, 1}, |
233 | | { "ServerDNSAllowBrokenResolvConf", "ServerDNSAllowBrokenConfig", 0, 0}, |
234 | | { "PreferTunnelledDirConns", "PreferTunneledDirConns", 0, 0}, |
235 | | { "BridgeAuthoritativeDirectory", "BridgeAuthoritativeDir", 0, 0}, |
236 | | { "HashedControlPassword", "__HashedControlSessionPassword", 1, 0}, |
237 | | { "VirtualAddrNetwork", "VirtualAddrNetworkIPv4", 0, 0}, |
238 | | { "SocksSocketsGroupWritable", "UnixSocksGroupWritable", 0, 1}, |
239 | | { "_HSLayer2Nodes", "HSLayer2Nodes", 0, 1 }, |
240 | | { "_HSLayer3Nodes", "HSLayer3Nodes", 0, 1 }, |
241 | | |
242 | | DOWNLOAD_SCHEDULE(ClientBootstrapConsensusAuthority), |
243 | | DOWNLOAD_SCHEDULE(ClientBootstrapConsensusAuthorityOnly), |
244 | | DOWNLOAD_SCHEDULE(ClientBootstrapConsensusFallback), |
245 | | DOWNLOAD_SCHEDULE(TestingBridge), |
246 | | DOWNLOAD_SCHEDULE(TestingBridgeBootstrap), |
247 | | DOWNLOAD_SCHEDULE(TestingClient), |
248 | | DOWNLOAD_SCHEDULE(TestingClientConsensus), |
249 | | DOWNLOAD_SCHEDULE(TestingServer), |
250 | | DOWNLOAD_SCHEDULE(TestingServerConsensus), |
251 | | |
252 | | { NULL, NULL, 0, 0}, |
253 | | }; |
254 | | |
255 | | /** dummy instance of or_options_t, used for type-checking its |
256 | | * members with CONF_CHECK_VAR_TYPE. */ |
257 | | DUMMY_TYPECHECK_INSTANCE(or_options_t); |
258 | | |
259 | | /** An entry for config_vars: "The option <b>varname</b> has type |
260 | | * CONFIG_TYPE_<b>conftype</b>, and corresponds to |
261 | | * or_options_t.<b>member</b>" |
262 | | */ |
263 | | #define VAR(varname,conftype,member,initvalue) \ |
264 | | CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, 0, initvalue) |
265 | | |
266 | | /* As VAR, but uses a type definition in addition to a type enum. */ |
267 | | #define VAR_D(varname,conftype,member,initvalue) \ |
268 | | CONFIG_VAR_DEFN(or_options_t, varname, conftype, member, 0, initvalue) |
269 | | |
270 | | #define VAR_NODUMP(varname,conftype,member,initvalue) \ |
271 | | CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ |
272 | | CFLG_NODUMP, initvalue) |
273 | | #define VAR_NODUMP_IMMUTABLE(varname,conftype,member,initvalue) \ |
274 | | CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ |
275 | | CFLG_NODUMP | CFLG_IMMUTABLE, initvalue) |
276 | | #define VAR_INVIS(varname,conftype,member,initvalue) \ |
277 | | CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ |
278 | | CFLG_NODUMP | CFLG_NOSET | CFLG_NOLIST, initvalue) |
279 | | |
280 | | #define V(member,conftype,initvalue) \ |
281 | | VAR(#member, conftype, member, initvalue) |
282 | | |
283 | | #define VAR_IMMUTABLE(varname, conftype, member, initvalue) \ |
284 | | CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ |
285 | | CFLG_IMMUTABLE, initvalue) |
286 | | |
287 | | #define V_IMMUTABLE(member,conftype,initvalue) \ |
288 | | VAR_IMMUTABLE(#member, conftype, member, initvalue) |
289 | | |
290 | | /** As V, but uses a type definition instead of a type enum */ |
291 | | #define V_D(member,type,initvalue) \ |
292 | | VAR_D(#member, type, member, initvalue) |
293 | | |
294 | | /** An entry for config_vars: "The option <b>varname</b> is obsolete." */ |
295 | | #define OBSOLETE(varname) CONFIG_VAR_OBSOLETE(varname) |
296 | | |
297 | | /** |
298 | | * Macro to declare *Port options. Each one comes in three entries. |
299 | | * For example, most users should use "SocksPort" to configure the |
300 | | * socks port, but TorBrowser wants to use __SocksPort so that it |
301 | | * isn't stored by SAVECONF. The SocksPortLines virtual option is |
302 | | * used to query both options from the controller. |
303 | | */ |
304 | | #define VPORT(member) \ |
305 | | VAR(#member "Lines", LINELIST_V, member ## _lines, NULL), \ |
306 | | VAR(#member, LINELIST_S, member ## _lines, NULL), \ |
307 | | VAR_NODUMP("__" #member, LINELIST_S, member ## _lines, NULL) |
308 | | |
309 | | /** UINT64_MAX as a decimal string */ |
310 | | #define UINT64_MAX_STRING "18446744073709551615" |
311 | | |
312 | | /** Array of configuration options. Until we disallow nonstandard |
313 | | * abbreviations, order is significant, since the first matching option will |
314 | | * be chosen first. |
315 | | */ |
316 | | static const config_var_t option_vars_[] = { |
317 | | V(AccountingMax, MEMUNIT, "0 bytes"), |
318 | | VAR("AccountingRule", STRING, AccountingRule_option, "max"), |
319 | | V(AccountingStart, STRING, NULL), |
320 | | V(Address, LINELIST, NULL), |
321 | | V(AddressDisableIPv6, BOOL, "0"), |
322 | | OBSOLETE("AllowDotExit"), |
323 | | OBSOLETE("AllowInvalidNodes"), |
324 | | V(AllowNonRFC953Hostnames, BOOL, "0"), |
325 | | OBSOLETE("AllowSingleHopCircuits"), |
326 | | OBSOLETE("AllowSingleHopExits"), |
327 | | V(AlternateBridgeAuthority, LINELIST, NULL), |
328 | | V(AlternateDirAuthority, LINELIST, NULL), |
329 | | OBSOLETE("AlternateHSAuthority"), |
330 | | V(AssumeReachable, BOOL, "0"), |
331 | | V(AssumeReachableIPv6, AUTOBOOL, "auto"), |
332 | | OBSOLETE("AuthDirBadDir"), |
333 | | OBSOLETE("AuthDirBadDirCCs"), |
334 | | V(AuthDirBadExit, LINELIST, NULL), |
335 | | V(AuthDirBadExitCCs, CSV, ""), |
336 | | V(AuthDirInvalid, LINELIST, NULL), |
337 | | V(AuthDirInvalidCCs, CSV, ""), |
338 | | V(AuthDirMiddleOnly, LINELIST, NULL), |
339 | | V(AuthDirMiddleOnlyCCs, CSV, ""), |
340 | | V(AuthDirReject, LINELIST, NULL), |
341 | | V(AuthDirRejectCCs, CSV, ""), |
342 | | OBSOLETE("AuthDirRejectUnlisted"), |
343 | | OBSOLETE("AuthDirListBadDirs"), |
344 | | OBSOLETE("AuthDirMaxServersPerAuthAddr"), |
345 | | VAR("AuthoritativeDirectory", BOOL, AuthoritativeDir, "0"), |
346 | | V(AutomapHostsOnResolve, BOOL, "0"), |
347 | | V(AutomapHostsSuffixes, CSV, ".onion,.exit"), |
348 | | V(AvoidDiskWrites, BOOL, "0"), |
349 | | V(BandwidthBurst, MEMUNIT, "1 GB"), |
350 | | V(BandwidthRate, MEMUNIT, "1 GB"), |
351 | | V(BridgeAuthoritativeDir, BOOL, "0"), |
352 | | VAR("Bridge", LINELIST, Bridges, NULL), |
353 | | V(BridgePassword, STRING, NULL), |
354 | | V(BridgeRecordUsageByCountry, BOOL, "1"), |
355 | | V(BridgeRelay, BOOL, "0"), |
356 | | V(BridgeDistribution, STRING, NULL), |
357 | | VAR_IMMUTABLE("CacheDirectory",FILENAME, CacheDirectory_option, NULL), |
358 | | V(CacheDirectoryGroupReadable, AUTOBOOL, "auto"), |
359 | | V(CellStatistics, BOOL, "0"), |
360 | | V(PaddingStatistics, BOOL, "1"), |
361 | | V(OverloadStatistics, BOOL, "1"), |
362 | | V(LearnCircuitBuildTimeout, BOOL, "1"), |
363 | | V(CircuitBuildTimeout, INTERVAL, "0"), |
364 | | OBSOLETE("CircuitIdleTimeout"), |
365 | | V(CircuitsAvailableTimeout, INTERVAL, "0"), |
366 | | V(CircuitStreamTimeout, INTERVAL, "0"), |
367 | | V(CircuitPriorityHalflife, DOUBLE, "-1.0"), /*negative:'Use default'*/ |
368 | | V(ClientDNSRejectInternalAddresses, BOOL,"1"), |
369 | | #if defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) |
370 | | /* The unit tests expect the ClientOnly default to be 0. */ |
371 | | V(ClientOnly, BOOL, "0"), |
372 | | #else |
373 | | /* We must be a Client if the relay module is disabled. */ |
374 | | V(ClientOnly, BOOL, "1"), |
375 | | #endif /* defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) */ |
376 | | V(ClientPreferIPv6ORPort, AUTOBOOL, "auto"), |
377 | | V(ClientPreferIPv6DirPort, AUTOBOOL, "auto"), |
378 | | OBSOLETE("ClientAutoIPv6ORPort"), |
379 | | V(ClientRejectInternalAddresses, BOOL, "1"), |
380 | | V(ClientTransportPlugin, LINELIST, NULL), |
381 | | V(ClientUseIPv6, BOOL, "1"), |
382 | | V(ClientUseIPv4, BOOL, "1"), |
383 | | V(CompiledProofOfWorkHash, AUTOBOOL, "auto"), |
384 | | V(ConfluxEnabled, AUTOBOOL, "auto"), |
385 | | VAR("ConfluxClientUX", STRING, ConfluxClientUX_option, |
386 | | "throughput"), |
387 | | V(ConnLimit, POSINT, "1000"), |
388 | | V(ConnDirectionStatistics, BOOL, "0"), |
389 | | V(ConstrainedSockets, BOOL, "0"), |
390 | | V(ConstrainedSockSize, MEMUNIT, "8192"), |
391 | | V(ContactInfo, STRING, NULL), |
392 | | OBSOLETE("ControlListenAddress"), |
393 | | VPORT(ControlPort), |
394 | | V(ControlPortFileGroupReadable,BOOL, "0"), |
395 | | V(ControlPortWriteToFile, FILENAME, NULL), |
396 | | V(ControlSocket, LINELIST, NULL), |
397 | | V(ControlSocketsGroupWritable, BOOL, "0"), |
398 | | V(UnixSocksGroupWritable, BOOL, "0"), |
399 | | V(CookieAuthentication, BOOL, "0"), |
400 | | V(CookieAuthFileGroupReadable, BOOL, "0"), |
401 | | V(CookieAuthFile, FILENAME, NULL), |
402 | | V(CountPrivateBandwidth, BOOL, "0"), |
403 | | VAR_IMMUTABLE("DataDirectory", FILENAME, DataDirectory_option, NULL), |
404 | | V(DataDirectoryGroupReadable, BOOL, "0"), |
405 | | V(DisableOOSCheck, BOOL, "1"), |
406 | | V(DisableNetwork, BOOL, "0"), |
407 | | V(DirAllowPrivateAddresses, BOOL, "0"), |
408 | | OBSOLETE("DirListenAddress"), |
409 | | V(DirPolicy, LINELIST, NULL), |
410 | | VPORT(DirPort), |
411 | | V(DirPortFrontPage, FILENAME, NULL), |
412 | | VAR("DirReqStatistics", BOOL, DirReqStatistics_option, "1"), |
413 | | VAR("DirAuthority", LINELIST, DirAuthorities, NULL), |
414 | | #if defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) |
415 | | /* The unit tests expect the DirCache default to be 1. */ |
416 | | V(DirCache, BOOL, "1"), |
417 | | #else |
418 | | /* We can't be a DirCache if the relay module is disabled. */ |
419 | | V(DirCache, BOOL, "0"), |
420 | | #endif /* defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) */ |
421 | | /* A DirAuthorityFallbackRate of 0.1 means that 0.5% of clients try an |
422 | | * authority when all fallbacks are up, and 2% try an authority when 25% of |
423 | | * fallbacks are down. (We rebuild the list when 25% of fallbacks are down). |
424 | | * |
425 | | * We want to reduce load on authorities, but keep these two figures within |
426 | | * an order of magnitude, so there isn't too much load shifting to |
427 | | * authorities when fallbacks go down. */ |
428 | | V(DirAuthorityFallbackRate, DOUBLE, "0.1"), |
429 | | V_IMMUTABLE(DisableAllSwap, BOOL, "0"), |
430 | | V_IMMUTABLE(DisableDebuggerAttachment, BOOL, "1"), |
431 | | OBSOLETE("DisableIOCP"), |
432 | | OBSOLETE("DisableV2DirectoryInfo_"), |
433 | | OBSOLETE("DynamicDHGroups"), |
434 | | VPORT(DNSPort), |
435 | | OBSOLETE("DNSListenAddress"), |
436 | | V(DormantClientTimeout, INTERVAL, "24 hours"), |
437 | | V(DormantTimeoutEnabled, BOOL, "1"), |
438 | | V(DormantTimeoutDisabledByIdleStreams, BOOL, "1"), |
439 | | V(DormantOnFirstStartup, BOOL, "0"), |
440 | | V(DormantCanceledByStartup, BOOL, "0"), |
441 | | V(DownloadExtraInfo, BOOL, "0"), |
442 | | V(TestingEnableConnBwEvent, BOOL, "0"), |
443 | | V(TestingEnableCellStatsEvent, BOOL, "0"), |
444 | | OBSOLETE("TestingEnableTbEmptyEvent"), |
445 | | V(EnforceDistinctSubnets, BOOL, "1"), |
446 | | V_D(EntryNodes, ROUTERSET, NULL), |
447 | | V(EntryStatistics, BOOL, "0"), |
448 | | OBSOLETE("TestingEstimatedDescriptorPropagationTime"), |
449 | | V_D(ExcludeNodes, ROUTERSET, NULL), |
450 | | V_D(ExcludeExitNodes, ROUTERSET, NULL), |
451 | | OBSOLETE("ExcludeSingleHopRelays"), |
452 | | V_D(ExitNodes, ROUTERSET, NULL), |
453 | | /* Researchers need a way to tell their clients to use specific |
454 | | * middles that they also control, to allow safe live-network |
455 | | * experimentation with new padding machines. */ |
456 | | V_D(MiddleNodes, ROUTERSET, NULL), |
457 | | V(ExitPolicy, LINELIST, NULL), |
458 | | V(ExitPolicyRejectPrivate, BOOL, "1"), |
459 | | V(ExitPolicyRejectLocalInterfaces, BOOL, "0"), |
460 | | V(ExitPortStatistics, BOOL, "0"), |
461 | | V(ExtendAllowPrivateAddresses, BOOL, "0"), |
462 | | V(ExitRelay, AUTOBOOL, "auto"), |
463 | | VPORT(ExtORPort), |
464 | | V(ExtORPortCookieAuthFile, FILENAME, NULL), |
465 | | V(ExtORPortCookieAuthFileGroupReadable, BOOL, "0"), |
466 | | V(ExtraInfoStatistics, BOOL, "1"), |
467 | | V(ExtendByEd25519ID, AUTOBOOL, "auto"), |
468 | | V(FallbackDir, LINELIST, NULL), |
469 | | |
470 | | V(UseDefaultFallbackDirs, BOOL, "1"), |
471 | | |
472 | | OBSOLETE("FallbackNetworkstatusFile"), |
473 | | V(FascistFirewall, BOOL, "0"), |
474 | | V(FirewallPorts, CSV, ""), |
475 | | OBSOLETE("FastFirstHopPK"), |
476 | | V(FetchDirInfoEarly, BOOL, "0"), |
477 | | V(FetchDirInfoExtraEarly, BOOL, "0"), |
478 | | V(FetchServerDescriptors, BOOL, "1"), |
479 | | V(FetchHidServDescriptors, BOOL, "1"), |
480 | | V(FetchUselessDescriptors, BOOL, "0"), |
481 | | OBSOLETE("FetchV2Networkstatus"), |
482 | | V(GeoIPExcludeUnknown, AUTOBOOL, "auto"), |
483 | | #ifdef _WIN32 |
484 | | V(GeoIPFile, FILENAME, "<default>"), |
485 | | V(GeoIPv6File, FILENAME, "<default>"), |
486 | | #elif defined(__ANDROID__) |
487 | | /* Android apps use paths that are configured at runtime. |
488 | | * /data/local/tmp is guaranteed to exist, but will only be |
489 | | * usable by the 'shell' and 'root' users, so this fallback is |
490 | | * for debugging only. */ |
491 | | V(GeoIPFile, FILENAME, "/data/local/tmp/geoip"), |
492 | | V(GeoIPv6File, FILENAME, "/data/local/tmp/geoip6"), |
493 | | #else |
494 | | V(GeoIPFile, FILENAME, |
495 | | SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"), |
496 | | V(GeoIPv6File, FILENAME, |
497 | | SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"), |
498 | | #endif /* defined(_WIN32) */ |
499 | | OBSOLETE("Group"), |
500 | | V(GuardLifetime, INTERVAL, "0 minutes"), |
501 | | V(HeartbeatPeriod, INTERVAL, "6 hours"), |
502 | | V(MainloopStats, BOOL, "0"), |
503 | | V(HashedControlPassword, LINELIST, NULL), |
504 | | OBSOLETE("HidServDirectoryV2"), |
505 | | OBSOLETE("HiddenServiceAuthorizeClient"), |
506 | | OBSOLETE("HidServAuth"), |
507 | | VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), |
508 | | VAR("HiddenServiceDirGroupReadable", LINELIST_S, RendConfigLines, NULL), |
509 | | VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL), |
510 | | VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL), |
511 | | VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines, NULL), |
512 | | VAR("HiddenServiceAllowUnknownPorts",LINELIST_S, RendConfigLines, NULL), |
513 | | VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL), |
514 | | VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL), |
515 | | VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL), |
516 | | VAR("HiddenServiceExportCircuitID", LINELIST_S, RendConfigLines, NULL), |
517 | | VAR("HiddenServiceEnableIntroDoSDefense", LINELIST_S, RendConfigLines, NULL), |
518 | | VAR("HiddenServiceEnableIntroDoSRatePerSec", |
519 | | LINELIST_S, RendConfigLines, NULL), |
520 | | VAR("HiddenServiceEnableIntroDoSBurstPerSec", |
521 | | LINELIST_S, RendConfigLines, NULL), |
522 | | VAR("HiddenServiceOnionBalanceInstance", |
523 | | LINELIST_S, RendConfigLines, NULL), |
524 | | VAR("HiddenServicePoWDefensesEnabled", LINELIST_S, RendConfigLines, NULL), |
525 | | VAR("HiddenServicePoWQueueRate", LINELIST_S, RendConfigLines, NULL), |
526 | | VAR("HiddenServicePoWQueueBurst", LINELIST_S, RendConfigLines, NULL), |
527 | | VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"), |
528 | | V(ClientOnionAuthDir, FILENAME, NULL), |
529 | | OBSOLETE("CloseHSClientCircuitsImmediatelyOnTimeout"), |
530 | | OBSOLETE("CloseHSServiceRendCircuitsImmediatelyOnTimeout"), |
531 | | V_IMMUTABLE(HiddenServiceSingleHopMode, BOOL, "0"), |
532 | | V_IMMUTABLE(HiddenServiceNonAnonymousMode,BOOL, "0"), |
533 | | V(HTTPProxy, STRING, NULL), |
534 | | V(HTTPProxyAuthenticator, STRING, NULL), |
535 | | V(HTTPSProxy, STRING, NULL), |
536 | | V(HTTPSProxyAuthenticator, STRING, NULL), |
537 | | VPORT(HTTPTunnelPort), |
538 | | V(IPv6Exit, BOOL, "0"), |
539 | | VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL), |
540 | | V(ServerTransportListenAddr, LINELIST, NULL), |
541 | | V(ServerTransportOptions, LINELIST, NULL), |
542 | | V(SigningKeyLifetime, INTERVAL, "30 days"), |
543 | | V(Socks4Proxy, STRING, NULL), |
544 | | V(Socks5Proxy, STRING, NULL), |
545 | | V(Socks5ProxyUsername, STRING, NULL), |
546 | | V(Socks5ProxyPassword, STRING, NULL), |
547 | | V(TCPProxy, STRING, NULL), |
548 | | VAR_IMMUTABLE("KeyDirectory", FILENAME, KeyDirectory_option, NULL), |
549 | | V(KeyDirectoryGroupReadable, AUTOBOOL, "auto"), |
550 | | VAR_D("HSLayer2Nodes", ROUTERSET, HSLayer2Nodes, NULL), |
551 | | VAR_D("HSLayer3Nodes", ROUTERSET, HSLayer3Nodes, NULL), |
552 | | V(KeepalivePeriod, INTERVAL, "5 minutes"), |
553 | | V_IMMUTABLE(KeepBindCapabilities, AUTOBOOL, "auto"), |
554 | | VAR("Log", LINELIST, Logs, NULL), |
555 | | V(LogMessageDomains, BOOL, "0"), |
556 | | V(LogTimeGranularity, MSEC_INTERVAL, "1 second"), |
557 | | V(TruncateLogFile, BOOL, "0"), |
558 | | V_IMMUTABLE(SyslogIdentityTag, STRING, NULL), |
559 | | OBSOLETE("AndroidIdentityTag"), |
560 | | V(LongLivedPorts, CSV, |
561 | | "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"), |
562 | | VAR("MapAddress", LINELIST, AddressMap, NULL), |
563 | | V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"), |
564 | | V(MaxCircuitDirtiness, INTERVAL, "10 minutes"), |
565 | | V(MaxClientCircuitsPending, POSINT, "32"), |
566 | | V(MaxConsensusAgeForDiffs, INTERVAL, "0 seconds"), |
567 | | VAR("MaxMemInQueues", MEMUNIT, MaxMemInQueues_raw, "0"), |
568 | | OBSOLETE("MaxOnionsPending"), |
569 | | V(MaxOnionQueueDelay, MSEC_INTERVAL, "0"), |
570 | | V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"), |
571 | | VPORT(MetricsPort), |
572 | | V(MetricsPortPolicy, LINELIST, NULL), |
573 | | V(TestingMinTimeToReportBandwidth, INTERVAL, "1 day"), |
574 | | VAR("MyFamily", LINELIST, MyFamily_lines, NULL), |
575 | | V(NewCircuitPeriod, INTERVAL, "30 seconds"), |
576 | | OBSOLETE("NamingAuthoritativeDirectory"), |
577 | | OBSOLETE("NATDListenAddress"), |
578 | | VPORT(NATDPort), |
579 | | V(Nickname, STRING, NULL), |
580 | | OBSOLETE("PredictedPortsRelevanceTime"), |
581 | | OBSOLETE("WarnUnsafeSocks"), |
582 | | VAR("NodeFamily", LINELIST, NodeFamilies, NULL), |
583 | | V_IMMUTABLE(NoExec, BOOL, "0"), |
584 | | V(NumCPUs, POSINT, "0"), |
585 | | V(NumDirectoryGuards, POSINT, "0"), |
586 | | V(NumEntryGuards, POSINT, "0"), |
587 | | V(NumPrimaryGuards, POSINT, "0"), |
588 | | V(OfflineMasterKey, BOOL, "0"), |
589 | | OBSOLETE("ORListenAddress"), |
590 | | VPORT(ORPort), |
591 | | V(OutboundBindAddress, LINELIST, NULL), |
592 | | V(OutboundBindAddressOR, LINELIST, NULL), |
593 | | V(OutboundBindAddressExit, LINELIST, NULL), |
594 | | V(OutboundBindAddressPT, LINELIST, NULL), |
595 | | |
596 | | OBSOLETE("PathBiasDisableRate"), |
597 | | V(PathBiasCircThreshold, INT, "-1"), |
598 | | V(PathBiasNoticeRate, DOUBLE, "-1"), |
599 | | V(PathBiasWarnRate, DOUBLE, "-1"), |
600 | | V(PathBiasExtremeRate, DOUBLE, "-1"), |
601 | | V(PathBiasScaleThreshold, INT, "-1"), |
602 | | OBSOLETE("PathBiasScaleFactor"), |
603 | | OBSOLETE("PathBiasMultFactor"), |
604 | | V(PathBiasDropGuards, AUTOBOOL, "0"), |
605 | | OBSOLETE("PathBiasUseCloseCounts"), |
606 | | |
607 | | V(PathBiasUseThreshold, INT, "-1"), |
608 | | V(PathBiasNoticeUseRate, DOUBLE, "-1"), |
609 | | V(PathBiasExtremeUseRate, DOUBLE, "-1"), |
610 | | V(PathBiasScaleUseThreshold, INT, "-1"), |
611 | | |
612 | | V(PathsNeededToBuildCircuits, DOUBLE, "-1"), |
613 | | V(PerConnBWBurst, MEMUNIT, "0"), |
614 | | V(PerConnBWRate, MEMUNIT, "0"), |
615 | | V_IMMUTABLE(PidFile, FILENAME, NULL), |
616 | | V_IMMUTABLE(TestingTorNetwork, BOOL, "0"), |
617 | | |
618 | | V(TestingLinkCertLifetime, INTERVAL, "2 days"), |
619 | | V(TestingAuthKeyLifetime, INTERVAL, "2 days"), |
620 | | V(TestingLinkKeySlop, INTERVAL, "3 hours"), |
621 | | V(TestingAuthKeySlop, INTERVAL, "3 hours"), |
622 | | V(TestingSigningKeySlop, INTERVAL, "1 day"), |
623 | | |
624 | | OBSOLETE("OptimisticData"), |
625 | | OBSOLETE("PortForwarding"), |
626 | | OBSOLETE("PortForwardingHelper"), |
627 | | OBSOLETE("PreferTunneledDirConns"), |
628 | | V(ProtocolWarnings, BOOL, "0"), |
629 | | V(PublishServerDescriptor, CSV, "1"), |
630 | | V(PublishHidServDescriptors, BOOL, "1"), |
631 | | V(ReachableAddresses, LINELIST, NULL), |
632 | | V(ReachableDirAddresses, LINELIST, NULL), |
633 | | V(ReachableORAddresses, LINELIST, NULL), |
634 | | OBSOLETE("RecommendedPackages"), |
635 | | V(ReducedConnectionPadding, BOOL, "0"), |
636 | | V(ConnectionPadding, AUTOBOOL, "auto"), |
637 | | V(RefuseUnknownExits, AUTOBOOL, "auto"), |
638 | | V(CircuitPadding, BOOL, "1"), |
639 | | V(ReconfigDropsBridgeDescs, BOOL, "0"), |
640 | | V(ReducedCircuitPadding, BOOL, "0"), |
641 | | V(RejectPlaintextPorts, CSV, ""), |
642 | | V(RelayBandwidthBurst, MEMUNIT, "0"), |
643 | | V(RelayBandwidthRate, MEMUNIT, "0"), |
644 | | V(RephistTrackTime, INTERVAL, "24 hours"), |
645 | | V_IMMUTABLE(RunAsDaemon, BOOL, "0"), |
646 | | V(ReducedExitPolicy, BOOL, "0"), |
647 | | V(ReevaluateExitPolicy, BOOL, "0"), |
648 | | OBSOLETE("RunTesting"), // currently unused |
649 | | V_IMMUTABLE(Sandbox, BOOL, "0"), |
650 | | V(SafeLogging, STRING, "1"), |
651 | | V(SafeSocks, BOOL, "0"), |
652 | | V(ServerDNSAllowBrokenConfig, BOOL, "1"), |
653 | | V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"), |
654 | | V(ServerDNSDetectHijacking, BOOL, "1"), |
655 | | V(ServerDNSRandomizeCase, BOOL, "1"), |
656 | | V(ServerDNSResolvConfFile, FILENAME, NULL), |
657 | | V(ServerDNSSearchDomains, BOOL, "0"), |
658 | | V(ServerDNSTestAddresses, CSV, |
659 | | "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"), |
660 | | OBSOLETE("SchedulerLowWaterMark__"), |
661 | | OBSOLETE("SchedulerHighWaterMark__"), |
662 | | OBSOLETE("SchedulerMaxFlushCells__"), |
663 | | V(KISTSchedRunInterval, MSEC_INTERVAL, "0 msec"), |
664 | | V(KISTSockBufSizeFactor, DOUBLE, "1.0"), |
665 | | V(Schedulers, CSV, "KIST,KISTLite,Vanilla"), |
666 | | V(ShutdownWaitLength, INTERVAL, "30 seconds"), |
667 | | OBSOLETE("SocksListenAddress"), |
668 | | V(SocksPolicy, LINELIST, NULL), |
669 | | VPORT(SocksPort), |
670 | | V(SocksTimeout, INTERVAL, "2 minutes"), |
671 | | V(SSLKeyLifetime, INTERVAL, "0"), |
672 | | OBSOLETE("StrictEntryNodes"), |
673 | | OBSOLETE("StrictExitNodes"), |
674 | | V(StrictNodes, BOOL, "0"), |
675 | | OBSOLETE("Support022HiddenServices"), |
676 | | V(TestSocks, BOOL, "0"), |
677 | | V_IMMUTABLE(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"), |
678 | | OBSOLETE("Tor2webMode"), |
679 | | OBSOLETE("Tor2webRendezvousPoints"), |
680 | | OBSOLETE("TLSECGroup"), |
681 | | V(TrackHostExits, CSV, NULL), |
682 | | V(TrackHostExitsExpire, INTERVAL, "30 minutes"), |
683 | | OBSOLETE("TransListenAddress"), |
684 | | VPORT(TransPort), |
685 | | V(TransProxyType, STRING, "default"), |
686 | | OBSOLETE("TunnelDirConns"), |
687 | | V(UpdateBridgesFromAuthority, BOOL, "0"), |
688 | | V(UseBridges, BOOL, "0"), |
689 | | VAR("UseEntryGuards", BOOL, UseEntryGuards_option, "1"), |
690 | | OBSOLETE("UseEntryGuardsAsDirGuards"), |
691 | | V(UseGuardFraction, AUTOBOOL, "auto"), |
692 | | V(VanguardsLiteEnabled, AUTOBOOL, "auto"), |
693 | | V(UseMicrodescriptors, AUTOBOOL, "auto"), |
694 | | OBSOLETE("UseNTorHandshake"), |
695 | | VAR("__AlwaysCongestionControl", BOOL, AlwaysCongestionControl, "0"), |
696 | | VAR("__SbwsExit", BOOL, SbwsExit, "0"), |
697 | | V_IMMUTABLE(User, STRING, NULL), |
698 | | OBSOLETE("UserspaceIOCPBuffers"), |
699 | | OBSOLETE("V1AuthoritativeDirectory"), |
700 | | OBSOLETE("V2AuthoritativeDirectory"), |
701 | | VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"), |
702 | | V(TestingV3AuthInitialVotingInterval, INTERVAL, "30 minutes"), |
703 | | V(TestingV3AuthInitialVoteDelay, INTERVAL, "5 minutes"), |
704 | | V(TestingV3AuthInitialDistDelay, INTERVAL, "5 minutes"), |
705 | | V(TestingV3AuthVotingStartOffset, INTERVAL, "0"), |
706 | | V(V3AuthVotingInterval, INTERVAL, "1 hour"), |
707 | | V(V3AuthVoteDelay, INTERVAL, "5 minutes"), |
708 | | V(V3AuthDistDelay, INTERVAL, "5 minutes"), |
709 | | V(V3AuthNIntervalsValid, POSINT, "3"), |
710 | | V(V3AuthUseLegacyKey, BOOL, "0"), |
711 | | V(V3BandwidthsFile, FILENAME, NULL), |
712 | | V(GuardfractionFile, FILENAME, NULL), |
713 | | OBSOLETE("VoteOnHidServDirectoriesV2"), |
714 | | V(VirtualAddrNetworkIPv4, STRING, "127.192.0.0/10"), |
715 | | V(VirtualAddrNetworkIPv6, STRING, "[FE80::]/10"), |
716 | | V(WarnPlaintextPorts, CSV, "23,109,110,143"), |
717 | | OBSOLETE("UseFilteringSSLBufferevents"), |
718 | | OBSOLETE("__UseFilteringSSLBufferevents"), |
719 | | VAR_NODUMP("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"), |
720 | | VAR_NODUMP("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"), |
721 | | VAR_NODUMP("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"), |
722 | | VAR_NODUMP_IMMUTABLE("__DisableSignalHandlers", BOOL, |
723 | | DisableSignalHandlers, "0"), |
724 | | VAR_NODUMP("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"), |
725 | | VAR_NODUMP("__HashedControlSessionPassword", LINELIST, |
726 | | HashedControlSessionPassword, |
727 | | NULL), |
728 | | VAR_NODUMP("__OwningControllerProcess",STRING, |
729 | | OwningControllerProcess, NULL), |
730 | | VAR_NODUMP_IMMUTABLE("__OwningControllerFD", UINT64, OwningControllerFD, |
731 | | UINT64_MAX_STRING), |
732 | | V(TestingServerDownloadInitialDelay, CSV_INTERVAL, "0"), |
733 | | V(TestingClientDownloadInitialDelay, CSV_INTERVAL, "0"), |
734 | | V(TestingServerConsensusDownloadInitialDelay, CSV_INTERVAL, "0"), |
735 | | V(TestingClientConsensusDownloadInitialDelay, CSV_INTERVAL, "0"), |
736 | | /* With the ClientBootstrapConsensus*Download* below: |
737 | | * Clients with only authorities will try: |
738 | | * - at least 3 authorities over 10 seconds, then exponentially backoff, |
739 | | * with the next attempt 3-21 seconds later, |
740 | | * Clients with authorities and fallbacks will try: |
741 | | * - at least 2 authorities and 4 fallbacks over 21 seconds, then |
742 | | * exponentially backoff, with the next attempts 4-33 seconds later, |
743 | | * Clients will also retry when an application request arrives. |
744 | | * After a number of failed requests, clients retry every 3 days + 1 hour. |
745 | | * |
746 | | * Clients used to try 2 authorities over 10 seconds, then wait for |
747 | | * 60 minutes or an application request. |
748 | | * |
749 | | * When clients have authorities and fallbacks available, they use these |
750 | | * schedules: (we stagger the times to avoid thundering herds) */ |
751 | | V(ClientBootstrapConsensusAuthorityDownloadInitialDelay, CSV_INTERVAL, "6"), |
752 | | V(ClientBootstrapConsensusFallbackDownloadInitialDelay, CSV_INTERVAL, "0"), |
753 | | /* When clients only have authorities available, they use this schedule: */ |
754 | | V(ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay, CSV_INTERVAL, |
755 | | "0"), |
756 | | /* We don't want to overwhelm slow networks (or mirrors whose replies are |
757 | | * blocked), but we also don't want to fail if only some mirrors are |
758 | | * blackholed. Clients will try 3 directories simultaneously. |
759 | | * (Relays never use simultaneous connections.) */ |
760 | | V(ClientBootstrapConsensusMaxInProgressTries, POSINT, "3"), |
761 | | /* When a client has any running bridges, check each bridge occasionally, |
762 | | * whether or not that bridge is actually up. */ |
763 | | V(TestingBridgeDownloadInitialDelay, CSV_INTERVAL,"10800"), |
764 | | /* When a client is just starting, or has no running bridges, check each |
765 | | * bridge a few times quickly, and then try again later. These schedules |
766 | | * are much longer than the other schedules, because we try each and every |
767 | | * configured bridge with this schedule. */ |
768 | | V(TestingBridgeBootstrapDownloadInitialDelay, CSV_INTERVAL, "0"), |
769 | | V(TestingClientMaxIntervalWithoutRequest, INTERVAL, "10 minutes"), |
770 | | V(TestingDirConnectionMaxStall, INTERVAL, "5 minutes"), |
771 | | OBSOLETE("TestingConsensusMaxDownloadTries"), |
772 | | OBSOLETE("ClientBootstrapConsensusMaxDownloadTries"), |
773 | | OBSOLETE("ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries"), |
774 | | OBSOLETE("TestingDescriptorMaxDownloadTries"), |
775 | | OBSOLETE("TestingMicrodescMaxDownloadTries"), |
776 | | OBSOLETE("TestingCertMaxDownloadTries"), |
777 | | VAR_INVIS("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, |
778 | | "0"), |
779 | | |
780 | | END_OF_CONFIG_VARS |
781 | | }; |
782 | | |
783 | | /** List of default directory authorities */ |
784 | | static const char *default_authorities[] = { |
785 | | #ifndef COCCI |
786 | | #include "auth_dirs.inc" |
787 | | #endif |
788 | | NULL |
789 | | }; |
790 | | |
791 | | /** List of fallback directory authorities. The list is generated by opt-in of |
792 | | * relays that meet certain stability criteria. |
793 | | */ |
794 | | static const char *default_fallbacks[] = { |
795 | | #ifndef COCCI |
796 | | #include "fallback_dirs.inc" |
797 | | #endif |
798 | | NULL |
799 | | }; |
800 | | |
801 | | /** Override default values with these if the user sets the TestingTorNetwork |
802 | | * option. */ |
803 | | static const struct { |
804 | | const char *k; |
805 | | const char *v; |
806 | | } testing_tor_network_defaults[] = { |
807 | | #ifndef COCCI |
808 | | #include "testnet.inc" |
809 | | #endif |
810 | | { NULL, NULL } |
811 | | }; |
812 | | |
813 | | #undef VAR |
814 | | #undef V |
815 | | #undef OBSOLETE |
816 | | |
817 | | static const config_deprecation_t option_deprecation_notes_[] = { |
818 | | /* Deprecated since 0.3.2.0-alpha. */ |
819 | | { "HTTPProxy", "It only applies to direct unencrypted HTTP connections " |
820 | | "to your directory server, which your Tor probably wasn't using." }, |
821 | | { "HTTPProxyAuthenticator", "HTTPProxy is deprecated in favor of HTTPSProxy " |
822 | | "which should be used with HTTPSProxyAuthenticator." }, |
823 | | /* End of options deprecated since 0.3.2.1-alpha */ |
824 | | |
825 | | /* Options deprecated since 0.3.2.2-alpha */ |
826 | | { "ReachableDirAddresses", "It has no effect on relays, and has had no " |
827 | | "effect on clients since 0.2.8." }, |
828 | | { "ClientPreferIPv6DirPort", "It has no effect on relays, and has had no " |
829 | | "effect on clients since 0.2.8." }, |
830 | | /* End of options deprecated since 0.3.2.2-alpha. */ |
831 | | |
832 | | /* Options deprecated since 0.4.3.1-alpha. */ |
833 | | { "ClientAutoIPv6ORPort", "This option is unreliable if a connection isn't " |
834 | | "reliably dual-stack."}, |
835 | | /* End of options deprecated since 0.4.3.1-alpha. */ |
836 | | |
837 | | { NULL, NULL } |
838 | | }; |
839 | | |
840 | | #ifdef _WIN32 |
841 | | static char *get_windows_conf_root(void); |
842 | | #endif |
843 | | |
844 | | static int options_check_transition_cb(const void *old, |
845 | | const void *new, |
846 | | char **msg); |
847 | | static int validate_data_directories(or_options_t *options); |
848 | | static int write_configuration_file(const char *fname, |
849 | | const or_options_t *options); |
850 | | |
851 | | static void init_libevent(const or_options_t *options); |
852 | | static int opt_streq(const char *s1, const char *s2); |
853 | | static int parse_outbound_addresses(or_options_t *options, int validate_only, |
854 | | char **msg); |
855 | | static void config_maybe_load_geoip_files_(const or_options_t *options, |
856 | | const or_options_t *old_options); |
857 | | static int options_validate_cb(const void *old_options, void *options, |
858 | | char **msg); |
859 | | static void cleanup_protocol_warning_severity_level(void); |
860 | | static void set_protocol_warning_severity_level(int warning_severity); |
861 | | static void options_clear_cb(const config_mgr_t *mgr, void *opts); |
862 | | static setopt_err_t options_validate_and_set(const or_options_t *old_options, |
863 | | or_options_t *new_options, |
864 | | char **msg_out); |
865 | | struct listener_transaction_t; |
866 | | static void options_rollback_listener_transaction( |
867 | | struct listener_transaction_t *xn); |
868 | | |
869 | | /** Magic value for or_options_t. */ |
870 | | #define OR_OPTIONS_MAGIC 9090909 |
871 | | |
872 | | /** Configuration format for or_options_t. */ |
873 | | static const config_format_t options_format = { |
874 | | .size = sizeof(or_options_t), |
875 | | .magic = { |
876 | | "or_options_t", |
877 | | OR_OPTIONS_MAGIC, |
878 | | offsetof(or_options_t, magic_), |
879 | | }, |
880 | | .abbrevs = option_abbrevs_, |
881 | | .deprecations = option_deprecation_notes_, |
882 | | .vars = option_vars_, |
883 | | .legacy_validate_fn = options_validate_cb, |
884 | | .check_transition_fn = options_check_transition_cb, |
885 | | .clear_fn = options_clear_cb, |
886 | | .has_config_suite = true, |
887 | | .config_suite_offset = offsetof(or_options_t, subconfigs_), |
888 | | }; |
889 | | |
890 | | /* |
891 | | * Functions to read and write the global options pointer. |
892 | | */ |
893 | | |
894 | | /** Command-line and config-file options. */ |
895 | | static or_options_t *global_options = NULL; |
896 | | /** The fallback options_t object; this is where we look for options not |
897 | | * in torrc before we fall back to Tor's defaults. */ |
898 | | static or_options_t *global_default_options = NULL; |
899 | | /** Name of most recently read torrc file. */ |
900 | | static char *torrc_fname = NULL; |
901 | | /** Name of the most recently read torrc-defaults file.*/ |
902 | | static char *torrc_defaults_fname = NULL; |
903 | | /** Result of parsing the command line. */ |
904 | | static parsed_cmdline_t *global_cmdline = NULL; |
905 | | /** List of port_cfg_t for all configured ports. */ |
906 | | static smartlist_t *configured_ports = NULL; |
907 | | /** True iff we're currently validating options, and any calls to |
908 | | * get_options() are likely to be bugs. */ |
909 | | static int in_option_validation = 0; |
910 | | /** True iff we have run options_act_once_on_startup() */ |
911 | | static bool have_set_startup_options = false; |
912 | | |
913 | | /* A global configuration manager to handle all configuration objects. */ |
914 | | static config_mgr_t *options_mgr = NULL; |
915 | | |
916 | | /** Return the global configuration manager object for torrc options. */ |
917 | | STATIC const config_mgr_t * |
918 | | get_options_mgr(void) |
919 | 16 | { |
920 | 16 | if (PREDICT_UNLIKELY(options_mgr == NULL)) { |
921 | 16 | options_mgr = config_mgr_new(&options_format); |
922 | 16 | int rv = subsystems_register_options_formats(options_mgr); |
923 | 16 | tor_assert(rv == 0); |
924 | 16 | config_mgr_freeze(options_mgr); |
925 | 16 | } |
926 | 16 | return options_mgr; |
927 | 16 | } |
928 | | |
929 | 0 | #define CHECK_OPTIONS_MAGIC(opt) STMT_BEGIN \ |
930 | 0 | config_check_toplevel_magic(get_options_mgr(), (opt)); \ |
931 | 0 | STMT_END |
932 | | |
933 | | /** Returns the currently configured options. */ |
934 | | MOCK_IMPL(or_options_t *, |
935 | | get_options_mutable, (void)) |
936 | 0 | { |
937 | 0 | tor_assert(global_options); |
938 | 0 | tor_assert_nonfatal(! in_option_validation); |
939 | 0 | return global_options; |
940 | 0 | } |
941 | | |
942 | | /** Returns the currently configured options */ |
943 | | MOCK_IMPL(const or_options_t *, |
944 | | get_options,(void)) |
945 | 0 | { |
946 | 0 | return get_options_mutable(); |
947 | 0 | } |
948 | | |
949 | | /** |
950 | | * True iff we have noticed that this is a testing tor network, and we |
951 | | * should use the corresponding defaults. |
952 | | **/ |
953 | | static bool testing_network_configured = false; |
954 | | |
955 | | /** Return a set of lines for any default options that we want to override |
956 | | * from those set in our config_var_t values. */ |
957 | | static config_line_t * |
958 | | get_options_defaults(void) |
959 | 0 | { |
960 | 0 | int i; |
961 | 0 | config_line_t *result = NULL, **next = &result; |
962 | |
|
963 | 0 | if (testing_network_configured) { |
964 | 0 | for (i = 0; testing_tor_network_defaults[i].k; ++i) { |
965 | 0 | config_line_append(next, |
966 | 0 | testing_tor_network_defaults[i].k, |
967 | 0 | testing_tor_network_defaults[i].v); |
968 | 0 | next = &(*next)->next; |
969 | 0 | } |
970 | 0 | } |
971 | |
|
972 | 0 | return result; |
973 | 0 | } |
974 | | |
975 | | /** Change the current global options to contain <b>new_val</b> instead of |
976 | | * their current value; take action based on the new value; free the old value |
977 | | * as necessary. Returns 0 on success, -1 on failure. |
978 | | */ |
979 | | int |
980 | | set_options(or_options_t *new_val, char **msg) |
981 | 0 | { |
982 | 0 | or_options_t *old_options = global_options; |
983 | 0 | global_options = new_val; |
984 | | /* Note that we pass the *old* options below, for comparison. It |
985 | | * pulls the new options directly out of global_options. */ |
986 | 0 | if (options_act_reversible(old_options, msg)<0) { |
987 | 0 | tor_assert(*msg); |
988 | 0 | global_options = old_options; |
989 | 0 | return -1; |
990 | 0 | } |
991 | 0 | if (subsystems_set_options(get_options_mgr(), new_val) < 0 || |
992 | 0 | options_act(old_options) < 0) { /* acting on the options failed. die. */ |
993 | 0 | if (! tor_event_loop_shutdown_is_pending()) { |
994 | 0 | log_err(LD_BUG, |
995 | 0 | "Acting on config options left us in a broken state. Dying."); |
996 | 0 | tor_shutdown_event_loop_and_exit(1); |
997 | 0 | } |
998 | 0 | global_options = old_options; |
999 | 0 | return -1; |
1000 | 0 | } |
1001 | | /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is |
1002 | | * just starting up then the old_options will be undefined. */ |
1003 | 0 | if (old_options && old_options != global_options) { |
1004 | 0 | config_line_t *changes = |
1005 | 0 | config_get_changes(get_options_mgr(), old_options, new_val); |
1006 | 0 | control_event_conf_changed(changes); |
1007 | 0 | connection_reapply_exit_policy(changes); |
1008 | 0 | config_free_lines(changes); |
1009 | 0 | } |
1010 | |
|
1011 | 0 | if (old_options != global_options) { |
1012 | 0 | or_options_free(old_options); |
1013 | | /* If we are here it means we've successfully applied the new options and |
1014 | | * that the global options have been changed to the new values. We'll |
1015 | | * check if we need to remove or add periodic events. */ |
1016 | 0 | periodic_events_on_new_options(global_options); |
1017 | 0 | } |
1018 | |
|
1019 | 0 | return 0; |
1020 | 0 | } |
1021 | | |
1022 | | /** Release additional memory allocated in options |
1023 | | */ |
1024 | | static void |
1025 | | options_clear_cb(const config_mgr_t *mgr, void *opts) |
1026 | 0 | { |
1027 | 0 | (void)mgr; |
1028 | 0 | CHECK_OPTIONS_MAGIC(opts); |
1029 | 0 | or_options_t *options = opts; |
1030 | |
|
1031 | 0 | routerset_free(options->ExcludeExitNodesUnion_); |
1032 | 0 | if (options->NodeFamilySets) { |
1033 | 0 | SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *, |
1034 | 0 | rs, routerset_free(rs)); |
1035 | 0 | smartlist_free(options->NodeFamilySets); |
1036 | 0 | } |
1037 | 0 | if (options->SchedulerTypes_) { |
1038 | 0 | SMARTLIST_FOREACH(options->SchedulerTypes_, int *, i, tor_free(i)); |
1039 | 0 | smartlist_free(options->SchedulerTypes_); |
1040 | 0 | } |
1041 | 0 | if (options->FilesOpenedByIncludes) { |
1042 | 0 | SMARTLIST_FOREACH(options->FilesOpenedByIncludes, char *, f, tor_free(f)); |
1043 | 0 | smartlist_free(options->FilesOpenedByIncludes); |
1044 | 0 | } |
1045 | 0 | tor_free(options->DataDirectory); |
1046 | 0 | tor_free(options->CacheDirectory); |
1047 | 0 | tor_free(options->KeyDirectory); |
1048 | 0 | tor_free(options->BridgePassword_AuthDigest_); |
1049 | 0 | tor_free(options->command_arg); |
1050 | 0 | tor_free(options->master_key_fname); |
1051 | 0 | config_free_lines(options->MyFamily); |
1052 | 0 | } |
1053 | | |
1054 | | /** Release all memory allocated in options |
1055 | | */ |
1056 | | STATIC void |
1057 | | or_options_free_(or_options_t *options) |
1058 | 0 | { |
1059 | 0 | config_free(get_options_mgr(), options); |
1060 | 0 | } |
1061 | | |
1062 | | /** Release all memory and resources held by global configuration structures. |
1063 | | */ |
1064 | | void |
1065 | | config_free_all(void) |
1066 | 0 | { |
1067 | 0 | or_options_free(global_options); |
1068 | 0 | global_options = NULL; |
1069 | 0 | or_options_free(global_default_options); |
1070 | 0 | global_default_options = NULL; |
1071 | |
|
1072 | 0 | parsed_cmdline_free(global_cmdline); |
1073 | |
|
1074 | 0 | if (configured_ports) { |
1075 | 0 | SMARTLIST_FOREACH(configured_ports, |
1076 | 0 | port_cfg_t *, p, port_cfg_free(p)); |
1077 | 0 | smartlist_free(configured_ports); |
1078 | 0 | configured_ports = NULL; |
1079 | 0 | } |
1080 | |
|
1081 | 0 | tor_free(torrc_fname); |
1082 | 0 | tor_free(torrc_defaults_fname); |
1083 | |
|
1084 | 0 | cleanup_protocol_warning_severity_level(); |
1085 | |
|
1086 | 0 | have_set_startup_options = false; |
1087 | |
|
1088 | 0 | config_mgr_free(options_mgr); |
1089 | 0 | } |
1090 | | |
1091 | | /** Make <b>address</b> -- a piece of information related to our operation as |
1092 | | * a client -- safe to log according to the settings in options->SafeLogging, |
1093 | | * and return it. |
1094 | | * |
1095 | | * (We return "[scrubbed]" if SafeLogging is "1", and address otherwise.) |
1096 | | */ |
1097 | | const char * |
1098 | | safe_str_client_opts(const or_options_t *options, const char *address) |
1099 | 0 | { |
1100 | 0 | tor_assert(address); |
1101 | 0 | if (!options) { |
1102 | 0 | options = get_options(); |
1103 | 0 | } |
1104 | |
|
1105 | 0 | if (options->SafeLogging_ == SAFELOG_SCRUB_ALL) |
1106 | 0 | return "[scrubbed]"; |
1107 | 0 | else |
1108 | 0 | return address; |
1109 | 0 | } |
1110 | | |
1111 | | /** Make <b>address</b> -- a piece of information of unspecified sensitivity |
1112 | | * -- safe to log according to the settings in options->SafeLogging, and |
1113 | | * return it. |
1114 | | * |
1115 | | * (We return "[scrubbed]" if SafeLogging is anything besides "0", and address |
1116 | | * otherwise.) |
1117 | | */ |
1118 | | const char * |
1119 | | safe_str_opts(const or_options_t *options, const char *address) |
1120 | 0 | { |
1121 | 0 | tor_assert(address); |
1122 | 0 | if (!options) { |
1123 | 0 | options = get_options(); |
1124 | 0 | } |
1125 | |
|
1126 | 0 | if (options->SafeLogging_ != SAFELOG_SCRUB_NONE) |
1127 | 0 | return "[scrubbed]"; |
1128 | 0 | else |
1129 | 0 | return address; |
1130 | 0 | } |
1131 | | |
1132 | | /** Equivalent to escaped(safe_str_client(address)). See reentrancy note on |
1133 | | * escaped(): don't use this outside the main thread, or twice in the same |
1134 | | * log statement. */ |
1135 | | const char * |
1136 | | escaped_safe_str_client(const char *address) |
1137 | 265 | { |
1138 | 265 | if (get_options()->SafeLogging_ == SAFELOG_SCRUB_ALL) |
1139 | 265 | return "[scrubbed]"; |
1140 | 0 | else |
1141 | 0 | return escaped(address); |
1142 | 265 | } |
1143 | | |
1144 | | /** Equivalent to escaped(safe_str(address)). See reentrancy note on |
1145 | | * escaped(): don't use this outside the main thread, or twice in the same |
1146 | | * log statement. */ |
1147 | | const char * |
1148 | | escaped_safe_str(const char *address) |
1149 | 0 | { |
1150 | 0 | if (get_options()->SafeLogging_ != SAFELOG_SCRUB_NONE) |
1151 | 0 | return "[scrubbed]"; |
1152 | 0 | else |
1153 | 0 | return escaped(address); |
1154 | 0 | } |
1155 | | |
1156 | | /** |
1157 | | * The severity level that should be used for warnings of severity |
1158 | | * LOG_PROTOCOL_WARN. |
1159 | | * |
1160 | | * We keep this outside the options, and we use an atomic_counter_t, in case |
1161 | | * one thread needs to use LOG_PROTOCOL_WARN while an option transition is |
1162 | | * happening in the main thread. |
1163 | | */ |
1164 | | static atomic_counter_t protocol_warning_severity_level; |
1165 | | |
1166 | | /** Return the severity level that should be used for warnings of severity |
1167 | | * LOG_PROTOCOL_WARN. */ |
1168 | | int |
1169 | | get_protocol_warning_severity_level(void) |
1170 | 11.5k | { |
1171 | 11.5k | return (int) atomic_counter_get(&protocol_warning_severity_level); |
1172 | 11.5k | } |
1173 | | |
1174 | | /** Set the protocol warning severity level to <b>severity</b>. */ |
1175 | | static void |
1176 | | set_protocol_warning_severity_level(int warning_severity) |
1177 | 16 | { |
1178 | 16 | atomic_counter_exchange(&protocol_warning_severity_level, |
1179 | 16 | warning_severity); |
1180 | 16 | } |
1181 | | |
1182 | | /** |
1183 | | * Initialize the log warning severity level for protocol warnings. Call |
1184 | | * only once at startup. |
1185 | | */ |
1186 | | void |
1187 | | init_protocol_warning_severity_level(void) |
1188 | 16 | { |
1189 | 16 | atomic_counter_init(&protocol_warning_severity_level); |
1190 | 16 | set_protocol_warning_severity_level(LOG_WARN); |
1191 | 16 | } |
1192 | | |
1193 | | /** |
1194 | | * Tear down protocol_warning_severity_level. |
1195 | | */ |
1196 | | static void |
1197 | | cleanup_protocol_warning_severity_level(void) |
1198 | 0 | { |
1199 | | /* Destroying a locked mutex is undefined behaviour. This mutex may be |
1200 | | * locked, because multiple threads can access it. But we need to destroy |
1201 | | * it, otherwise re-initialisation will trigger undefined behaviour. |
1202 | | * See #31735 for details. */ |
1203 | 0 | atomic_counter_destroy(&protocol_warning_severity_level); |
1204 | 0 | } |
1205 | | |
1206 | | /** Add the default directory authorities directly into the trusted dir list, |
1207 | | * but only add them insofar as they share bits with <b>type</b>. |
1208 | | * Each authority's bits are restricted to the bits shared with <b>type</b>. |
1209 | | * If <b>type</b> is ALL_DIRINFO or NO_DIRINFO (zero), add all authorities. */ |
1210 | | STATIC void |
1211 | | add_default_trusted_dir_authorities(dirinfo_type_t type) |
1212 | 0 | { |
1213 | 0 | int i; |
1214 | 0 | for (i=0; default_authorities[i]; i++) { |
1215 | 0 | if (parse_dir_authority_line(default_authorities[i], type, 0)<0) { |
1216 | 0 | log_err(LD_BUG, "Couldn't parse internal DirAuthority line %s", |
1217 | 0 | default_authorities[i]); |
1218 | 0 | } |
1219 | 0 | } |
1220 | 0 | } |
1221 | | |
1222 | | /** Add the default fallback directory servers into the fallback directory |
1223 | | * server list. */ |
1224 | | MOCK_IMPL(void, |
1225 | | add_default_fallback_dir_servers,(void)) |
1226 | 0 | { |
1227 | 0 | int i; |
1228 | 0 | for (i=0; default_fallbacks[i]; i++) { |
1229 | 0 | if (parse_dir_fallback_line(default_fallbacks[i], 0)<0) { |
1230 | 0 | log_err(LD_BUG, "Couldn't parse internal FallbackDir line %s", |
1231 | 0 | default_fallbacks[i]); |
1232 | 0 | } |
1233 | 0 | } |
1234 | 0 | } |
1235 | | |
1236 | | /** Look at all the config options for using alternate directory |
1237 | | * authorities, and make sure none of them are broken. Also, warn the |
1238 | | * user if we changed any dangerous ones. |
1239 | | */ |
1240 | | static int |
1241 | | validate_dir_servers(const or_options_t *options, |
1242 | | const or_options_t *old_options) |
1243 | 0 | { |
1244 | 0 | config_line_t *cl; |
1245 | |
|
1246 | 0 | if (options->DirAuthorities && |
1247 | 0 | (options->AlternateDirAuthority || options->AlternateBridgeAuthority)) { |
1248 | 0 | log_warn(LD_CONFIG, |
1249 | 0 | "You cannot set both DirAuthority and Alternate*Authority."); |
1250 | 0 | return -1; |
1251 | 0 | } |
1252 | | |
1253 | | /* do we want to complain to the user about being partitionable? */ |
1254 | 0 | if ((options->DirAuthorities && |
1255 | 0 | (!old_options || |
1256 | 0 | !config_lines_eq(options->DirAuthorities, |
1257 | 0 | old_options->DirAuthorities))) || |
1258 | 0 | (options->AlternateDirAuthority && |
1259 | 0 | (!old_options || |
1260 | 0 | !config_lines_eq(options->AlternateDirAuthority, |
1261 | 0 | old_options->AlternateDirAuthority)))) { |
1262 | 0 | log_warn(LD_CONFIG, |
1263 | 0 | "You have used DirAuthority or AlternateDirAuthority to " |
1264 | 0 | "specify alternate directory authorities in " |
1265 | 0 | "your configuration. This is potentially dangerous: it can " |
1266 | 0 | "make you look different from all other Tor users, and hurt " |
1267 | 0 | "your anonymity. Even if you've specified the same " |
1268 | 0 | "authorities as Tor uses by default, the defaults could " |
1269 | 0 | "change in the future. Be sure you know what you're doing."); |
1270 | 0 | } |
1271 | | |
1272 | | /* Now go through the four ways you can configure an alternate |
1273 | | * set of directory authorities, and make sure none are broken. */ |
1274 | 0 | for (cl = options->DirAuthorities; cl; cl = cl->next) |
1275 | 0 | if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0) |
1276 | 0 | return -1; |
1277 | 0 | for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next) |
1278 | 0 | if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0) |
1279 | 0 | return -1; |
1280 | 0 | for (cl = options->AlternateDirAuthority; cl; cl = cl->next) |
1281 | 0 | if (parse_dir_authority_line(cl->value, NO_DIRINFO, 1)<0) |
1282 | 0 | return -1; |
1283 | 0 | for (cl = options->FallbackDir; cl; cl = cl->next) |
1284 | 0 | if (parse_dir_fallback_line(cl->value, 1)<0) |
1285 | 0 | return -1; |
1286 | 0 | return 0; |
1287 | 0 | } |
1288 | | |
1289 | | /** Look at all the config options and assign new dir authorities |
1290 | | * as appropriate. |
1291 | | */ |
1292 | | int |
1293 | | consider_adding_dir_servers(const or_options_t *options, |
1294 | | const or_options_t *old_options) |
1295 | 0 | { |
1296 | 0 | config_line_t *cl; |
1297 | 0 | int need_to_update = |
1298 | 0 | !smartlist_len(router_get_trusted_dir_servers()) || |
1299 | 0 | !smartlist_len(router_get_fallback_dir_servers()) || !old_options || |
1300 | 0 | !config_lines_eq(options->DirAuthorities, old_options->DirAuthorities) || |
1301 | 0 | !config_lines_eq(options->FallbackDir, old_options->FallbackDir) || |
1302 | 0 | (options->UseDefaultFallbackDirs != old_options->UseDefaultFallbackDirs) || |
1303 | 0 | !config_lines_eq(options->AlternateBridgeAuthority, |
1304 | 0 | old_options->AlternateBridgeAuthority) || |
1305 | 0 | !config_lines_eq(options->AlternateDirAuthority, |
1306 | 0 | old_options->AlternateDirAuthority); |
1307 | |
|
1308 | 0 | if (!need_to_update) |
1309 | 0 | return 0; /* all done */ |
1310 | | |
1311 | | /* "You cannot set both DirAuthority and Alternate*Authority." |
1312 | | * Checking that this restriction holds allows us to simplify |
1313 | | * the unit tests. */ |
1314 | 0 | tor_assert(!(options->DirAuthorities && |
1315 | 0 | (options->AlternateDirAuthority |
1316 | 0 | || options->AlternateBridgeAuthority))); |
1317 | | |
1318 | | /* Start from a clean slate. */ |
1319 | 0 | clear_dir_servers(); |
1320 | |
|
1321 | 0 | if (!options->DirAuthorities) { |
1322 | | /* then we may want some of the defaults */ |
1323 | 0 | dirinfo_type_t type = NO_DIRINFO; |
1324 | 0 | if (!options->AlternateBridgeAuthority) { |
1325 | 0 | type |= BRIDGE_DIRINFO; |
1326 | 0 | } |
1327 | 0 | if (!options->AlternateDirAuthority) { |
1328 | 0 | type |= V3_DIRINFO | EXTRAINFO_DIRINFO | MICRODESC_DIRINFO; |
1329 | | /* Only add the default fallback directories when the DirAuthorities, |
1330 | | * AlternateDirAuthority, and FallbackDir directory config options |
1331 | | * are set to their defaults, and when UseDefaultFallbackDirs is 1. */ |
1332 | 0 | if (!options->FallbackDir && options->UseDefaultFallbackDirs) { |
1333 | 0 | add_default_fallback_dir_servers(); |
1334 | 0 | } |
1335 | 0 | } |
1336 | | /* if type == NO_DIRINFO, we don't want to add any of the |
1337 | | * default authorities, because we've replaced them all */ |
1338 | 0 | if (type != NO_DIRINFO) |
1339 | 0 | add_default_trusted_dir_authorities(type); |
1340 | 0 | } |
1341 | |
|
1342 | 0 | for (cl = options->DirAuthorities; cl; cl = cl->next) |
1343 | 0 | if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0) |
1344 | 0 | return -1; |
1345 | 0 | for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next) |
1346 | 0 | if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0) |
1347 | 0 | return -1; |
1348 | 0 | for (cl = options->AlternateDirAuthority; cl; cl = cl->next) |
1349 | 0 | if (parse_dir_authority_line(cl->value, NO_DIRINFO, 0)<0) |
1350 | 0 | return -1; |
1351 | 0 | for (cl = options->FallbackDir; cl; cl = cl->next) |
1352 | 0 | if (parse_dir_fallback_line(cl->value, 0)<0) |
1353 | 0 | return -1; |
1354 | 0 | return 0; |
1355 | 0 | } |
1356 | | |
1357 | | /** |
1358 | | * Make sure that <b>directory</b> exists, with appropriate ownership and |
1359 | | * permissions (as modified by <b>group_readable</b>). If <b>create</b>, |
1360 | | * create the directory if it is missing. Return 0 on success. |
1361 | | * On failure, return -1 and set *<b>msg_out</b>. |
1362 | | */ |
1363 | | static int |
1364 | | check_and_create_data_directory(int create, |
1365 | | const char *directory, |
1366 | | int group_readable, |
1367 | | const char *owner, |
1368 | | char **msg_out) |
1369 | 0 | { |
1370 | 0 | cpd_check_t cpd_opts = create ? CPD_CREATE : CPD_CHECK; |
1371 | 0 | if (group_readable) |
1372 | 0 | cpd_opts |= CPD_GROUP_READ; |
1373 | 0 | if (check_private_dir(directory, |
1374 | 0 | cpd_opts, |
1375 | 0 | owner) < 0) { |
1376 | 0 | tor_asprintf(msg_out, |
1377 | 0 | "Couldn't %s private data directory \"%s\"", |
1378 | 0 | create ? "create" : "access", |
1379 | 0 | directory); |
1380 | 0 | return -1; |
1381 | 0 | } |
1382 | | |
1383 | 0 | #ifndef _WIN32 |
1384 | 0 | if (group_readable) { |
1385 | | /* Only new dirs created get new opts, also enforce group read. */ |
1386 | 0 | if (chmod(directory, 0750)) { |
1387 | 0 | log_warn(LD_FS,"Unable to make %s group-readable: %s", |
1388 | 0 | directory, strerror(errno)); |
1389 | 0 | } |
1390 | 0 | } |
1391 | 0 | #endif /* !defined(_WIN32) */ |
1392 | |
|
1393 | 0 | return 0; |
1394 | 0 | } |
1395 | | |
1396 | | /** |
1397 | | * Ensure that our keys directory exists, with appropriate permissions. |
1398 | | * Return 0 on success, -1 on failure. |
1399 | | */ |
1400 | | int |
1401 | | create_keys_directory(const or_options_t *options) |
1402 | 0 | { |
1403 | | /* Make sure DataDirectory exists, and is private. */ |
1404 | 0 | cpd_check_t cpd_opts = CPD_CREATE; |
1405 | 0 | if (options->DataDirectoryGroupReadable) |
1406 | 0 | cpd_opts |= CPD_GROUP_READ; |
1407 | 0 | if (check_private_dir(options->DataDirectory, cpd_opts, options->User)) { |
1408 | 0 | log_err(LD_OR, "Can't create/check datadirectory %s", |
1409 | 0 | options->DataDirectory); |
1410 | 0 | return -1; |
1411 | 0 | } |
1412 | | |
1413 | | /* Check the key directory. */ |
1414 | 0 | if (check_private_dir(options->KeyDirectory, CPD_CREATE, options->User)) { |
1415 | 0 | return -1; |
1416 | 0 | } |
1417 | 0 | return 0; |
1418 | 0 | } |
1419 | | |
1420 | | /* Helps determine flags to pass to switch_id. */ |
1421 | | static int have_low_ports = -1; |
1422 | | |
1423 | | /** Take case of initial startup tasks that must occur before any of the |
1424 | | * transactional option-related changes are allowed. */ |
1425 | | static int |
1426 | | options_act_once_on_startup(char **msg_out) |
1427 | 0 | { |
1428 | 0 | if (have_set_startup_options) |
1429 | 0 | return 0; |
1430 | | |
1431 | 0 | const or_options_t *options = get_options(); |
1432 | 0 | const bool running_tor = options->command == CMD_RUN_TOR; |
1433 | |
|
1434 | 0 | if (!running_tor) |
1435 | 0 | return 0; |
1436 | | |
1437 | | /* Daemonize _first_, since we only want to open most of this stuff in |
1438 | | * the subprocess. Libevent bases can't be reliably inherited across |
1439 | | * processes. */ |
1440 | 0 | if (options->RunAsDaemon) { |
1441 | 0 | if (! start_daemon_has_been_called()) |
1442 | 0 | subsystems_prefork(); |
1443 | | /* No need to roll back, since you can't change the value. */ |
1444 | 0 | if (start_daemon()) |
1445 | 0 | subsystems_postfork(); |
1446 | 0 | } |
1447 | |
|
1448 | | #ifdef HAVE_SYSTEMD |
1449 | | /* Our PID may have changed, inform supervisor */ |
1450 | | sd_notifyf(0, "MAINPID=%ld\n", (long int)getpid()); |
1451 | | #endif |
1452 | | |
1453 | | /* Set up libevent. (We need to do this before we can register the |
1454 | | * listeners as listeners.) */ |
1455 | 0 | init_libevent(options); |
1456 | | |
1457 | | /* This has to come up after libevent is initialized. */ |
1458 | 0 | control_initialize_event_queue(); |
1459 | | |
1460 | | /* |
1461 | | * Initialize the scheduler - this has to come after |
1462 | | * options_init_from_torrc() sets up libevent - why yes, that seems |
1463 | | * completely sensible to hide the libevent setup in the option parsing |
1464 | | * code! It also needs to happen before init_keys(), so it needs to |
1465 | | * happen here too. How yucky. */ |
1466 | 0 | scheduler_init(); |
1467 | | |
1468 | | /* Attempt to lock all current and future memory with mlockall() only once. |
1469 | | * This must happen before setuid. */ |
1470 | 0 | if (options->DisableAllSwap) { |
1471 | 0 | if (tor_mlockall() == -1) { |
1472 | 0 | *msg_out = tor_strdup("DisableAllSwap failure. Do you have proper " |
1473 | 0 | "permissions?"); |
1474 | 0 | return -1; |
1475 | 0 | } |
1476 | 0 | } |
1477 | | |
1478 | 0 | have_set_startup_options = true; |
1479 | 0 | return 0; |
1480 | 0 | } |
1481 | | |
1482 | | /** |
1483 | | * Change our user ID if we're configured to do so. |
1484 | | **/ |
1485 | | static int |
1486 | | options_switch_id(char **msg_out) |
1487 | 0 | { |
1488 | 0 | const or_options_t *options = get_options(); |
1489 | | |
1490 | | /* Setuid/setgid as appropriate */ |
1491 | 0 | if (options->User) { |
1492 | 0 | tor_assert(have_low_ports != -1); |
1493 | 0 | unsigned switch_id_flags = 0; |
1494 | 0 | if (options->KeepBindCapabilities == 1) { |
1495 | 0 | switch_id_flags |= SWITCH_ID_KEEP_BINDLOW; |
1496 | 0 | switch_id_flags |= SWITCH_ID_WARN_IF_NO_CAPS; |
1497 | 0 | } |
1498 | 0 | if (options->KeepBindCapabilities == -1 && have_low_ports) { |
1499 | 0 | switch_id_flags |= SWITCH_ID_KEEP_BINDLOW; |
1500 | 0 | } |
1501 | 0 | if (switch_id(options->User, switch_id_flags) != 0) { |
1502 | | /* No need to roll back, since you can't change the value. */ |
1503 | 0 | *msg_out = tor_strdup("Problem with User value. See logs for details."); |
1504 | 0 | return -1; |
1505 | 0 | } |
1506 | 0 | } |
1507 | | |
1508 | 0 | return 0; |
1509 | 0 | } |
1510 | | |
1511 | | /** |
1512 | | * Helper. Given a data directory (<b>datadir</b>) and another directory |
1513 | | * (<b>subdir</b>) with respective group-writable permissions |
1514 | | * <b>datadir_gr</b> and <b>subdir_gr</b>, compute whether the subdir should |
1515 | | * be group-writeable. |
1516 | | **/ |
1517 | | static int |
1518 | | compute_group_readable_flag(const char *datadir, |
1519 | | const char *subdir, |
1520 | | int datadir_gr, |
1521 | | int subdir_gr) |
1522 | 0 | { |
1523 | 0 | if (subdir_gr != -1) { |
1524 | | /* The user specified a default for "subdir", so we always obey it. */ |
1525 | 0 | return subdir_gr; |
1526 | 0 | } |
1527 | | |
1528 | | /* The user left the subdir_gr option on "auto." */ |
1529 | 0 | if (0 == strcmp(subdir, datadir)) { |
1530 | | /* The directories are the same, so we use the group-readable flag from |
1531 | | * the datadirectory */ |
1532 | 0 | return datadir_gr; |
1533 | 0 | } else { |
1534 | | /* The directories are different, so we default to "not group-readable" */ |
1535 | 0 | return 0; |
1536 | 0 | } |
1537 | 0 | } |
1538 | | |
1539 | | /** |
1540 | | * Create our DataDirectory, CacheDirectory, and KeyDirectory, and |
1541 | | * set their permissions correctly. |
1542 | | */ |
1543 | | STATIC int |
1544 | | options_create_directories(char **msg_out) |
1545 | 0 | { |
1546 | 0 | const or_options_t *options = get_options(); |
1547 | 0 | const bool running_tor = options->command == CMD_RUN_TOR; |
1548 | | |
1549 | | /* Ensure data directory is private; create if possible. */ |
1550 | | /* It's okay to do this in "options_act_reversible()" even though it isn't |
1551 | | * actually reversible, since you can't change the DataDirectory while |
1552 | | * Tor is running. */ |
1553 | 0 | if (check_and_create_data_directory(running_tor /* create */, |
1554 | 0 | options->DataDirectory, |
1555 | 0 | options->DataDirectoryGroupReadable, |
1556 | 0 | options->User, |
1557 | 0 | msg_out) < 0) { |
1558 | 0 | return -1; |
1559 | 0 | } |
1560 | | |
1561 | | /* We need to handle the group-readable flag for the cache directory and key |
1562 | | * directory specially, since they may be the same as the data directory */ |
1563 | 0 | const int key_dir_group_readable = compute_group_readable_flag( |
1564 | 0 | options->DataDirectory, |
1565 | 0 | options->KeyDirectory, |
1566 | 0 | options->DataDirectoryGroupReadable, |
1567 | 0 | options->KeyDirectoryGroupReadable); |
1568 | |
|
1569 | 0 | if (check_and_create_data_directory(running_tor /* create */, |
1570 | 0 | options->KeyDirectory, |
1571 | 0 | key_dir_group_readable, |
1572 | 0 | options->User, |
1573 | 0 | msg_out) < 0) { |
1574 | 0 | return -1; |
1575 | 0 | } |
1576 | | |
1577 | 0 | const int cache_dir_group_readable = compute_group_readable_flag( |
1578 | 0 | options->DataDirectory, |
1579 | 0 | options->CacheDirectory, |
1580 | 0 | options->DataDirectoryGroupReadable, |
1581 | 0 | options->CacheDirectoryGroupReadable); |
1582 | |
|
1583 | 0 | if (check_and_create_data_directory(running_tor /* create */, |
1584 | 0 | options->CacheDirectory, |
1585 | 0 | cache_dir_group_readable, |
1586 | 0 | options->User, |
1587 | 0 | msg_out) < 0) { |
1588 | 0 | return -1; |
1589 | 0 | } |
1590 | | |
1591 | 0 | return 0; |
1592 | 0 | } |
1593 | | |
1594 | | /** Structure to represent an incomplete configuration of a set of |
1595 | | * listeners. |
1596 | | * |
1597 | | * This structure is generated by options_start_listener_transaction(), and is |
1598 | | * either committed by options_commit_listener_transaction() or rolled back by |
1599 | | * options_rollback_listener_transaction(). */ |
1600 | | typedef struct listener_transaction_t { |
1601 | | bool set_conn_limit; /**< True if we've set the connection limit */ |
1602 | | unsigned old_conn_limit; /**< If nonzero, previous connlimit value. */ |
1603 | | smartlist_t *new_listeners; /**< List of new listeners that we opened. */ |
1604 | | } listener_transaction_t; |
1605 | | |
1606 | | /** |
1607 | | * Start configuring our listeners based on the current value of |
1608 | | * get_options(). |
1609 | | * |
1610 | | * The value <b>old_options</b> holds either the previous options object, |
1611 | | * or NULL if we're starting for the first time. |
1612 | | * |
1613 | | * On success, return a listener_transaction_t that we can either roll back or |
1614 | | * commit. |
1615 | | * |
1616 | | * On failure return NULL and write a message into a newly allocated string in |
1617 | | * *<b>msg_out</b>. |
1618 | | **/ |
1619 | | static listener_transaction_t * |
1620 | | options_start_listener_transaction(const or_options_t *old_options, |
1621 | | char **msg_out) |
1622 | 0 | { |
1623 | 0 | listener_transaction_t *xn = tor_malloc_zero(sizeof(listener_transaction_t)); |
1624 | 0 | xn->new_listeners = smartlist_new(); |
1625 | 0 | or_options_t *options = get_options_mutable(); |
1626 | 0 | const bool running_tor = options->command == CMD_RUN_TOR; |
1627 | |
|
1628 | 0 | if (! running_tor) { |
1629 | 0 | return xn; |
1630 | 0 | } |
1631 | | |
1632 | 0 | int n_ports=0; |
1633 | | /* We need to set the connection limit before we can open the listeners. */ |
1634 | 0 | if (! sandbox_is_active()) { |
1635 | 0 | if (set_max_file_descriptors((unsigned)options->ConnLimit, |
1636 | 0 | &options->ConnLimit_) < 0) { |
1637 | 0 | *msg_out = tor_strdup("Problem with ConnLimit value. " |
1638 | 0 | "See logs for details."); |
1639 | 0 | goto rollback; |
1640 | 0 | } |
1641 | 0 | xn->set_conn_limit = true; |
1642 | 0 | if (old_options) |
1643 | 0 | xn->old_conn_limit = (unsigned)old_options->ConnLimit; |
1644 | 0 | } else { |
1645 | 0 | tor_assert(old_options); |
1646 | 0 | options->ConnLimit_ = old_options->ConnLimit_; |
1647 | 0 | } |
1648 | | |
1649 | | /* Adjust the port configuration so we can launch listeners. */ |
1650 | | /* 31851: some ports are relay-only */ |
1651 | 0 | if (parse_ports(options, 0, msg_out, &n_ports, NULL)) { |
1652 | 0 | if (!*msg_out) |
1653 | 0 | *msg_out = tor_strdup("Unexpected problem parsing port config"); |
1654 | 0 | goto rollback; |
1655 | 0 | } |
1656 | | |
1657 | | /* Set the hibernation state appropriately.*/ |
1658 | 0 | consider_hibernation(time(NULL)); |
1659 | | |
1660 | | /* Launch the listeners. (We do this before we setuid, so we can bind to |
1661 | | * ports under 1024.) We don't want to rebind if we're hibernating or |
1662 | | * shutting down. If networking is disabled, this will close all but the |
1663 | | * control listeners, but disable those. */ |
1664 | | /* 31851: some listeners are relay-only */ |
1665 | 0 | if (!we_are_hibernating()) { |
1666 | 0 | if (retry_all_listeners(xn->new_listeners, |
1667 | 0 | options->DisableNetwork) < 0) { |
1668 | 0 | *msg_out = tor_strdup("Failed to bind one of the listener ports."); |
1669 | 0 | goto rollback; |
1670 | 0 | } |
1671 | 0 | } |
1672 | 0 | if (options->DisableNetwork) { |
1673 | | /* Aggressively close non-controller stuff, NOW */ |
1674 | 0 | log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept " |
1675 | 0 | "non-control network connections. Shutting down all existing " |
1676 | 0 | "connections."); |
1677 | 0 | connection_mark_all_noncontrol_connections(); |
1678 | | /* We can't complete circuits until the network is re-enabled. */ |
1679 | 0 | note_that_we_maybe_cant_complete_circuits(); |
1680 | 0 | } |
1681 | |
|
1682 | | #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) |
1683 | | /* Open /dev/pf before (possibly) dropping privileges. */ |
1684 | | if (options->TransPort_set && |
1685 | | options->TransProxyType_parsed == TPT_DEFAULT) { |
1686 | | if (get_pf_socket() < 0) { |
1687 | | *msg_out = tor_strdup("Unable to open /dev/pf for transparent proxy."); |
1688 | | goto rollback; |
1689 | | } |
1690 | | } |
1691 | | #endif /* defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) */ |
1692 | |
|
1693 | 0 | return xn; |
1694 | | |
1695 | 0 | rollback: |
1696 | 0 | options_rollback_listener_transaction(xn); |
1697 | 0 | return NULL; |
1698 | 0 | } |
1699 | | |
1700 | | /** |
1701 | | * Finish configuring the listeners that started to get configured with |
1702 | | * <b>xn</b>. Frees <b>xn</b>. |
1703 | | **/ |
1704 | | static void |
1705 | | options_commit_listener_transaction(listener_transaction_t *xn) |
1706 | 0 | { |
1707 | 0 | tor_assert(xn); |
1708 | 0 | if (xn->set_conn_limit) { |
1709 | 0 | or_options_t *options = get_options_mutable(); |
1710 | | /* |
1711 | | * If we adjusted the conn limit, recompute the OOS threshold too |
1712 | | * |
1713 | | * How many possible sockets to keep in reserve? If we have lots of |
1714 | | * possible sockets, keep this below a limit and set ConnLimit_high_thresh |
1715 | | * very close to ConnLimit_, but if ConnLimit_ is low, shrink it in |
1716 | | * proportion. |
1717 | | * |
1718 | | * Somewhat arbitrarily, set socks_in_reserve to 5% of ConnLimit_, but |
1719 | | * cap it at 64. |
1720 | | */ |
1721 | 0 | int socks_in_reserve = options->ConnLimit_ / 20; |
1722 | 0 | if (socks_in_reserve > 64) socks_in_reserve = 64; |
1723 | |
|
1724 | 0 | options->ConnLimit_high_thresh = options->ConnLimit_ - socks_in_reserve; |
1725 | 0 | options->ConnLimit_low_thresh = (options->ConnLimit_ / 4) * 3; |
1726 | 0 | log_info(LD_GENERAL, |
1727 | 0 | "Recomputed OOS thresholds: ConnLimit %d, ConnLimit_ %d, " |
1728 | 0 | "ConnLimit_high_thresh %d, ConnLimit_low_thresh %d", |
1729 | 0 | options->ConnLimit, options->ConnLimit_, |
1730 | 0 | options->ConnLimit_high_thresh, |
1731 | 0 | options->ConnLimit_low_thresh); |
1732 | | |
1733 | | /* Give the OOS handler a chance with the new thresholds */ |
1734 | 0 | connection_check_oos(get_n_open_sockets(), 0); |
1735 | 0 | } |
1736 | |
|
1737 | 0 | smartlist_free(xn->new_listeners); |
1738 | 0 | tor_free(xn); |
1739 | 0 | } |
1740 | | |
1741 | | /** |
1742 | | * Revert the listener configuration changes that that started to get |
1743 | | * configured with <b>xn</b>. Frees <b>xn</b>. |
1744 | | **/ |
1745 | | static void |
1746 | | options_rollback_listener_transaction(listener_transaction_t *xn) |
1747 | 0 | { |
1748 | 0 | if (! xn) |
1749 | 0 | return; |
1750 | | |
1751 | 0 | or_options_t *options = get_options_mutable(); |
1752 | |
|
1753 | 0 | if (xn->set_conn_limit && xn->old_conn_limit) |
1754 | 0 | set_max_file_descriptors(xn->old_conn_limit, &options->ConnLimit_); |
1755 | |
|
1756 | 0 | SMARTLIST_FOREACH(xn->new_listeners, connection_t *, conn, |
1757 | 0 | { |
1758 | 0 | log_notice(LD_NET, "Closing partially-constructed %s", |
1759 | 0 | connection_describe(conn)); |
1760 | 0 | connection_close_immediate(conn); |
1761 | 0 | connection_mark_for_close(conn); |
1762 | 0 | }); |
1763 | |
|
1764 | 0 | smartlist_free(xn->new_listeners); |
1765 | 0 | tor_free(xn); |
1766 | 0 | } |
1767 | | |
1768 | | /** Structure to represent an incomplete configuration of a set of logs. |
1769 | | * |
1770 | | * This structure is generated by options_start_log_transaction(), and is |
1771 | | * either committed by options_commit_log_transaction() or rolled back by |
1772 | | * options_rollback_log_transaction(). */ |
1773 | | typedef struct log_transaction_t { |
1774 | | /** Previous lowest severity of any configured log. */ |
1775 | | int old_min_log_level; |
1776 | | /** True if we have marked the previous logs to be closed */ |
1777 | | bool logs_marked; |
1778 | | /** True if we initialized the new set of logs */ |
1779 | | bool logs_initialized; |
1780 | | /** True if our safelogging configuration is different from what it was |
1781 | | * previously (or if we are starting for the first time). */ |
1782 | | bool safelogging_changed; |
1783 | | } log_transaction_t; |
1784 | | |
1785 | | /** |
1786 | | * Start configuring our logs based on the current value of get_options(). |
1787 | | * |
1788 | | * The value <b>old_options</b> holds either the previous options object, |
1789 | | * or NULL if we're starting for the first time. |
1790 | | * |
1791 | | * On success, return a log_transaction_t that we can either roll back or |
1792 | | * commit. |
1793 | | * |
1794 | | * On failure return NULL and write a message into a newly allocated string in |
1795 | | * *<b>msg_out</b>. |
1796 | | **/ |
1797 | | STATIC log_transaction_t * |
1798 | | options_start_log_transaction(const or_options_t *old_options, |
1799 | | char **msg_out) |
1800 | 0 | { |
1801 | 0 | const or_options_t *options = get_options(); |
1802 | 0 | const bool running_tor = options->command == CMD_RUN_TOR; |
1803 | |
|
1804 | 0 | log_transaction_t *xn = tor_malloc_zero(sizeof(log_transaction_t)); |
1805 | 0 | xn->old_min_log_level = get_min_log_level(); |
1806 | 0 | xn->safelogging_changed = !old_options || |
1807 | 0 | old_options->SafeLogging_ != options->SafeLogging_; |
1808 | |
|
1809 | 0 | if (! running_tor) |
1810 | 0 | goto done; |
1811 | | |
1812 | 0 | mark_logs_temp(); /* Close current logs once new logs are open. */ |
1813 | 0 | xn->logs_marked = true; |
1814 | | /* Configure the tor_log(s) */ |
1815 | 0 | if (options_init_logs(old_options, options, 0)<0) { |
1816 | 0 | *msg_out = tor_strdup("Failed to init Log options. See logs for details."); |
1817 | 0 | options_rollback_log_transaction(xn); |
1818 | 0 | xn = NULL; |
1819 | 0 | goto done; |
1820 | 0 | } |
1821 | | |
1822 | 0 | xn->logs_initialized = true; |
1823 | |
|
1824 | 0 | done: |
1825 | 0 | return xn; |
1826 | 0 | } |
1827 | | |
1828 | | /** |
1829 | | * Finish configuring the logs that started to get configured with <b>xn</b>. |
1830 | | * Frees <b>xn</b>. |
1831 | | **/ |
1832 | | STATIC void |
1833 | | options_commit_log_transaction(log_transaction_t *xn) |
1834 | 0 | { |
1835 | 0 | const or_options_t *options = get_options(); |
1836 | 0 | tor_assert(xn); |
1837 | | |
1838 | 0 | if (xn->logs_marked) { |
1839 | 0 | log_severity_list_t *severity = |
1840 | 0 | tor_malloc_zero(sizeof(log_severity_list_t)); |
1841 | 0 | close_temp_logs(); |
1842 | 0 | add_callback_log(severity, control_event_logmsg); |
1843 | 0 | logs_set_pending_callback_callback(control_event_logmsg_pending); |
1844 | 0 | control_adjust_event_log_severity(); |
1845 | 0 | tor_free(severity); |
1846 | 0 | tor_log_update_sigsafe_err_fds(); |
1847 | 0 | } |
1848 | |
|
1849 | 0 | if (xn->logs_initialized) { |
1850 | 0 | flush_log_messages_from_startup(); |
1851 | 0 | } |
1852 | |
|
1853 | 0 | { |
1854 | 0 | const char *badness = NULL; |
1855 | 0 | int bad_safelog = 0, bad_severity = 0, new_badness = 0; |
1856 | 0 | if (options->SafeLogging_ != SAFELOG_SCRUB_ALL) { |
1857 | 0 | bad_safelog = 1; |
1858 | 0 | if (xn->safelogging_changed) |
1859 | 0 | new_badness = 1; |
1860 | 0 | } |
1861 | 0 | if (get_min_log_level() >= LOG_INFO) { |
1862 | 0 | bad_severity = 1; |
1863 | 0 | if (get_min_log_level() != xn->old_min_log_level) |
1864 | 0 | new_badness = 1; |
1865 | 0 | } |
1866 | 0 | if (bad_safelog && bad_severity) |
1867 | 0 | badness = "you disabled SafeLogging, and " |
1868 | 0 | "you're logging more than \"notice\""; |
1869 | 0 | else if (bad_safelog) |
1870 | 0 | badness = "you disabled SafeLogging"; |
1871 | 0 | else |
1872 | 0 | badness = "you're logging more than \"notice\""; |
1873 | 0 | if (new_badness) |
1874 | 0 | log_warn(LD_GENERAL, "Your log may contain sensitive information - %s. " |
1875 | 0 | "Don't log unless it serves an important reason. " |
1876 | 0 | "Overwrite the log afterwards.", badness); |
1877 | 0 | } |
1878 | |
|
1879 | 0 | tor_free(xn); |
1880 | 0 | } |
1881 | | |
1882 | | /** |
1883 | | * Revert the log configuration changes that that started to get configured |
1884 | | * with <b>xn</b>. Frees <b>xn</b>. |
1885 | | **/ |
1886 | | STATIC void |
1887 | | options_rollback_log_transaction(log_transaction_t *xn) |
1888 | 0 | { |
1889 | 0 | if (!xn) |
1890 | 0 | return; |
1891 | | |
1892 | 0 | if (xn->logs_marked) { |
1893 | 0 | rollback_log_changes(); |
1894 | 0 | control_adjust_event_log_severity(); |
1895 | 0 | } |
1896 | |
|
1897 | 0 | tor_free(xn); |
1898 | 0 | } |
1899 | | |
1900 | | /** |
1901 | | * Fetch the active option list, and take actions based on it. All of |
1902 | | * the things we do in this function should survive being done |
1903 | | * repeatedly, OR be done only once when starting Tor. If present, |
1904 | | * <b>old_options</b> contains the previous value of the options. |
1905 | | * |
1906 | | * This function is only truly "reversible" _after_ the first time it |
1907 | | * is run. The first time that it runs, it performs some irreversible |
1908 | | * tasks in the correct sequence between the reversible option changes. |
1909 | | * |
1910 | | * Option changes should only be marked as "reversible" if they cannot |
1911 | | * be validated before switching them, but they can be switched back if |
1912 | | * some other validation fails. |
1913 | | * |
1914 | | * Return 0 if all goes well, return -1 if things went badly. |
1915 | | */ |
1916 | | MOCK_IMPL(STATIC int, |
1917 | | options_act_reversible,(const or_options_t *old_options, char **msg)) |
1918 | 0 | { |
1919 | 0 | const bool first_time = ! have_set_startup_options; |
1920 | 0 | log_transaction_t *log_transaction = NULL; |
1921 | 0 | listener_transaction_t *listener_transaction = NULL; |
1922 | 0 | int r = -1; |
1923 | | |
1924 | | /* The ordering of actions in this function is not free, sadly. |
1925 | | * |
1926 | | * First of all, we _must_ daemonize before we take all kinds of |
1927 | | * initialization actions, since they need to happen in the |
1928 | | * subprocess. |
1929 | | */ |
1930 | 0 | if (options_act_once_on_startup(msg) < 0) |
1931 | 0 | goto rollback; |
1932 | | |
1933 | | /* Once we've handled most of once-off initialization, we need to |
1934 | | * open our listeners before we switch IDs. (If we open listeners first, |
1935 | | * we might not be able to bind to low ports.) |
1936 | | */ |
1937 | 0 | listener_transaction = options_start_listener_transaction(old_options, msg); |
1938 | 0 | if (listener_transaction == NULL) |
1939 | 0 | goto rollback; |
1940 | | |
1941 | 0 | if (first_time) { |
1942 | 0 | if (options_switch_id(msg) < 0) |
1943 | 0 | goto rollback; |
1944 | 0 | } |
1945 | | |
1946 | | /* On the other hand, we need to touch the file system _after_ we |
1947 | | * switch IDs: otherwise, we'll be making directories and opening files |
1948 | | * with the wrong permissions. |
1949 | | */ |
1950 | 0 | if (first_time) { |
1951 | 0 | if (options_create_directories(msg) < 0) |
1952 | 0 | goto rollback; |
1953 | 0 | } |
1954 | | |
1955 | | /* Bail out at this point if we're not going to be a client or server: |
1956 | | * we don't run Tor itself. */ |
1957 | 0 | log_transaction = options_start_log_transaction(old_options, msg); |
1958 | 0 | if (log_transaction == NULL) |
1959 | 0 | goto rollback; |
1960 | | |
1961 | | // Commit! |
1962 | 0 | r = 0; |
1963 | |
|
1964 | 0 | options_commit_log_transaction(log_transaction); |
1965 | |
|
1966 | 0 | options_commit_listener_transaction(listener_transaction); |
1967 | |
|
1968 | 0 | goto done; |
1969 | | |
1970 | 0 | rollback: |
1971 | 0 | r = -1; |
1972 | 0 | tor_assert(*msg); |
1973 | | |
1974 | 0 | options_rollback_log_transaction(log_transaction); |
1975 | 0 | options_rollback_listener_transaction(listener_transaction); |
1976 | |
|
1977 | 0 | done: |
1978 | 0 | return r; |
1979 | 0 | } |
1980 | | |
1981 | | /** If we need to have a GEOIP ip-to-country map to run with our configured |
1982 | | * options, return 1 and set *<b>reason_out</b> to a description of why. */ |
1983 | | int |
1984 | | options_need_geoip_info(const or_options_t *options, const char **reason_out) |
1985 | 0 | { |
1986 | 0 | int bridge_usage = should_record_bridge_info(options); |
1987 | 0 | int routerset_usage = |
1988 | 0 | routerset_needs_geoip(options->EntryNodes) || |
1989 | 0 | routerset_needs_geoip(options->ExitNodes) || |
1990 | 0 | routerset_needs_geoip(options->MiddleNodes) || |
1991 | 0 | routerset_needs_geoip(options->ExcludeExitNodes) || |
1992 | 0 | routerset_needs_geoip(options->ExcludeNodes) || |
1993 | 0 | routerset_needs_geoip(options->HSLayer2Nodes) || |
1994 | 0 | routerset_needs_geoip(options->HSLayer3Nodes); |
1995 | |
|
1996 | 0 | if (routerset_usage && reason_out) { |
1997 | 0 | *reason_out = "We've been configured to use (or avoid) nodes in certain " |
1998 | 0 | "countries, and we need GEOIP information to figure out which ones they " |
1999 | 0 | "are."; |
2000 | 0 | } else if (bridge_usage && reason_out) { |
2001 | 0 | *reason_out = "We've been configured to see which countries can access " |
2002 | 0 | "us as a bridge, and we need GEOIP information to tell which countries " |
2003 | 0 | "clients are in."; |
2004 | 0 | } |
2005 | 0 | return bridge_usage || routerset_usage; |
2006 | 0 | } |
2007 | | |
2008 | | /* Used in the various options_transition_affects* functions. */ |
2009 | | #define YES_IF_CHANGED_BOOL(opt) \ |
2010 | 0 | if (!CFG_EQ_BOOL(old_options, new_options, opt)) return 1; |
2011 | | #define YES_IF_CHANGED_INT(opt) \ |
2012 | | if (!CFG_EQ_INT(old_options, new_options, opt)) return 1; |
2013 | | #define YES_IF_CHANGED_STRING(opt) \ |
2014 | | if (!CFG_EQ_STRING(old_options, new_options, opt)) return 1; |
2015 | | #define YES_IF_CHANGED_LINELIST(opt) \ |
2016 | 0 | if (!CFG_EQ_LINELIST(old_options, new_options, opt)) return 1; |
2017 | | #define YES_IF_CHANGED_SMARTLIST(opt) \ |
2018 | 0 | if (!CFG_EQ_SMARTLIST(old_options, new_options, opt)) return 1; |
2019 | | #define YES_IF_CHANGED_ROUTERSET(opt) \ |
2020 | 0 | if (!CFG_EQ_ROUTERSET(old_options, new_options, opt)) return 1; |
2021 | | |
2022 | | /** |
2023 | | * Return true if changing the configuration from <b>old</b> to <b>new</b> |
2024 | | * affects the guard subsystem. |
2025 | | */ |
2026 | | static int |
2027 | | options_transition_affects_guards(const or_options_t *old_options, |
2028 | | const or_options_t *new_options) |
2029 | 0 | { |
2030 | | /* NOTE: Make sure this function stays in sync with |
2031 | | * node_passes_guard_filter */ |
2032 | 0 | tor_assert(old_options); |
2033 | 0 | tor_assert(new_options); |
2034 | | |
2035 | 0 | YES_IF_CHANGED_BOOL(UseEntryGuards); |
2036 | 0 | YES_IF_CHANGED_BOOL(UseBridges); |
2037 | 0 | YES_IF_CHANGED_BOOL(ClientUseIPv4); |
2038 | 0 | YES_IF_CHANGED_BOOL(ClientUseIPv6); |
2039 | 0 | YES_IF_CHANGED_BOOL(FascistFirewall); |
2040 | 0 | YES_IF_CHANGED_ROUTERSET(ExcludeNodes); |
2041 | 0 | YES_IF_CHANGED_ROUTERSET(EntryNodes); |
2042 | 0 | YES_IF_CHANGED_SMARTLIST(FirewallPorts); |
2043 | 0 | YES_IF_CHANGED_LINELIST(Bridges); |
2044 | 0 | YES_IF_CHANGED_LINELIST(ReachableORAddresses); |
2045 | 0 | YES_IF_CHANGED_LINELIST(ReachableDirAddresses); |
2046 | |
|
2047 | 0 | return 0; |
2048 | 0 | } |
2049 | | |
2050 | | /** Fetch the active option list, and take actions based on it. All of the |
2051 | | * things we do should survive being done repeatedly. If present, |
2052 | | * <b>old_options</b> contains the previous value of the options. |
2053 | | * |
2054 | | * Return 0 if all goes well, return -1 if it's time to die. |
2055 | | * |
2056 | | * Note: We haven't moved all the "act on new configuration" logic |
2057 | | * the options_act* functions yet. Some is still in do_hup() and other |
2058 | | * places. |
2059 | | */ |
2060 | | MOCK_IMPL(STATIC int, |
2061 | | options_act,(const or_options_t *old_options)) |
2062 | 0 | { |
2063 | 0 | config_line_t *cl; |
2064 | 0 | or_options_t *options = get_options_mutable(); |
2065 | 0 | int running_tor = options->command == CMD_RUN_TOR; |
2066 | 0 | char *msg=NULL; |
2067 | 0 | const int transition_affects_guards = |
2068 | 0 | old_options && options_transition_affects_guards(old_options, options); |
2069 | |
|
2070 | 0 | if (options->NoExec || options->Sandbox) { |
2071 | 0 | tor_disable_spawning_background_processes(); |
2072 | 0 | } |
2073 | | |
2074 | | /* disable ptrace and later, other basic debugging techniques */ |
2075 | 0 | { |
2076 | | /* Remember if we already disabled debugger attachment */ |
2077 | 0 | static int disabled_debugger_attach = 0; |
2078 | | /* Remember if we already warned about being configured not to disable |
2079 | | * debugger attachment */ |
2080 | 0 | static int warned_debugger_attach = 0; |
2081 | | /* Don't disable debugger attachment when we're running the unit tests. */ |
2082 | 0 | if (options->DisableDebuggerAttachment && !disabled_debugger_attach && |
2083 | 0 | running_tor) { |
2084 | 0 | int ok = tor_disable_debugger_attach(); |
2085 | | /* LCOV_EXCL_START the warned_debugger_attach is 0 can't reach inside. */ |
2086 | 0 | if (warned_debugger_attach && ok == 1) { |
2087 | 0 | log_notice(LD_CONFIG, "Disabled attaching debuggers for unprivileged " |
2088 | 0 | "users."); |
2089 | 0 | } |
2090 | | /* LCOV_EXCL_STOP */ |
2091 | 0 | disabled_debugger_attach = (ok == 1); |
2092 | 0 | } else if (!options->DisableDebuggerAttachment && |
2093 | 0 | !warned_debugger_attach) { |
2094 | 0 | log_notice(LD_CONFIG, "Not disabling debugger attaching for " |
2095 | 0 | "unprivileged users."); |
2096 | 0 | warned_debugger_attach = 1; |
2097 | 0 | } |
2098 | 0 | } |
2099 | | |
2100 | | /* Write control ports to disk as appropriate */ |
2101 | 0 | control_ports_write_to_file(); |
2102 | |
|
2103 | 0 | if (running_tor && !have_lockfile()) { |
2104 | 0 | if (try_locking(options, 1) < 0) |
2105 | 0 | return -1; |
2106 | 0 | } |
2107 | | |
2108 | 0 | { |
2109 | 0 | int warning_severity = options->ProtocolWarnings ? LOG_WARN : LOG_INFO; |
2110 | 0 | set_protocol_warning_severity_level(warning_severity); |
2111 | 0 | } |
2112 | |
|
2113 | 0 | if (consider_adding_dir_servers(options, old_options) < 0) { |
2114 | | // XXXX This should get validated earlier, and committed here, to |
2115 | | // XXXX lower opportunities for reaching an error case. |
2116 | 0 | return -1; |
2117 | 0 | } |
2118 | | |
2119 | 0 | if (hs_service_non_anonymous_mode_enabled(options)) { |
2120 | 0 | log_warn(LD_GENERAL, "This copy of Tor was compiled or configured to run " |
2121 | 0 | "in a non-anonymous mode. It will provide NO ANONYMITY."); |
2122 | 0 | } |
2123 | | |
2124 | | /* 31851: OutboundBindAddressExit is relay-only */ |
2125 | 0 | if (parse_outbound_addresses(options, 0, &msg) < 0) { |
2126 | | // LCOV_EXCL_START |
2127 | 0 | log_warn(LD_BUG, "Failed parsing previously validated outbound " |
2128 | 0 | "bind addresses: %s", msg); |
2129 | 0 | tor_free(msg); |
2130 | 0 | return -1; |
2131 | | // LCOV_EXCL_STOP |
2132 | 0 | } |
2133 | | |
2134 | 0 | if (options->Bridges) { |
2135 | 0 | mark_bridge_list(); |
2136 | 0 | for (cl = options->Bridges; cl; cl = cl->next) { |
2137 | 0 | bridge_line_t *bridge_line = parse_bridge_line(cl->value); |
2138 | 0 | if (!bridge_line) { |
2139 | | // LCOV_EXCL_START |
2140 | 0 | log_warn(LD_BUG, |
2141 | 0 | "Previously validated Bridge line could not be added!"); |
2142 | 0 | return -1; |
2143 | | // LCOV_EXCL_STOP |
2144 | 0 | } |
2145 | 0 | bridge_add_from_config(bridge_line); |
2146 | 0 | } |
2147 | 0 | sweep_bridge_list(); |
2148 | 0 | } |
2149 | | |
2150 | 0 | if (running_tor && hs_config_service_all(options, 0)<0) { |
2151 | | // LCOV_EXCL_START |
2152 | 0 | log_warn(LD_BUG, |
2153 | 0 | "Previously validated hidden services line could not be added!"); |
2154 | 0 | return -1; |
2155 | | // LCOV_EXCL_STOP |
2156 | 0 | } |
2157 | | |
2158 | 0 | if (running_tor && hs_config_client_auth_all(options, 0) < 0) { |
2159 | | // LCOV_EXCL_START |
2160 | 0 | log_warn(LD_BUG, "Previously validated client authorization for " |
2161 | 0 | "hidden services could not be added!"); |
2162 | 0 | return -1; |
2163 | | // LCOV_EXCL_STOP |
2164 | 0 | } |
2165 | | |
2166 | 0 | if (running_tor && !old_options && |
2167 | 0 | options->OwningControllerFD != UINT64_MAX) { |
2168 | 0 | const unsigned ctrl_flags = |
2169 | 0 | CC_LOCAL_FD_IS_OWNER | |
2170 | 0 | CC_LOCAL_FD_IS_AUTHENTICATED; |
2171 | 0 | tor_socket_t ctrl_sock = (tor_socket_t)options->OwningControllerFD; |
2172 | 0 | if (control_connection_add_local_fd(ctrl_sock, ctrl_flags) < 0) { |
2173 | 0 | log_warn(LD_CONFIG, "Could not add local controller connection with " |
2174 | 0 | "given FD."); |
2175 | 0 | return -1; |
2176 | 0 | } |
2177 | 0 | } |
2178 | | |
2179 | | /* Load state */ |
2180 | 0 | if (! or_state_loaded() && running_tor) { |
2181 | 0 | if (or_state_load()) |
2182 | 0 | return -1; |
2183 | 0 | if (options_act_dirauth_mtbf(options) < 0) |
2184 | 0 | return -1; |
2185 | 0 | } |
2186 | | |
2187 | | /* 31851: some of the code in these functions is relay-only */ |
2188 | 0 | mark_transport_list(); |
2189 | 0 | pt_prepare_proxy_list_for_config_read(); |
2190 | 0 | if (!options->DisableNetwork) { |
2191 | 0 | if (options->ClientTransportPlugin) { |
2192 | 0 | for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { |
2193 | 0 | if (pt_parse_transport_line(options, cl->value, 0, 0) < 0) { |
2194 | | // LCOV_EXCL_START |
2195 | 0 | log_warn(LD_BUG, |
2196 | 0 | "Previously validated ClientTransportPlugin line " |
2197 | 0 | "could not be added!"); |
2198 | 0 | return -1; |
2199 | | // LCOV_EXCL_STOP |
2200 | 0 | } |
2201 | 0 | } |
2202 | 0 | } |
2203 | 0 | } |
2204 | | |
2205 | 0 | if (options_act_server_transport(old_options) < 0) |
2206 | 0 | return -1; |
2207 | | |
2208 | 0 | sweep_transport_list(); |
2209 | 0 | sweep_proxy_list(); |
2210 | | |
2211 | | /* Start the PT proxy configuration. By doing this configuration |
2212 | | here, we also figure out which proxies need to be restarted and |
2213 | | which not. */ |
2214 | 0 | if (pt_proxies_configuration_pending() && !net_is_disabled()) |
2215 | 0 | pt_configure_remaining_proxies(); |
2216 | | |
2217 | | /* Bail out at this point if we're not going to be a client or server: |
2218 | | * we want to not fork, and to log stuff to stderr. */ |
2219 | 0 | if (!running_tor) |
2220 | 0 | return 0; |
2221 | | |
2222 | | /* Finish backgrounding the process */ |
2223 | 0 | if (options->RunAsDaemon) { |
2224 | | /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */ |
2225 | 0 | finish_daemon(options->DataDirectory); |
2226 | 0 | } |
2227 | |
|
2228 | 0 | if (options_act_relay(old_options) < 0) |
2229 | 0 | return -1; |
2230 | | |
2231 | | /* Write our PID to the PID file. If we do not have write permissions we |
2232 | | * will log a warning and exit. */ |
2233 | 0 | if (options->PidFile && !sandbox_is_active()) { |
2234 | 0 | if (write_pidfile(options->PidFile) < 0) { |
2235 | 0 | log_err(LD_CONFIG, "Unable to write PIDFile %s", |
2236 | 0 | escaped(options->PidFile)); |
2237 | 0 | return -1; |
2238 | 0 | } |
2239 | 0 | } |
2240 | | |
2241 | | /* Register addressmap directives */ |
2242 | 0 | config_register_addressmaps(options); |
2243 | 0 | parse_virtual_addr_network(options->VirtualAddrNetworkIPv4, AF_INET,0,NULL); |
2244 | 0 | parse_virtual_addr_network(options->VirtualAddrNetworkIPv6, AF_INET6,0,NULL); |
2245 | | |
2246 | | /* Update address policies. */ |
2247 | 0 | if (policies_parse_from_options(options) < 0) { |
2248 | | /* This should be impossible, but let's be sure. */ |
2249 | 0 | log_warn(LD_BUG,"Error parsing already-validated policy options."); |
2250 | 0 | return -1; |
2251 | 0 | } |
2252 | | |
2253 | 0 | if (init_control_cookie_authentication(options->CookieAuthentication) < 0) { |
2254 | 0 | log_warn(LD_CONFIG,"Error creating control cookie authentication file."); |
2255 | 0 | return -1; |
2256 | 0 | } |
2257 | | |
2258 | 0 | monitor_owning_controller_process(options->OwningControllerProcess); |
2259 | | |
2260 | | /* reload keys as needed for rendezvous services. */ |
2261 | 0 | if (hs_service_load_all_keys() < 0) { |
2262 | 0 | log_warn(LD_GENERAL,"Error loading rendezvous service keys"); |
2263 | 0 | return -1; |
2264 | 0 | } |
2265 | | |
2266 | | /* Inform the scheduler subsystem that a configuration changed happened. It |
2267 | | * might be a change of scheduler or parameter. */ |
2268 | 0 | scheduler_conf_changed(); |
2269 | |
|
2270 | 0 | if (options_act_relay_accounting(old_options) < 0) |
2271 | 0 | return -1; |
2272 | | |
2273 | | /* Change the cell EWMA settings */ |
2274 | 0 | cmux_ewma_set_options(options, networkstatus_get_latest_consensus()); |
2275 | | |
2276 | | /* Update the BridgePassword's hashed version as needed. We store this as a |
2277 | | * digest so that we can do side-channel-proof comparisons on it. |
2278 | | */ |
2279 | 0 | if (options->BridgePassword) { |
2280 | 0 | char *http_authenticator; |
2281 | 0 | http_authenticator = alloc_http_authenticator(options->BridgePassword); |
2282 | 0 | if (!http_authenticator) { |
2283 | | // XXXX This should get validated in options_validate(). |
2284 | 0 | log_warn(LD_BUG, "Unable to allocate HTTP authenticator. Not setting " |
2285 | 0 | "BridgePassword."); |
2286 | 0 | return -1; |
2287 | 0 | } |
2288 | 0 | options->BridgePassword_AuthDigest_ = tor_malloc(DIGEST256_LEN); |
2289 | 0 | crypto_digest256(options->BridgePassword_AuthDigest_, |
2290 | 0 | http_authenticator, strlen(http_authenticator), |
2291 | 0 | DIGEST_SHA256); |
2292 | 0 | tor_free(http_authenticator); |
2293 | 0 | } |
2294 | | |
2295 | 0 | config_maybe_load_geoip_files_(options, old_options); |
2296 | |
|
2297 | 0 | if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) { |
2298 | | /* ExcludeUnknown is true or "auto" */ |
2299 | 0 | const int is_auto = options->GeoIPExcludeUnknown == -1; |
2300 | 0 | int changed; |
2301 | |
|
2302 | 0 | changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto); |
2303 | 0 | changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto); |
2304 | |
|
2305 | 0 | if (changed) |
2306 | 0 | routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto); |
2307 | 0 | } |
2308 | | |
2309 | | /* Check for transitions that need action. */ |
2310 | 0 | if (old_options) { |
2311 | 0 | int revise_trackexithosts = 0; |
2312 | 0 | int revise_automap_entries = 0; |
2313 | 0 | int abandon_circuits = 0; |
2314 | 0 | if ((options->UseEntryGuards && !old_options->UseEntryGuards) || |
2315 | 0 | options->UseBridges != old_options->UseBridges || |
2316 | 0 | (options->UseBridges && |
2317 | 0 | !config_lines_eq(options->Bridges, old_options->Bridges)) || |
2318 | 0 | !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes) || |
2319 | 0 | !routerset_equal(old_options->ExcludeExitNodes, |
2320 | 0 | options->ExcludeExitNodes) || |
2321 | 0 | !routerset_equal(old_options->EntryNodes, options->EntryNodes) || |
2322 | 0 | !routerset_equal(old_options->ExitNodes, options->ExitNodes) || |
2323 | 0 | !routerset_equal(old_options->HSLayer2Nodes, |
2324 | 0 | options->HSLayer2Nodes) || |
2325 | 0 | !routerset_equal(old_options->HSLayer3Nodes, |
2326 | 0 | options->HSLayer3Nodes) || |
2327 | 0 | !routerset_equal(old_options->MiddleNodes, options->MiddleNodes) || |
2328 | 0 | options->StrictNodes != old_options->StrictNodes) { |
2329 | 0 | log_info(LD_CIRC, |
2330 | 0 | "Changed to using entry guards or bridges, or changed " |
2331 | 0 | "preferred or excluded node lists. " |
2332 | 0 | "Abandoning previous circuits."); |
2333 | 0 | abandon_circuits = 1; |
2334 | 0 | } |
2335 | |
|
2336 | 0 | if (transition_affects_guards) { |
2337 | 0 | if (options->ReconfigDropsBridgeDescs) |
2338 | 0 | routerlist_drop_bridge_descriptors(); |
2339 | 0 | if (guards_update_all()) { |
2340 | 0 | abandon_circuits = 1; |
2341 | 0 | } |
2342 | 0 | } |
2343 | |
|
2344 | 0 | if (abandon_circuits) { |
2345 | 0 | circuit_mark_all_unused_circs(); |
2346 | 0 | circuit_mark_all_dirty_circs_as_unusable(); |
2347 | 0 | revise_trackexithosts = 1; |
2348 | 0 | } |
2349 | |
|
2350 | 0 | if (!smartlist_strings_eq(old_options->TrackHostExits, |
2351 | 0 | options->TrackHostExits)) |
2352 | 0 | revise_trackexithosts = 1; |
2353 | |
|
2354 | 0 | if (revise_trackexithosts) |
2355 | 0 | addressmap_clear_excluded_trackexithosts(options); |
2356 | |
|
2357 | 0 | if (!options->AutomapHostsOnResolve && |
2358 | 0 | old_options->AutomapHostsOnResolve) { |
2359 | 0 | revise_automap_entries = 1; |
2360 | 0 | } else { |
2361 | 0 | if (!smartlist_strings_eq(old_options->AutomapHostsSuffixes, |
2362 | 0 | options->AutomapHostsSuffixes)) |
2363 | 0 | revise_automap_entries = 1; |
2364 | 0 | else if (!opt_streq(old_options->VirtualAddrNetworkIPv4, |
2365 | 0 | options->VirtualAddrNetworkIPv4) || |
2366 | 0 | !opt_streq(old_options->VirtualAddrNetworkIPv6, |
2367 | 0 | options->VirtualAddrNetworkIPv6)) |
2368 | 0 | revise_automap_entries = 1; |
2369 | 0 | } |
2370 | |
|
2371 | 0 | if (revise_automap_entries) |
2372 | 0 | addressmap_clear_invalid_automaps(options); |
2373 | |
|
2374 | 0 | if (options_act_bridge_stats(old_options) < 0) |
2375 | 0 | return -1; |
2376 | | |
2377 | 0 | if (dns_reset()) |
2378 | 0 | return -1; |
2379 | | |
2380 | 0 | if (options_act_relay_bandwidth(old_options) < 0) |
2381 | 0 | return -1; |
2382 | | |
2383 | 0 | if (options->BandwidthRate != old_options->BandwidthRate || |
2384 | 0 | options->BandwidthBurst != old_options->BandwidthBurst) |
2385 | 0 | connection_bucket_adjust(options); |
2386 | |
|
2387 | 0 | if (options->MainloopStats != old_options->MainloopStats) { |
2388 | 0 | reset_main_loop_counters(); |
2389 | 0 | } |
2390 | 0 | } |
2391 | | |
2392 | | /* 31851: These options are relay-only, but we need to disable them if we |
2393 | | * are in client mode. In 29211, we will disable all relay options in |
2394 | | * client mode. */ |
2395 | | /* Only collect directory-request statistics on relays and bridges. */ |
2396 | 0 | options->DirReqStatistics = options->DirReqStatistics_option && |
2397 | 0 | server_mode(options); |
2398 | 0 | options->HiddenServiceStatistics = |
2399 | 0 | options->HiddenServiceStatistics_option && server_mode(options); |
2400 | | |
2401 | | /* Only collect other relay-only statistics on relays. */ |
2402 | 0 | if (!public_server_mode(options)) { |
2403 | 0 | options->CellStatistics = 0; |
2404 | 0 | options->EntryStatistics = 0; |
2405 | 0 | options->ConnDirectionStatistics = 0; |
2406 | 0 | options->ExitPortStatistics = 0; |
2407 | 0 | } |
2408 | |
|
2409 | 0 | bool print_notice = 0; |
2410 | 0 | if (options_act_relay_stats(old_options, &print_notice) < 0) |
2411 | 0 | return -1; |
2412 | 0 | if (options_act_dirauth_stats(old_options, &print_notice) < 0) |
2413 | 0 | return -1; |
2414 | 0 | if (print_notice) |
2415 | 0 | options_act_relay_stats_msg(); |
2416 | |
|
2417 | 0 | if (options_act_relay_desc(old_options) < 0) |
2418 | 0 | return -1; |
2419 | | |
2420 | 0 | if (options_act_dirauth(old_options) < 0) |
2421 | 0 | return -1; |
2422 | | |
2423 | | /* We may need to reschedule some directory stuff if our status changed. */ |
2424 | 0 | if (old_options) { |
2425 | 0 | if (!bool_eq(dirclient_fetches_dir_info_early(options), |
2426 | 0 | dirclient_fetches_dir_info_early(old_options)) || |
2427 | 0 | !bool_eq(dirclient_fetches_dir_info_later(options), |
2428 | 0 | dirclient_fetches_dir_info_later(old_options)) || |
2429 | 0 | !config_lines_eq(old_options->Bridges, options->Bridges)) { |
2430 | | /* Make sure update_router_have_minimum_dir_info() gets called. */ |
2431 | 0 | router_dir_info_changed(); |
2432 | | /* We might need to download a new consensus status later or sooner than |
2433 | | * we had expected. */ |
2434 | 0 | update_consensus_networkstatus_fetch_time(time(NULL)); |
2435 | 0 | } |
2436 | 0 | } |
2437 | |
|
2438 | 0 | if (options_act_relay_dos(old_options) < 0) |
2439 | 0 | return -1; |
2440 | 0 | if (options_act_relay_dir(old_options) < 0) |
2441 | 0 | return -1; |
2442 | | |
2443 | 0 | return 0; |
2444 | 0 | } |
2445 | | |
2446 | | /** |
2447 | | * Enumeration to describe the syntax for a command-line option. |
2448 | | **/ |
2449 | | typedef enum { |
2450 | | /** Describe an option that does not take an argument. */ |
2451 | | ARGUMENT_NONE = 0, |
2452 | | /** Describes an option that takes a single argument. */ |
2453 | | ARGUMENT_NECESSARY = 1, |
2454 | | /** Describes an option that takes a single optional argument. */ |
2455 | | ARGUMENT_OPTIONAL = 2 |
2456 | | } takes_argument_t; |
2457 | | |
2458 | | /** Table describing arguments that Tor accepts on the command line, |
2459 | | * other than those that are the same as in torrc. */ |
2460 | | static const struct { |
2461 | | /** The string that the user has to provide. */ |
2462 | | const char *name; |
2463 | | /** Optional short name. */ |
2464 | | const char *short_name; |
2465 | | /** Does this option accept an argument? */ |
2466 | | takes_argument_t takes_argument; |
2467 | | /** If not CMD_RUN_TOR, what should Tor do when it starts? */ |
2468 | | tor_cmdline_mode_t command; |
2469 | | /** If nonzero, set the quiet level to this. 1 is "hush", 2 is "quiet" */ |
2470 | | int quiet; |
2471 | | } CMDLINE_ONLY_OPTIONS[] = { |
2472 | | { .name="--torrc-file", |
2473 | | .short_name="-f", |
2474 | | .takes_argument=ARGUMENT_NECESSARY }, |
2475 | | { .name="--allow-missing-torrc" }, |
2476 | | { .name="--defaults-torrc", |
2477 | | .takes_argument=ARGUMENT_NECESSARY }, |
2478 | | { .name="--hash-password", |
2479 | | .takes_argument=ARGUMENT_NECESSARY, |
2480 | | .command=CMD_HASH_PASSWORD, |
2481 | | .quiet=QUIET_HUSH }, |
2482 | | { .name="--dump-config", |
2483 | | .takes_argument=ARGUMENT_OPTIONAL, |
2484 | | .command=CMD_DUMP_CONFIG, |
2485 | | .quiet=QUIET_SILENT }, |
2486 | | { .name="--list-fingerprint", |
2487 | | .takes_argument=ARGUMENT_OPTIONAL, |
2488 | | .command=CMD_LIST_FINGERPRINT }, |
2489 | | { .name="--keygen", |
2490 | | .command=CMD_KEYGEN }, |
2491 | | { .name="--key-expiration", |
2492 | | .takes_argument=ARGUMENT_OPTIONAL, |
2493 | | .command=CMD_KEY_EXPIRATION }, |
2494 | | { .name="--format", |
2495 | | .takes_argument=ARGUMENT_NECESSARY }, |
2496 | | { .name="--newpass" }, |
2497 | | { .name="--no-passphrase" }, |
2498 | | { .name="--passphrase-fd", |
2499 | | .takes_argument=ARGUMENT_NECESSARY }, |
2500 | | { .name="--verify-config", |
2501 | | .command=CMD_VERIFY_CONFIG }, |
2502 | | { .name="--ignore-missing-torrc" }, |
2503 | | { .name="--quiet", |
2504 | | .quiet=QUIET_SILENT }, |
2505 | | { .name="--hush", |
2506 | | .quiet=QUIET_HUSH }, |
2507 | | { .name="--version", |
2508 | | .command=CMD_IMMEDIATE, |
2509 | | .quiet=QUIET_HUSH }, |
2510 | | { .name="--list-modules", |
2511 | | .command=CMD_IMMEDIATE, |
2512 | | .quiet=QUIET_HUSH }, |
2513 | | { .name="--library-versions", |
2514 | | .command=CMD_IMMEDIATE, |
2515 | | .quiet=QUIET_HUSH }, |
2516 | | { .name="--help", |
2517 | | .short_name="-h", |
2518 | | .command=CMD_IMMEDIATE, |
2519 | | .quiet=QUIET_HUSH }, |
2520 | | { .name="--list-torrc-options", |
2521 | | .command=CMD_IMMEDIATE, |
2522 | | .quiet=QUIET_HUSH }, |
2523 | | { .name="--list-deprecated-options", |
2524 | | .command=CMD_IMMEDIATE }, |
2525 | | { .name="--nt-service" }, |
2526 | | { .name="-nt-service" }, |
2527 | | { .name="--dbg-dump-subsystem-list", |
2528 | | .command=CMD_IMMEDIATE, |
2529 | | .quiet=QUIET_HUSH }, |
2530 | | { .name=NULL }, |
2531 | | }; |
2532 | | |
2533 | | /** Helper: Read a list of configuration options from the command line. If |
2534 | | * successful, return a newly allocated parsed_cmdline_t; otherwise return |
2535 | | * NULL. |
2536 | | * |
2537 | | * If <b>ignore_errors</b> is set, try to recover from all recoverable |
2538 | | * errors and return the best command line we can. |
2539 | | */ |
2540 | | parsed_cmdline_t * |
2541 | | config_parse_commandline(int argc, char **argv, int ignore_errors) |
2542 | 0 | { |
2543 | 0 | parsed_cmdline_t *result = tor_malloc_zero(sizeof(parsed_cmdline_t)); |
2544 | 0 | result->command = CMD_RUN_TOR; |
2545 | 0 | config_line_t *param = NULL; |
2546 | |
|
2547 | 0 | config_line_t **new_cmdline = &result->cmdline_opts; |
2548 | 0 | config_line_t **new = &result->other_opts; |
2549 | |
|
2550 | 0 | char *s, *arg; |
2551 | 0 | int i = 1; |
2552 | |
|
2553 | 0 | while (i < argc) { |
2554 | 0 | unsigned command = CONFIG_LINE_NORMAL; |
2555 | 0 | takes_argument_t want_arg = ARGUMENT_NECESSARY; |
2556 | 0 | int is_cmdline = 0; |
2557 | 0 | int j; |
2558 | 0 | bool is_a_command = false; |
2559 | |
|
2560 | 0 | for (j = 0; CMDLINE_ONLY_OPTIONS[j].name != NULL; ++j) { |
2561 | 0 | if (!strcmp(argv[i], CMDLINE_ONLY_OPTIONS[j].name) || |
2562 | 0 | (CMDLINE_ONLY_OPTIONS[j].short_name && |
2563 | 0 | !strcmp(argv[i], CMDLINE_ONLY_OPTIONS[j].short_name))) { |
2564 | 0 | is_cmdline = 1; |
2565 | 0 | want_arg = CMDLINE_ONLY_OPTIONS[j].takes_argument; |
2566 | 0 | if (CMDLINE_ONLY_OPTIONS[j].command != CMD_RUN_TOR) { |
2567 | 0 | is_a_command = true; |
2568 | 0 | result->command = CMDLINE_ONLY_OPTIONS[j].command; |
2569 | 0 | } |
2570 | 0 | quiet_level_t quiet = CMDLINE_ONLY_OPTIONS[j].quiet; |
2571 | 0 | if (quiet > result->quiet_level) |
2572 | 0 | result->quiet_level = quiet; |
2573 | 0 | break; |
2574 | 0 | } |
2575 | 0 | } |
2576 | |
|
2577 | 0 | s = argv[i]; |
2578 | | |
2579 | | /* Each keyword may be prefixed with one or two dashes. */ |
2580 | 0 | if (*s == '-') |
2581 | 0 | s++; |
2582 | 0 | if (*s == '-') |
2583 | 0 | s++; |
2584 | | /* Figure out the command, if any. */ |
2585 | 0 | if (*s == '+') { |
2586 | 0 | s++; |
2587 | 0 | command = CONFIG_LINE_APPEND; |
2588 | 0 | } else if (*s == '/') { |
2589 | 0 | s++; |
2590 | 0 | command = CONFIG_LINE_CLEAR; |
2591 | | /* A 'clear' command has no argument. */ |
2592 | 0 | want_arg = 0; |
2593 | 0 | } |
2594 | |
|
2595 | 0 | const int is_last = (i == argc-1); |
2596 | |
|
2597 | 0 | if (want_arg == ARGUMENT_NECESSARY && is_last) { |
2598 | 0 | if (ignore_errors) { |
2599 | 0 | arg = tor_strdup(""); |
2600 | 0 | } else { |
2601 | 0 | log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.", |
2602 | 0 | argv[i]); |
2603 | 0 | parsed_cmdline_free(result); |
2604 | 0 | return NULL; |
2605 | 0 | } |
2606 | 0 | } else if (want_arg == ARGUMENT_OPTIONAL && |
2607 | | /* optional arguments may never start with '-'. */ |
2608 | 0 | (is_last || argv[i+1][0] == '-')) { |
2609 | 0 | arg = tor_strdup(""); |
2610 | 0 | want_arg = ARGUMENT_NONE; // prevent skipping the next flag. |
2611 | 0 | } else { |
2612 | 0 | arg = (want_arg != ARGUMENT_NONE) ? tor_strdup(argv[i+1]) : |
2613 | 0 | tor_strdup(""); |
2614 | 0 | } |
2615 | | |
2616 | 0 | param = tor_malloc_zero(sizeof(config_line_t)); |
2617 | 0 | param->key = is_cmdline ? tor_strdup(argv[i]) : |
2618 | 0 | tor_strdup(config_expand_abbrev(get_options_mgr(), s, 1, 1)); |
2619 | 0 | param->value = arg; |
2620 | 0 | param->command = command; |
2621 | 0 | param->next = NULL; |
2622 | 0 | log_debug(LD_CONFIG, "command line: parsed keyword '%s', value '%s'", |
2623 | 0 | param->key, param->value); |
2624 | |
|
2625 | 0 | if (is_a_command) { |
2626 | 0 | result->command_arg = param->value; |
2627 | 0 | } |
2628 | |
|
2629 | 0 | if (is_cmdline) { |
2630 | 0 | *new_cmdline = param; |
2631 | 0 | new_cmdline = &((*new_cmdline)->next); |
2632 | 0 | } else { |
2633 | 0 | *new = param; |
2634 | 0 | new = &((*new)->next); |
2635 | 0 | } |
2636 | |
|
2637 | 0 | i += want_arg ? 2 : 1; |
2638 | 0 | } |
2639 | | |
2640 | 0 | return result; |
2641 | 0 | } |
2642 | | |
2643 | | /** Release all storage held by <b>cmdline</b>. */ |
2644 | | void |
2645 | | parsed_cmdline_free_(parsed_cmdline_t *cmdline) |
2646 | 0 | { |
2647 | 0 | if (!cmdline) |
2648 | 0 | return; |
2649 | 0 | config_free_lines(cmdline->cmdline_opts); |
2650 | 0 | config_free_lines(cmdline->other_opts); |
2651 | 0 | tor_free(cmdline); |
2652 | 0 | } |
2653 | | |
2654 | | /** Return true iff key is a valid configuration option. */ |
2655 | | int |
2656 | | option_is_recognized(const char *key) |
2657 | 0 | { |
2658 | 0 | return config_find_option_name(get_options_mgr(), key) != NULL; |
2659 | 0 | } |
2660 | | |
2661 | | /** Return the canonical name of a configuration option, or NULL |
2662 | | * if no such option exists. */ |
2663 | | const char * |
2664 | | option_get_canonical_name(const char *key) |
2665 | 0 | { |
2666 | 0 | return config_find_option_name(get_options_mgr(), key); |
2667 | 0 | } |
2668 | | |
2669 | | /** Return a canonical list of the options assigned for key. |
2670 | | */ |
2671 | | config_line_t * |
2672 | | option_get_assignment(const or_options_t *options, const char *key) |
2673 | 0 | { |
2674 | 0 | return config_get_assigned_option(get_options_mgr(), options, key, 1); |
2675 | 0 | } |
2676 | | |
2677 | | /** Try assigning <b>list</b> to the global options. You do this by duping |
2678 | | * options, assigning list to the new one, then validating it. If it's |
2679 | | * ok, then throw out the old one and stick with the new one. Else, |
2680 | | * revert to old and return failure. Return SETOPT_OK on success, or |
2681 | | * a setopt_err_t on failure. |
2682 | | * |
2683 | | * If not success, point *<b>msg</b> to a newly allocated string describing |
2684 | | * what went wrong. |
2685 | | */ |
2686 | | setopt_err_t |
2687 | | options_trial_assign(config_line_t *list, unsigned flags, char **msg) |
2688 | 0 | { |
2689 | 0 | int r; |
2690 | 0 | or_options_t *trial_options = config_dup(get_options_mgr(), get_options()); |
2691 | |
|
2692 | 0 | if ((r=config_assign(get_options_mgr(), trial_options, |
2693 | 0 | list, flags, msg)) < 0) { |
2694 | 0 | or_options_free(trial_options); |
2695 | 0 | return r; |
2696 | 0 | } |
2697 | 0 | const or_options_t *cur_options = get_options(); |
2698 | |
|
2699 | 0 | return options_validate_and_set(cur_options, trial_options, msg); |
2700 | 0 | } |
2701 | | |
2702 | | /** Print a usage message for tor. */ |
2703 | | static void |
2704 | | print_usage(void) |
2705 | 0 | { |
2706 | 0 | printf( |
2707 | 0 | "Copyright (c) 2001-2004, Roger Dingledine\n" |
2708 | 0 | "Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n" |
2709 | 0 | "Copyright (c) 2007-2021, The Tor Project, Inc.\n\n" |
2710 | 0 | "tor -f <torrc> [args]\n" |
2711 | 0 | "See man page for options, or https://www.torproject.org/ for " |
2712 | 0 | "documentation.\n"); |
2713 | 0 | } |
2714 | | |
2715 | | /** Print all non-obsolete torrc options. */ |
2716 | | static void |
2717 | | list_torrc_options(void) |
2718 | 0 | { |
2719 | 0 | smartlist_t *vars = config_mgr_list_vars(get_options_mgr()); |
2720 | 0 | SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) { |
2721 | | /* Possibly this should check listable, rather than (or in addition to) |
2722 | | * settable. See ticket 31654. |
2723 | | */ |
2724 | 0 | if (! config_var_is_settable(var)) { |
2725 | | /* This variable cannot be set, or cannot be set by this name. */ |
2726 | 0 | continue; |
2727 | 0 | } |
2728 | 0 | printf("%s\n", var->member.name); |
2729 | 0 | } SMARTLIST_FOREACH_END(var); |
2730 | 0 | smartlist_free(vars); |
2731 | 0 | } |
2732 | | |
2733 | | /** Print all deprecated but non-obsolete torrc options. */ |
2734 | | static void |
2735 | | list_deprecated_options(void) |
2736 | 0 | { |
2737 | 0 | smartlist_t *deps = config_mgr_list_deprecated_vars(get_options_mgr()); |
2738 | | /* Possibly this should check whether the variables are listable, |
2739 | | * but currently it does not. See ticket 31654. */ |
2740 | 0 | SMARTLIST_FOREACH(deps, const char *, name, |
2741 | 0 | printf("%s\n", name)); |
2742 | 0 | smartlist_free(deps); |
2743 | 0 | } |
2744 | | |
2745 | | /** Print all compile-time modules and their enabled/disabled status. */ |
2746 | | static void |
2747 | | list_enabled_modules(void) |
2748 | 0 | { |
2749 | 0 | static const struct { |
2750 | 0 | const char *name; |
2751 | 0 | bool have; |
2752 | 0 | } list[] = { |
2753 | 0 | { "relay", have_module_relay() }, |
2754 | 0 | { "dirauth", have_module_dirauth() }, |
2755 | 0 | { "dircache", have_module_dircache() }, |
2756 | 0 | { "pow", have_module_pow() } |
2757 | 0 | }; |
2758 | |
|
2759 | 0 | for (unsigned i = 0; i < sizeof list / sizeof list[0]; i++) { |
2760 | 0 | printf("%s: %s\n", list[i].name, list[i].have ? "yes" : "no"); |
2761 | 0 | } |
2762 | 0 | } |
2763 | | |
2764 | | /** Prints compile-time and runtime library versions. */ |
2765 | | static void |
2766 | | print_library_versions(void) |
2767 | 0 | { |
2768 | 0 | printf("Tor version %s. \n", get_version()); |
2769 | 0 | printf("Library versions\tCompiled\t\tRuntime\n"); |
2770 | 0 | printf("Libevent\t\t%-15s\t\t%s\n", |
2771 | 0 | tor_libevent_get_header_version_str(), |
2772 | 0 | tor_libevent_get_version_str()); |
2773 | 0 | #ifdef ENABLE_OPENSSL |
2774 | 0 | printf("OpenSSL \t\t%-15s\t\t%s\n", |
2775 | 0 | crypto_openssl_get_header_version_str(), |
2776 | 0 | crypto_openssl_get_version_str()); |
2777 | 0 | #endif |
2778 | | #ifdef ENABLE_NSS |
2779 | | printf("NSS \t\t%-15s\t\t%s\n", |
2780 | | crypto_nss_get_header_version_str(), |
2781 | | crypto_nss_get_version_str()); |
2782 | | #endif |
2783 | 0 | if (tor_compress_supports_method(ZLIB_METHOD)) { |
2784 | 0 | printf("Zlib \t\t%-15s\t\t%s\n", |
2785 | 0 | tor_compress_version_str(ZLIB_METHOD), |
2786 | 0 | tor_compress_header_version_str(ZLIB_METHOD)); |
2787 | 0 | } |
2788 | 0 | if (tor_compress_supports_method(LZMA_METHOD)) { |
2789 | 0 | printf("Liblzma \t\t%-15s\t\t%s\n", |
2790 | 0 | tor_compress_version_str(LZMA_METHOD), |
2791 | 0 | tor_compress_header_version_str(LZMA_METHOD)); |
2792 | 0 | } |
2793 | 0 | if (tor_compress_supports_method(ZSTD_METHOD)) { |
2794 | 0 | printf("Libzstd \t\t%-15s\t\t%s\n", |
2795 | 0 | tor_compress_version_str(ZSTD_METHOD), |
2796 | 0 | tor_compress_header_version_str(ZSTD_METHOD)); |
2797 | 0 | } |
2798 | 0 | if (tor_libc_get_name()) { |
2799 | 0 | printf("%-7s \t\t%-15s\t\t%s\n", |
2800 | 0 | tor_libc_get_name(), |
2801 | 0 | tor_libc_get_header_version_str(), |
2802 | 0 | tor_libc_get_version_str()); |
2803 | 0 | } |
2804 | | //TODO: Hex versions? |
2805 | 0 | } |
2806 | | |
2807 | | /** Handles the --no-passphrase command line option. */ |
2808 | | static int |
2809 | | handle_cmdline_no_passphrase(tor_cmdline_mode_t command) |
2810 | 0 | { |
2811 | 0 | if (command == CMD_KEYGEN) { |
2812 | 0 | get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_OFF; |
2813 | 0 | return 0; |
2814 | 0 | } else { |
2815 | 0 | log_err(LD_CONFIG, "--no-passphrase specified without --keygen!"); |
2816 | 0 | return -1; |
2817 | 0 | } |
2818 | 0 | } |
2819 | | |
2820 | | /** Handles the --format command line option. */ |
2821 | | static int |
2822 | | handle_cmdline_format(tor_cmdline_mode_t command, const char *value) |
2823 | 0 | { |
2824 | 0 | if (command == CMD_KEY_EXPIRATION) { |
2825 | | // keep the same order as enum key_expiration_format |
2826 | 0 | const char *formats[] = { "iso8601", "timestamp" }; |
2827 | 0 | int format = -1; |
2828 | 0 | for (unsigned i = 0; i < ARRAY_LENGTH(formats); i++) { |
2829 | 0 | if (!strcmp(value, formats[i])) { |
2830 | 0 | format = i; |
2831 | 0 | break; |
2832 | 0 | } |
2833 | 0 | } |
2834 | |
|
2835 | 0 | if (format < 0) { |
2836 | 0 | log_err(LD_CONFIG, "Invalid --format value %s", escaped(value)); |
2837 | 0 | return -1; |
2838 | 0 | } else { |
2839 | 0 | get_options_mutable()->key_expiration_format = format; |
2840 | 0 | } |
2841 | 0 | return 0; |
2842 | 0 | } else { |
2843 | 0 | log_err(LD_CONFIG, "--format specified without --key-expiration!"); |
2844 | 0 | return -1; |
2845 | 0 | } |
2846 | 0 | } |
2847 | | |
2848 | | /** Handles the --newpass command line option. */ |
2849 | | static int |
2850 | | handle_cmdline_newpass(tor_cmdline_mode_t command) |
2851 | 0 | { |
2852 | 0 | if (command == CMD_KEYGEN) { |
2853 | 0 | get_options_mutable()->change_key_passphrase = 1; |
2854 | 0 | return 0; |
2855 | 0 | } else { |
2856 | 0 | log_err(LD_CONFIG, "--newpass specified without --keygen!"); |
2857 | 0 | return -1; |
2858 | 0 | } |
2859 | 0 | } |
2860 | | |
2861 | | /** Handles the --passphrase-fd command line option. */ |
2862 | | static int |
2863 | | handle_cmdline_passphrase_fd(tor_cmdline_mode_t command, const char *value) |
2864 | 0 | { |
2865 | 0 | if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) { |
2866 | 0 | log_err(LD_CONFIG, "--no-passphrase specified with --passphrase-fd!"); |
2867 | 0 | return -1; |
2868 | 0 | } else if (command != CMD_KEYGEN) { |
2869 | 0 | log_err(LD_CONFIG, "--passphrase-fd specified without --keygen!"); |
2870 | 0 | return -1; |
2871 | 0 | } else { |
2872 | 0 | int ok = 1; |
2873 | 0 | long fd = tor_parse_long(value, 10, 0, INT_MAX, &ok, NULL); |
2874 | 0 | if (fd < 0 || ok == 0) { |
2875 | 0 | log_err(LD_CONFIG, "Invalid --passphrase-fd value %s", escaped(value)); |
2876 | 0 | return -1; |
2877 | 0 | } |
2878 | 0 | get_options_mutable()->keygen_passphrase_fd = (int)fd; |
2879 | 0 | get_options_mutable()->use_keygen_passphrase_fd = 1; |
2880 | 0 | get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_ON; |
2881 | 0 | return 0; |
2882 | 0 | } |
2883 | 0 | } |
2884 | | |
2885 | | /** Handles the --master-key command line option. */ |
2886 | | static int |
2887 | | handle_cmdline_master_key(tor_cmdline_mode_t command, const char *value) |
2888 | 0 | { |
2889 | 0 | if (command != CMD_KEYGEN) { |
2890 | 0 | log_err(LD_CONFIG, "--master-key without --keygen!"); |
2891 | 0 | return -1; |
2892 | 0 | } else { |
2893 | 0 | get_options_mutable()->master_key_fname = tor_strdup(value); |
2894 | 0 | return 0; |
2895 | 0 | } |
2896 | 0 | } |
2897 | | |
2898 | | /* Return true if <b>options</b> is using the default authorities, and false |
2899 | | * if any authority-related option has been overridden. */ |
2900 | | int |
2901 | | using_default_dir_authorities(const or_options_t *options) |
2902 | 0 | { |
2903 | 0 | return (!options->DirAuthorities && !options->AlternateDirAuthority); |
2904 | 0 | } |
2905 | | |
2906 | | /** Return a new empty or_options_t. Used for testing. */ |
2907 | | or_options_t * |
2908 | | options_new(void) |
2909 | 16 | { |
2910 | 16 | or_options_t *options = config_new(get_options_mgr()); |
2911 | 16 | options->command = CMD_RUN_TOR; |
2912 | 16 | return options; |
2913 | 16 | } |
2914 | | |
2915 | | /** Set <b>options</b> to hold reasonable defaults for most options. |
2916 | | * Each option defaults to zero. */ |
2917 | | void |
2918 | | options_init(or_options_t *options) |
2919 | 0 | { |
2920 | 0 | config_init(get_options_mgr(), options); |
2921 | 0 | config_line_t *dflts = get_options_defaults(); |
2922 | 0 | char *msg=NULL; |
2923 | 0 | if (config_assign(get_options_mgr(), options, dflts, |
2924 | 0 | CAL_WARN_DEPRECATIONS, &msg)<0) { |
2925 | 0 | log_err(LD_BUG, "Unable to set default options: %s", msg); |
2926 | 0 | tor_free(msg); |
2927 | 0 | tor_assert_unreached(); |
2928 | 0 | } |
2929 | 0 | config_free_lines(dflts); |
2930 | 0 | tor_free(msg); |
2931 | 0 | } |
2932 | | |
2933 | | /** Return a string containing a possible configuration file that would give |
2934 | | * the configuration in <b>options</b>. If <b>minimal</b> is true, do not |
2935 | | * include options that are the same as Tor's defaults. |
2936 | | */ |
2937 | | char * |
2938 | | options_dump(const or_options_t *options, int how_to_dump) |
2939 | 0 | { |
2940 | 0 | const or_options_t *use_defaults; |
2941 | 0 | int minimal; |
2942 | 0 | switch (how_to_dump) { |
2943 | 0 | case OPTIONS_DUMP_MINIMAL: |
2944 | 0 | use_defaults = global_default_options; |
2945 | 0 | minimal = 1; |
2946 | 0 | break; |
2947 | 0 | case OPTIONS_DUMP_ALL: |
2948 | 0 | use_defaults = NULL; |
2949 | 0 | minimal = 0; |
2950 | 0 | break; |
2951 | 0 | default: |
2952 | 0 | log_warn(LD_BUG, "Bogus value for how_to_dump==%d", how_to_dump); |
2953 | 0 | return NULL; |
2954 | 0 | } |
2955 | | |
2956 | 0 | return config_dump(get_options_mgr(), use_defaults, options, minimal, 0); |
2957 | 0 | } |
2958 | | |
2959 | | /** Return 0 if every element of sl is a string holding a decimal |
2960 | | * representation of a port number, or if sl is NULL. |
2961 | | * Otherwise set *msg and return -1. */ |
2962 | | static int |
2963 | | validate_ports_csv(smartlist_t *sl, const char *name, char **msg) |
2964 | 0 | { |
2965 | 0 | int i; |
2966 | 0 | tor_assert(name); |
2967 | | |
2968 | 0 | if (!sl) |
2969 | 0 | return 0; |
2970 | | |
2971 | 0 | SMARTLIST_FOREACH(sl, const char *, cp, |
2972 | 0 | { |
2973 | 0 | i = atoi(cp); |
2974 | 0 | if (i < 1 || i > 65535) { |
2975 | 0 | tor_asprintf(msg, "Port '%s' out of range in %s", cp, name); |
2976 | 0 | return -1; |
2977 | 0 | } |
2978 | 0 | }); |
2979 | 0 | return 0; |
2980 | 0 | } |
2981 | | |
2982 | | /** If <b>value</b> exceeds ROUTER_MAX_DECLARED_BANDWIDTH, write |
2983 | | * a complaint into *<b>msg</b> using string <b>desc</b>, and return -1. |
2984 | | * Else return 0. |
2985 | | */ |
2986 | | int |
2987 | | config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg) |
2988 | 0 | { |
2989 | 0 | if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) { |
2990 | | /* This handles an understandable special case where somebody says "2gb" |
2991 | | * whereas our actual maximum is 2gb-1 (INT_MAX) */ |
2992 | 0 | --*value; |
2993 | 0 | } |
2994 | 0 | if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) { |
2995 | 0 | tor_asprintf(msg, "%s (%"PRIu64") must be at most %d", |
2996 | 0 | desc, (*value), |
2997 | 0 | ROUTER_MAX_DECLARED_BANDWIDTH); |
2998 | 0 | return -1; |
2999 | 0 | } |
3000 | 0 | return 0; |
3001 | 0 | } |
3002 | | |
3003 | | /** Highest allowable value for CircuitsAvailableTimeout. |
3004 | | * If this is too large, client connections will stay open for too long, |
3005 | | * incurring extra padding overhead. */ |
3006 | 0 | #define MAX_CIRCS_AVAILABLE_TIME (24*60*60) |
3007 | | |
3008 | | /** Lowest allowable value for MaxCircuitDirtiness; if this is too low, Tor |
3009 | | * will generate too many circuits and potentially overload the network. */ |
3010 | 0 | #define MIN_MAX_CIRCUIT_DIRTINESS 10 |
3011 | | |
3012 | | /** Highest allowable value for MaxCircuitDirtiness: prevents time_t |
3013 | | * overflows. */ |
3014 | 0 | #define MAX_MAX_CIRCUIT_DIRTINESS (30*24*60*60) |
3015 | | |
3016 | | /** Lowest allowable value for CircuitStreamTimeout; if this is too low, Tor |
3017 | | * will generate too many circuits and potentially overload the network. */ |
3018 | 0 | #define MIN_CIRCUIT_STREAM_TIMEOUT 10 |
3019 | | |
3020 | | /** Lowest recommended value for CircuitBuildTimeout; if it is set too low |
3021 | | * and LearnCircuitBuildTimeout is off, the failure rate for circuit |
3022 | | * construction may be very high. In that case, if it is set below this |
3023 | | * threshold emit a warning. |
3024 | | * */ |
3025 | 0 | #define RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT (10) |
3026 | | |
3027 | | /** |
3028 | | * Validate <b>new_options</b>. If it is valid, and it is a reasonable |
3029 | | * replacement for <b>old_options</b>, replace the previous value of the |
3030 | | * global options, and return return SETOPT_OK. |
3031 | | * |
3032 | | * If it is not valid, then free <b>new_options</b>, set *<b>msg_out</b> to a |
3033 | | * newly allocated error message, and return an error code. |
3034 | | */ |
3035 | | static setopt_err_t |
3036 | | options_validate_and_set(const or_options_t *old_options, |
3037 | | or_options_t *new_options, |
3038 | | char **msg_out) |
3039 | 0 | { |
3040 | 0 | setopt_err_t rv; |
3041 | 0 | validation_status_t vs; |
3042 | |
|
3043 | 0 | in_option_validation = 1; |
3044 | 0 | vs = config_validate(get_options_mgr(), old_options, new_options, msg_out); |
3045 | |
|
3046 | 0 | if (vs == VSTAT_TRANSITION_ERR) { |
3047 | 0 | rv = SETOPT_ERR_TRANSITION; |
3048 | 0 | goto err; |
3049 | 0 | } else if (vs < 0) { |
3050 | 0 | rv = SETOPT_ERR_PARSE; |
3051 | 0 | goto err; |
3052 | 0 | } |
3053 | 0 | in_option_validation = 0; |
3054 | |
|
3055 | 0 | if (set_options(new_options, msg_out)) { |
3056 | 0 | rv = SETOPT_ERR_SETTING; |
3057 | 0 | goto err; |
3058 | 0 | } |
3059 | | |
3060 | 0 | rv = SETOPT_OK; |
3061 | 0 | new_options = NULL; /* prevent free */ |
3062 | 0 | err: |
3063 | 0 | in_option_validation = 0; |
3064 | 0 | tor_assert(new_options == NULL || rv != SETOPT_OK); |
3065 | 0 | or_options_free(new_options); |
3066 | 0 | return rv; |
3067 | 0 | } |
3068 | | |
3069 | | #ifdef TOR_UNIT_TESTS |
3070 | | /** |
3071 | | * Return 0 if every setting in <b>options</b> is reasonable, is a |
3072 | | * permissible transition from <b>old_options</b>, and none of the |
3073 | | * testing-only settings differ from <b>default_options</b> unless in |
3074 | | * testing mode. Else return -1. Should have no side effects, except for |
3075 | | * normalizing the contents of <b>options</b>. |
3076 | | * |
3077 | | * On error, tor_strdup an error explanation into *<b>msg</b>. |
3078 | | */ |
3079 | | int |
3080 | | options_validate(const or_options_t *old_options, or_options_t *options, |
3081 | | char **msg) |
3082 | 0 | { |
3083 | 0 | validation_status_t vs; |
3084 | 0 | vs = config_validate(get_options_mgr(), old_options, options, msg); |
3085 | 0 | return vs < 0 ? -1 : 0; |
3086 | 0 | } |
3087 | | #endif /* defined(TOR_UNIT_TESTS) */ |
3088 | | |
3089 | | #define REJECT(arg) \ |
3090 | 0 | STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END |
3091 | | #if defined(__GNUC__) && __GNUC__ <= 3 |
3092 | | #define COMPLAIN(args...) \ |
3093 | | STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END |
3094 | | #else |
3095 | | #define COMPLAIN(args, ...) \ |
3096 | 0 | STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END |
3097 | | #endif /* defined(__GNUC__) && __GNUC__ <= 3 */ |
3098 | | |
3099 | | /** Log a warning message iff <b>filepath</b> is not absolute. |
3100 | | * Warning message must contain option name <b>option</b> and |
3101 | | * an absolute path that <b>filepath</b> will resolve to. |
3102 | | * |
3103 | | * In case <b>filepath</b> is absolute, do nothing. |
3104 | | * |
3105 | | * Return 1 if there were relative paths; 0 otherwise. |
3106 | | */ |
3107 | | static int |
3108 | | warn_if_option_path_is_relative(const char *option, |
3109 | | const char *filepath) |
3110 | 0 | { |
3111 | 0 | if (filepath && path_is_relative(filepath)) { |
3112 | 0 | char *abs_path = make_path_absolute(filepath); |
3113 | 0 | COMPLAIN("Path for %s (%s) is relative and will resolve to %s." |
3114 | 0 | " Is this what you wanted?", option, filepath, abs_path); |
3115 | 0 | tor_free(abs_path); |
3116 | 0 | return 1; |
3117 | 0 | } |
3118 | 0 | return 0; |
3119 | 0 | } |
3120 | | |
3121 | | /** Scan <b>options</b> for occurrences of relative file/directory |
3122 | | * paths and log a warning whenever one is found. |
3123 | | * |
3124 | | * Return 1 if there were relative paths; 0 otherwise. |
3125 | | */ |
3126 | | static int |
3127 | | warn_about_relative_paths(const or_options_t *options) |
3128 | 0 | { |
3129 | 0 | tor_assert(options); |
3130 | 0 | int n = 0; |
3131 | 0 | const config_mgr_t *mgr = get_options_mgr(); |
3132 | |
|
3133 | 0 | smartlist_t *vars = config_mgr_list_vars(mgr); |
3134 | 0 | SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, cv) { |
3135 | 0 | config_line_t *line; |
3136 | 0 | if (cv->member.type != CONFIG_TYPE_FILENAME) |
3137 | 0 | continue; |
3138 | 0 | const char *name = cv->member.name; |
3139 | 0 | line = config_get_assigned_option(mgr, options, name, 0); |
3140 | 0 | if (line) |
3141 | 0 | n += warn_if_option_path_is_relative(name, line->value); |
3142 | 0 | config_free_lines(line); |
3143 | 0 | } SMARTLIST_FOREACH_END(cv); |
3144 | 0 | smartlist_free(vars); |
3145 | |
|
3146 | 0 | for (config_line_t *hs_line = options->RendConfigLines; hs_line; |
3147 | 0 | hs_line = hs_line->next) { |
3148 | 0 | if (!strcasecmp(hs_line->key, "HiddenServiceDir")) |
3149 | 0 | n += warn_if_option_path_is_relative("HiddenServiceDir",hs_line->value); |
3150 | 0 | } |
3151 | 0 | return n != 0; |
3152 | 0 | } |
3153 | | |
3154 | | /* Validate options related to the scheduler. From the Schedulers list, the |
3155 | | * SchedulerTypes_ list is created with int values so once we select the |
3156 | | * scheduler, which can happen anytime at runtime, we don't have to parse |
3157 | | * strings and thus be quick. |
3158 | | * |
3159 | | * Return 0 on success else -1 and msg is set with an error message. */ |
3160 | | static int |
3161 | | options_validate_scheduler(or_options_t *options, char **msg) |
3162 | 0 | { |
3163 | 0 | tor_assert(options); |
3164 | 0 | tor_assert(msg); |
3165 | | |
3166 | 0 | if (!options->Schedulers || smartlist_len(options->Schedulers) == 0) { |
3167 | 0 | REJECT("Empty Schedulers list. Either remove the option so the defaults " |
3168 | 0 | "can be used or set at least one value."); |
3169 | 0 | } |
3170 | | /* Ok, we do have scheduler types, validate them. */ |
3171 | 0 | if (options->SchedulerTypes_) { |
3172 | 0 | SMARTLIST_FOREACH(options->SchedulerTypes_, int *, iptr, tor_free(iptr)); |
3173 | 0 | smartlist_free(options->SchedulerTypes_); |
3174 | 0 | } |
3175 | 0 | options->SchedulerTypes_ = smartlist_new(); |
3176 | 0 | SMARTLIST_FOREACH_BEGIN(options->Schedulers, const char *, type) { |
3177 | 0 | int *sched_type; |
3178 | 0 | if (!strcasecmp("KISTLite", type)) { |
3179 | 0 | sched_type = tor_malloc_zero(sizeof(int)); |
3180 | 0 | *sched_type = SCHEDULER_KIST_LITE; |
3181 | 0 | smartlist_add(options->SchedulerTypes_, sched_type); |
3182 | 0 | } else if (!strcasecmp("KIST", type)) { |
3183 | 0 | sched_type = tor_malloc_zero(sizeof(int)); |
3184 | 0 | *sched_type = SCHEDULER_KIST; |
3185 | 0 | smartlist_add(options->SchedulerTypes_, sched_type); |
3186 | 0 | } else if (!strcasecmp("Vanilla", type)) { |
3187 | 0 | sched_type = tor_malloc_zero(sizeof(int)); |
3188 | 0 | *sched_type = SCHEDULER_VANILLA; |
3189 | 0 | smartlist_add(options->SchedulerTypes_, sched_type); |
3190 | 0 | } else { |
3191 | 0 | tor_asprintf(msg, "Unknown type %s in option Schedulers. " |
3192 | 0 | "Possible values are KIST, KISTLite and Vanilla.", |
3193 | 0 | escaped(type)); |
3194 | 0 | return -1; |
3195 | 0 | } |
3196 | 0 | } SMARTLIST_FOREACH_END(type); |
3197 | | |
3198 | 0 | if (options->KISTSockBufSizeFactor < 0) { |
3199 | 0 | REJECT("KISTSockBufSizeFactor must be at least 0"); |
3200 | 0 | } |
3201 | | |
3202 | | /* Don't need to validate that the Interval is less than anything because |
3203 | | * zero is valid and all negative values are valid. */ |
3204 | 0 | if (options->KISTSchedRunInterval > KIST_SCHED_RUN_INTERVAL_MAX) { |
3205 | 0 | tor_asprintf(msg, "KISTSchedRunInterval must not be more than %d (ms)", |
3206 | 0 | KIST_SCHED_RUN_INTERVAL_MAX); |
3207 | 0 | return -1; |
3208 | 0 | } |
3209 | | |
3210 | 0 | return 0; |
3211 | 0 | } |
3212 | | |
3213 | | /* Validate options related to single onion services. |
3214 | | * Modifies some options that are incompatible with single onion services. |
3215 | | * On failure returns -1, and sets *msg to an error string. |
3216 | | * Returns 0 on success. */ |
3217 | | STATIC int |
3218 | | options_validate_single_onion(or_options_t *options, char **msg) |
3219 | 0 | { |
3220 | | /* The two single onion service options must have matching values. */ |
3221 | 0 | if (options->HiddenServiceSingleHopMode && |
3222 | 0 | !options->HiddenServiceNonAnonymousMode) { |
3223 | 0 | REJECT("HiddenServiceSingleHopMode does not provide any server anonymity. " |
3224 | 0 | "It must be used with HiddenServiceNonAnonymousMode set to 1."); |
3225 | 0 | } |
3226 | 0 | if (options->HiddenServiceNonAnonymousMode && |
3227 | 0 | !options->HiddenServiceSingleHopMode) { |
3228 | 0 | REJECT("HiddenServiceNonAnonymousMode does not provide any server " |
3229 | 0 | "anonymity. It must be used with HiddenServiceSingleHopMode set to " |
3230 | 0 | "1."); |
3231 | 0 | } |
3232 | | |
3233 | | /* Now that we've checked that the two options are consistent, we can safely |
3234 | | * call the hs_service_* functions that abstract these options. */ |
3235 | | |
3236 | | /* If you run an anonymous client with an active Single Onion service, the |
3237 | | * client loses anonymity. */ |
3238 | 0 | const int client_port_set = (options->SocksPort_set || |
3239 | 0 | options->TransPort_set || |
3240 | 0 | options->NATDPort_set || |
3241 | 0 | options->DNSPort_set || |
3242 | 0 | options->HTTPTunnelPort_set); |
3243 | 0 | if (hs_service_non_anonymous_mode_enabled(options) && client_port_set) { |
3244 | 0 | REJECT("HiddenServiceNonAnonymousMode is incompatible with using Tor as " |
3245 | 0 | "an anonymous client. Please set Socks/Trans/NATD/DNSPort to 0, or " |
3246 | 0 | "revert HiddenServiceNonAnonymousMode to 0."); |
3247 | 0 | } |
3248 | | |
3249 | 0 | if (hs_service_allow_non_anonymous_connection(options) |
3250 | 0 | && options->UseEntryGuards) { |
3251 | | /* Single Onion services only use entry guards when uploading descriptors; |
3252 | | * all other connections are one-hop. Further, Single Onions causes the |
3253 | | * hidden service code to do things which break the path bias |
3254 | | * detector, and it's far easier to turn off entry guards (and |
3255 | | * thus the path bias detector with it) than to figure out how to |
3256 | | * make path bias compatible with single onions. |
3257 | | */ |
3258 | 0 | log_notice(LD_CONFIG, |
3259 | 0 | "HiddenServiceSingleHopMode is enabled; disabling " |
3260 | 0 | "UseEntryGuards."); |
3261 | 0 | options->UseEntryGuards = 0; |
3262 | 0 | } |
3263 | |
|
3264 | 0 | return 0; |
3265 | 0 | } |
3266 | | |
3267 | | /** |
3268 | | * Legacy validation/normalization callback for or_options_t. See |
3269 | | * legacy_validate_fn_t for more information. |
3270 | | */ |
3271 | | static int |
3272 | | options_validate_cb(const void *old_options_, void *options_, char **msg) |
3273 | 0 | { |
3274 | 0 | if (old_options_) |
3275 | 0 | CHECK_OPTIONS_MAGIC(old_options_); |
3276 | 0 | CHECK_OPTIONS_MAGIC(options_); |
3277 | 0 | const or_options_t *old_options = old_options_; |
3278 | 0 | or_options_t *options = options_; |
3279 | |
|
3280 | 0 | config_line_t *cl; |
3281 | 0 | int n_ports=0; |
3282 | 0 | int world_writable_control_socket=0; |
3283 | |
|
3284 | 0 | tor_assert(msg); |
3285 | 0 | *msg = NULL; |
3286 | |
|
3287 | 0 | if (parse_ports(options, 1, msg, &n_ports, |
3288 | 0 | &world_writable_control_socket) < 0) |
3289 | 0 | return -1; |
3290 | | |
3291 | | #ifndef HAVE_SYS_UN_H |
3292 | | if (options->ControlSocket || options->ControlSocketsGroupWritable) { |
3293 | | *msg = tor_strdup("Unix domain sockets (ControlSocket) not supported " |
3294 | | "on this OS/with this build."); |
3295 | | return -1; |
3296 | | } |
3297 | | #else /* defined(HAVE_SYS_UN_H) */ |
3298 | 0 | if (options->ControlSocketsGroupWritable && !options->ControlSocket) { |
3299 | 0 | *msg = tor_strdup("Setting ControlSocketsGroupWritable without setting " |
3300 | 0 | "a ControlSocket makes no sense."); |
3301 | 0 | return -1; |
3302 | 0 | } |
3303 | 0 | #endif /* !defined(HAVE_SYS_UN_H) */ |
3304 | | |
3305 | | /* Set UseEntryGuards from the configured value, before we check it below. |
3306 | | * We change UseEntryGuards when it's incompatible with other options, |
3307 | | * but leave UseEntryGuards_option with the original value. |
3308 | | * Always use the value of UseEntryGuards, not UseEntryGuards_option. */ |
3309 | 0 | options->UseEntryGuards = options->UseEntryGuards_option; |
3310 | |
|
3311 | 0 | if (options_validate_relay_os(old_options, options, msg) < 0) |
3312 | 0 | return -1; |
3313 | | |
3314 | | /* 31851: OutboundBindAddressExit is unused in client mode */ |
3315 | 0 | if (parse_outbound_addresses(options, 1, msg) < 0) |
3316 | 0 | return -1; |
3317 | | |
3318 | 0 | if (validate_data_directories(options)<0) |
3319 | 0 | REJECT("Invalid DataDirectory"); |
3320 | | |
3321 | | /* need to check for relative paths after we populate |
3322 | | * options->DataDirectory (just above). */ |
3323 | 0 | if (warn_about_relative_paths(options) && options->RunAsDaemon) { |
3324 | 0 | REJECT("You have specified at least one relative path (see above) " |
3325 | 0 | "with the RunAsDaemon option. RunAsDaemon is not compatible " |
3326 | 0 | "with relative paths."); |
3327 | 0 | } |
3328 | | |
3329 | 0 | if (options_validate_relay_info(old_options, options, msg) < 0) |
3330 | 0 | return -1; |
3331 | | |
3332 | | /* 31851: this function is currently a no-op in client mode */ |
3333 | 0 | check_network_configuration(server_mode(options)); |
3334 | | |
3335 | | /* Validate the tor_log(s) */ |
3336 | 0 | if (options_init_logs(old_options, options, 1)<0) |
3337 | 0 | REJECT("Failed to validate Log options. See logs for details."); |
3338 | | |
3339 | | /* XXXX require that the only port not be DirPort? */ |
3340 | | /* XXXX require that at least one port be listened-upon. */ |
3341 | 0 | if (n_ports == 0 && !options->RendConfigLines) |
3342 | 0 | log_warn(LD_CONFIG, |
3343 | 0 | "SocksPort, TransPort, NATDPort, DNSPort, and ORPort are all " |
3344 | 0 | "undefined, and there aren't any hidden services configured. " |
3345 | 0 | "Tor will still run, but probably won't do anything."); |
3346 | |
|
3347 | 0 | options->TransProxyType_parsed = TPT_DEFAULT; |
3348 | 0 | #ifdef USE_TRANSPARENT |
3349 | 0 | if (options->TransProxyType) { |
3350 | 0 | if (!strcasecmp(options->TransProxyType, "default")) { |
3351 | 0 | options->TransProxyType_parsed = TPT_DEFAULT; |
3352 | 0 | } else if (!strcasecmp(options->TransProxyType, "pf-divert")) { |
3353 | 0 | #if !defined(OpenBSD) && !defined(DARWIN) |
3354 | | /* Later versions of OS X have pf */ |
3355 | 0 | REJECT("pf-divert is a OpenBSD-specific " |
3356 | 0 | "and OS X/Darwin-specific feature."); |
3357 | | #else |
3358 | | options->TransProxyType_parsed = TPT_PF_DIVERT; |
3359 | | #endif /* !defined(OpenBSD) && !defined(DARWIN) */ |
3360 | 0 | } else if (!strcasecmp(options->TransProxyType, "tproxy")) { |
3361 | | #if !defined(__linux__) |
3362 | | REJECT("TPROXY is a Linux-specific feature."); |
3363 | | #else |
3364 | 0 | options->TransProxyType_parsed = TPT_TPROXY; |
3365 | 0 | #endif |
3366 | 0 | } else if (!strcasecmp(options->TransProxyType, "ipfw")) { |
3367 | 0 | #ifndef KERNEL_MAY_SUPPORT_IPFW |
3368 | | /* Earlier versions of OS X have ipfw */ |
3369 | 0 | REJECT("ipfw is a FreeBSD-specific " |
3370 | 0 | "and OS X/Darwin-specific feature."); |
3371 | | #else |
3372 | | options->TransProxyType_parsed = TPT_IPFW; |
3373 | | #endif /* !defined(KERNEL_MAY_SUPPORT_IPFW) */ |
3374 | 0 | } else { |
3375 | 0 | REJECT("Unrecognized value for TransProxyType"); |
3376 | 0 | } |
3377 | | |
3378 | 0 | if (strcasecmp(options->TransProxyType, "default") && |
3379 | 0 | !options->TransPort_set) { |
3380 | 0 | REJECT("Cannot use TransProxyType without any valid TransPort."); |
3381 | 0 | } |
3382 | 0 | } |
3383 | | #else /* !defined(USE_TRANSPARENT) */ |
3384 | | if (options->TransPort_set) |
3385 | | REJECT("TransPort is disabled in this build."); |
3386 | | #endif /* defined(USE_TRANSPARENT) */ |
3387 | | |
3388 | 0 | if (options->TokenBucketRefillInterval <= 0 |
3389 | 0 | || options->TokenBucketRefillInterval > 1000) { |
3390 | 0 | REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive."); |
3391 | 0 | } |
3392 | | |
3393 | 0 | if (options->AssumeReachable && options->AssumeReachableIPv6 == 0) { |
3394 | 0 | REJECT("Cannot set AssumeReachable 1 and AssumeReachableIPv6 0."); |
3395 | 0 | } |
3396 | | |
3397 | 0 | if (options->ExcludeExitNodes || options->ExcludeNodes) { |
3398 | 0 | options->ExcludeExitNodesUnion_ = routerset_new(); |
3399 | 0 | routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes); |
3400 | 0 | routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeNodes); |
3401 | 0 | } |
3402 | |
|
3403 | 0 | if (options->NodeFamilies) { |
3404 | 0 | options->NodeFamilySets = smartlist_new(); |
3405 | 0 | for (cl = options->NodeFamilies; cl; cl = cl->next) { |
3406 | 0 | routerset_t *rs = routerset_new(); |
3407 | 0 | if (routerset_parse(rs, cl->value, cl->key) == 0) { |
3408 | 0 | smartlist_add(options->NodeFamilySets, rs); |
3409 | 0 | } else { |
3410 | 0 | routerset_free(rs); |
3411 | 0 | } |
3412 | 0 | } |
3413 | 0 | } |
3414 | |
|
3415 | 0 | if (options->ExcludeNodes && options->StrictNodes) { |
3416 | 0 | COMPLAIN("You have asked to exclude certain relays from all positions " |
3417 | 0 | "in your circuits. Expect hidden services and other Tor " |
3418 | 0 | "features to be broken in unpredictable ways."); |
3419 | 0 | } |
3420 | |
|
3421 | 0 | if (options_validate_dirauth_mode(old_options, options, msg) < 0) |
3422 | 0 | return -1; |
3423 | | |
3424 | 0 | if (options->FetchDirInfoExtraEarly && !options->FetchDirInfoEarly) |
3425 | 0 | REJECT("FetchDirInfoExtraEarly requires that you also set " |
3426 | 0 | "FetchDirInfoEarly"); |
3427 | | |
3428 | 0 | if (options->ConnLimit <= 0) { |
3429 | 0 | tor_asprintf(msg, |
3430 | 0 | "ConnLimit must be greater than 0, but was set to %d", |
3431 | 0 | options->ConnLimit); |
3432 | 0 | return -1; |
3433 | 0 | } |
3434 | | |
3435 | 0 | if (options->PathsNeededToBuildCircuits >= 0.0) { |
3436 | 0 | if (options->PathsNeededToBuildCircuits < 0.25) { |
3437 | 0 | log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too low. Increasing " |
3438 | 0 | "to 0.25"); |
3439 | 0 | options->PathsNeededToBuildCircuits = 0.25; |
3440 | 0 | } else if (options->PathsNeededToBuildCircuits > 0.95) { |
3441 | 0 | log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too high. Decreasing " |
3442 | 0 | "to 0.95"); |
3443 | 0 | options->PathsNeededToBuildCircuits = 0.95; |
3444 | 0 | } |
3445 | 0 | } |
3446 | |
|
3447 | 0 | if (options->MaxClientCircuitsPending <= 0 || |
3448 | 0 | options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) { |
3449 | 0 | tor_asprintf(msg, |
3450 | 0 | "MaxClientCircuitsPending must be between 1 and %d, but " |
3451 | 0 | "was set to %d", MAX_MAX_CLIENT_CIRCUITS_PENDING, |
3452 | 0 | options->MaxClientCircuitsPending); |
3453 | 0 | return -1; |
3454 | 0 | } |
3455 | | |
3456 | 0 | if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0) |
3457 | 0 | return -1; |
3458 | | |
3459 | 0 | if (validate_ports_csv(options->LongLivedPorts, "LongLivedPorts", msg) < 0) |
3460 | 0 | return -1; |
3461 | | |
3462 | 0 | if (validate_ports_csv(options->RejectPlaintextPorts, |
3463 | 0 | "RejectPlaintextPorts", msg) < 0) |
3464 | 0 | return -1; |
3465 | | |
3466 | 0 | if (validate_ports_csv(options->WarnPlaintextPorts, |
3467 | 0 | "WarnPlaintextPorts", msg) < 0) |
3468 | 0 | return -1; |
3469 | | |
3470 | 0 | if (options->FascistFirewall && !options->ReachableAddresses) { |
3471 | 0 | if (options->FirewallPorts && smartlist_len(options->FirewallPorts)) { |
3472 | | /* We already have firewall ports set, so migrate them to |
3473 | | * ReachableAddresses, which will set ReachableORAddresses and |
3474 | | * ReachableDirAddresses if they aren't set explicitly. */ |
3475 | 0 | smartlist_t *instead = smartlist_new(); |
3476 | 0 | config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t)); |
3477 | 0 | new_line->key = tor_strdup("ReachableAddresses"); |
3478 | | /* If we're configured with the old format, we need to prepend some |
3479 | | * open ports. */ |
3480 | 0 | SMARTLIST_FOREACH(options->FirewallPorts, const char *, portno, |
3481 | 0 | { |
3482 | 0 | int p = atoi(portno); |
3483 | 0 | if (p<0) continue; |
3484 | 0 | smartlist_add_asprintf(instead, "*:%d", p); |
3485 | 0 | }); |
3486 | 0 | new_line->value = smartlist_join_strings(instead,",",0,NULL); |
3487 | | /* These have been deprecated since 0.1.1.5-alpha-cvs */ |
3488 | 0 | log_notice(LD_CONFIG, |
3489 | 0 | "Converting FascistFirewall and FirewallPorts " |
3490 | 0 | "config options to new format: \"ReachableAddresses %s\"", |
3491 | 0 | new_line->value); |
3492 | 0 | options->ReachableAddresses = new_line; |
3493 | 0 | SMARTLIST_FOREACH(instead, char *, cp, tor_free(cp)); |
3494 | 0 | smartlist_free(instead); |
3495 | 0 | } else { |
3496 | | /* We do not have FirewallPorts set, so add 80 to |
3497 | | * ReachableDirAddresses, and 443 to ReachableORAddresses. */ |
3498 | 0 | if (!options->ReachableDirAddresses) { |
3499 | 0 | config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t)); |
3500 | 0 | new_line->key = tor_strdup("ReachableDirAddresses"); |
3501 | 0 | new_line->value = tor_strdup("*:80"); |
3502 | 0 | options->ReachableDirAddresses = new_line; |
3503 | 0 | log_notice(LD_CONFIG, "Converting FascistFirewall config option " |
3504 | 0 | "to new format: \"ReachableDirAddresses *:80\""); |
3505 | 0 | } |
3506 | 0 | if (!options->ReachableORAddresses) { |
3507 | 0 | config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t)); |
3508 | 0 | new_line->key = tor_strdup("ReachableORAddresses"); |
3509 | 0 | new_line->value = tor_strdup("*:443"); |
3510 | 0 | options->ReachableORAddresses = new_line; |
3511 | 0 | log_notice(LD_CONFIG, "Converting FascistFirewall config option " |
3512 | 0 | "to new format: \"ReachableORAddresses *:443\""); |
3513 | 0 | } |
3514 | 0 | } |
3515 | 0 | } |
3516 | |
|
3517 | 0 | if ((options->ReachableAddresses || |
3518 | 0 | options->ReachableORAddresses || |
3519 | 0 | options->ReachableDirAddresses || |
3520 | 0 | options->ClientUseIPv4 == 0) && |
3521 | 0 | server_mode(options)) |
3522 | 0 | REJECT("Servers must be able to freely connect to the rest " |
3523 | 0 | "of the Internet, so they must not set Reachable*Addresses " |
3524 | 0 | "or FascistFirewall or FirewallPorts or ClientUseIPv4 0."); |
3525 | | |
3526 | 0 | if (options->UseBridges && |
3527 | 0 | server_mode(options)) |
3528 | 0 | REJECT("Servers must be able to freely connect to the rest " |
3529 | 0 | "of the Internet, so they must not set UseBridges."); |
3530 | | |
3531 | | /* If both of these are set, we'll end up with funny behavior where we |
3532 | | * demand enough entrynodes be up and running else we won't build |
3533 | | * circuits, yet we never actually use them. */ |
3534 | 0 | if (options->UseBridges && options->EntryNodes) |
3535 | 0 | REJECT("You cannot set both UseBridges and EntryNodes."); |
3536 | | |
3537 | | /* If we have UseBridges as 1 and UseEntryGuards as 0, we end up bypassing |
3538 | | * the use of bridges */ |
3539 | 0 | if (options->UseBridges && !options->UseEntryGuards) |
3540 | 0 | REJECT("Setting UseBridges requires also setting UseEntryGuards."); |
3541 | | |
3542 | 0 | options->MaxMemInQueues = |
3543 | 0 | compute_real_max_mem_in_queues(options->MaxMemInQueues_raw, |
3544 | 0 | server_mode(options)); |
3545 | 0 | options->MaxMemInQueues_low_threshold = (options->MaxMemInQueues / 4) * 3; |
3546 | |
|
3547 | 0 | if (!options->SafeLogging || |
3548 | 0 | !strcasecmp(options->SafeLogging, "0")) { |
3549 | 0 | options->SafeLogging_ = SAFELOG_SCRUB_NONE; |
3550 | 0 | } else if (!strcasecmp(options->SafeLogging, "relay")) { |
3551 | 0 | options->SafeLogging_ = SAFELOG_SCRUB_RELAY; |
3552 | 0 | } else if (!strcasecmp(options->SafeLogging, "1")) { |
3553 | 0 | options->SafeLogging_ = SAFELOG_SCRUB_ALL; |
3554 | 0 | } else { |
3555 | 0 | tor_asprintf(msg, |
3556 | 0 | "Unrecognized value '%s' in SafeLogging", |
3557 | 0 | escaped(options->SafeLogging)); |
3558 | 0 | return -1; |
3559 | 0 | } |
3560 | | |
3561 | 0 | options->ConfluxClientUX = CONFLUX_UX_HIGH_THROUGHPUT; |
3562 | 0 | if (options->ConfluxClientUX_option) { |
3563 | 0 | if (!strcmp(options->ConfluxClientUX_option, "latency")) |
3564 | 0 | options->ConfluxClientUX = CONFLUX_UX_MIN_LATENCY; |
3565 | 0 | else if (!strcmp(options->ConfluxClientUX_option, "throughput")) |
3566 | 0 | options->ConfluxClientUX = CONFLUX_UX_HIGH_THROUGHPUT; |
3567 | 0 | else if (!strcmp(options->ConfluxClientUX_option, "latency_lowmem")) |
3568 | 0 | options->ConfluxClientUX = CONFLUX_UX_LOW_MEM_LATENCY; |
3569 | 0 | else if (!strcmp(options->ConfluxClientUX_option, "throughput_lowmem")) |
3570 | 0 | options->ConfluxClientUX = CONFLUX_UX_LOW_MEM_THROUGHPUT; |
3571 | 0 | else |
3572 | 0 | REJECT("ConfluxClientUX must be 'latency', 'throughput, " |
3573 | 0 | "'latency_lowmem', or 'throughput_lowmem'"); |
3574 | 0 | } |
3575 | | |
3576 | 0 | if (options_validate_publish_server(old_options, options, msg) < 0) |
3577 | 0 | return -1; |
3578 | | |
3579 | 0 | if (options_validate_relay_padding(old_options, options, msg) < 0) |
3580 | 0 | return -1; |
3581 | | |
3582 | | /* Check the Single Onion Service options */ |
3583 | 0 | if (options_validate_single_onion(options, msg) < 0) |
3584 | 0 | return -1; |
3585 | | |
3586 | 0 | if (options->CircuitsAvailableTimeout > MAX_CIRCS_AVAILABLE_TIME) { |
3587 | | // options_t is immutable for new code (the above code is older), |
3588 | | // so just make the user fix the value themselves rather than |
3589 | | // silently keep a shadow value lower than what they asked for. |
3590 | 0 | REJECT("CircuitsAvailableTimeout is too large. Max is 24 hours."); |
3591 | 0 | } |
3592 | | |
3593 | 0 | if (options->EntryNodes && !options->UseEntryGuards) { |
3594 | 0 | REJECT("If EntryNodes is set, UseEntryGuards must be enabled."); |
3595 | 0 | } |
3596 | | |
3597 | 0 | if (!(options->UseEntryGuards) && |
3598 | 0 | (options->RendConfigLines != NULL) && |
3599 | 0 | !hs_service_allow_non_anonymous_connection(options)) { |
3600 | 0 | log_warn(LD_CONFIG, |
3601 | 0 | "UseEntryGuards is disabled, but you have configured one or more " |
3602 | 0 | "hidden services on this Tor instance. Your hidden services " |
3603 | 0 | "will be very easy to locate using a well-known attack -- see " |
3604 | 0 | "https://freehaven.net/anonbib/#hs-attack06 for details."); |
3605 | 0 | } |
3606 | |
|
3607 | 0 | if (options->NumPrimaryGuards && options->NumEntryGuards && |
3608 | 0 | options->NumEntryGuards > options->NumPrimaryGuards) { |
3609 | 0 | REJECT("NumEntryGuards must not be greater than NumPrimaryGuards."); |
3610 | 0 | } |
3611 | | |
3612 | 0 | if (options->EntryNodes && |
3613 | 0 | routerset_is_list(options->EntryNodes) && |
3614 | 0 | (routerset_len(options->EntryNodes) == 1) && |
3615 | 0 | (options->RendConfigLines != NULL)) { |
3616 | 0 | tor_asprintf(msg, |
3617 | 0 | "You have one single EntryNodes and at least one hidden service " |
3618 | 0 | "configured. This is bad because it's very easy to locate your " |
3619 | 0 | "entry guard which can then lead to the deanonymization of your " |
3620 | 0 | "hidden service -- for more details, see " |
3621 | 0 | "https://bugs.torproject.org/tpo/core/tor/14917. " |
3622 | 0 | "For this reason, the use of one EntryNodes with an hidden " |
3623 | 0 | "service is prohibited until a better solution is found."); |
3624 | 0 | return -1; |
3625 | 0 | } |
3626 | | |
3627 | | /* Inform the hidden service operator that pinning EntryNodes can possibly |
3628 | | * be harmful for the service anonymity. */ |
3629 | 0 | if (options->EntryNodes && |
3630 | 0 | routerset_is_list(options->EntryNodes) && |
3631 | 0 | (options->RendConfigLines != NULL)) { |
3632 | 0 | log_warn(LD_CONFIG, |
3633 | 0 | "EntryNodes is set with multiple entries and at least one " |
3634 | 0 | "hidden service is configured. Pinning entry nodes can possibly " |
3635 | 0 | "be harmful to the service anonymity. Because of this, we " |
3636 | 0 | "recommend you either don't do that or make sure you know what " |
3637 | 0 | "you are doing. For more details, please look at " |
3638 | 0 | "https://bugs.torproject.org/tpo/core/tor/21155."); |
3639 | 0 | } |
3640 | | |
3641 | | /* Single Onion Services: non-anonymous hidden services */ |
3642 | 0 | if (hs_service_non_anonymous_mode_enabled(options)) { |
3643 | 0 | log_warn(LD_CONFIG, |
3644 | 0 | "HiddenServiceNonAnonymousMode is set. Every hidden service on " |
3645 | 0 | "this tor instance is NON-ANONYMOUS. If " |
3646 | 0 | "the HiddenServiceNonAnonymousMode option is changed, Tor will " |
3647 | 0 | "refuse to launch hidden services from the same directories, to " |
3648 | 0 | "protect your anonymity against config errors. This setting is " |
3649 | 0 | "for experimental use only."); |
3650 | 0 | } |
3651 | |
|
3652 | 0 | if (!options->LearnCircuitBuildTimeout && options->CircuitBuildTimeout && |
3653 | 0 | options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) { |
3654 | 0 | log_warn(LD_CONFIG, |
3655 | 0 | "CircuitBuildTimeout is shorter (%d seconds) than the recommended " |
3656 | 0 | "minimum (%d seconds), and LearnCircuitBuildTimeout is disabled. " |
3657 | 0 | "If tor isn't working, raise this value or enable " |
3658 | 0 | "LearnCircuitBuildTimeout.", |
3659 | 0 | options->CircuitBuildTimeout, |
3660 | 0 | RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT ); |
3661 | 0 | } else if (!options->LearnCircuitBuildTimeout && |
3662 | 0 | !options->CircuitBuildTimeout) { |
3663 | 0 | int severity = LOG_NOTICE; |
3664 | | /* Be a little quieter if we've deliberately disabled |
3665 | | * LearnCircuitBuildTimeout. */ |
3666 | 0 | if (circuit_build_times_disabled_(options, 1)) { |
3667 | 0 | severity = LOG_INFO; |
3668 | 0 | } |
3669 | 0 | log_fn(severity, LD_CONFIG, "You disabled LearnCircuitBuildTimeout, but " |
3670 | 0 | "didn't specify a CircuitBuildTimeout. I'll pick a plausible " |
3671 | 0 | "default."); |
3672 | 0 | } |
3673 | |
|
3674 | 0 | if (options->DormantClientTimeout < 10*60 && !options->TestingTorNetwork) { |
3675 | 0 | REJECT("DormantClientTimeout is too low. It must be at least 10 minutes."); |
3676 | 0 | } |
3677 | | |
3678 | 0 | if (options->PathBiasNoticeRate > 1.0) { |
3679 | 0 | tor_asprintf(msg, |
3680 | 0 | "PathBiasNoticeRate is too high. " |
3681 | 0 | "It must be between 0 and 1.0"); |
3682 | 0 | return -1; |
3683 | 0 | } |
3684 | 0 | if (options->PathBiasWarnRate > 1.0) { |
3685 | 0 | tor_asprintf(msg, |
3686 | 0 | "PathBiasWarnRate is too high. " |
3687 | 0 | "It must be between 0 and 1.0"); |
3688 | 0 | return -1; |
3689 | 0 | } |
3690 | 0 | if (options->PathBiasExtremeRate > 1.0) { |
3691 | 0 | tor_asprintf(msg, |
3692 | 0 | "PathBiasExtremeRate is too high. " |
3693 | 0 | "It must be between 0 and 1.0"); |
3694 | 0 | return -1; |
3695 | 0 | } |
3696 | 0 | if (options->PathBiasNoticeUseRate > 1.0) { |
3697 | 0 | tor_asprintf(msg, |
3698 | 0 | "PathBiasNoticeUseRate is too high. " |
3699 | 0 | "It must be between 0 and 1.0"); |
3700 | 0 | return -1; |
3701 | 0 | } |
3702 | 0 | if (options->PathBiasExtremeUseRate > 1.0) { |
3703 | 0 | tor_asprintf(msg, |
3704 | 0 | "PathBiasExtremeUseRate is too high. " |
3705 | 0 | "It must be between 0 and 1.0"); |
3706 | 0 | return -1; |
3707 | 0 | } |
3708 | | |
3709 | 0 | if (options->MaxCircuitDirtiness < MIN_MAX_CIRCUIT_DIRTINESS) { |
3710 | 0 | log_warn(LD_CONFIG, "MaxCircuitDirtiness option is too short; " |
3711 | 0 | "raising to %d seconds.", MIN_MAX_CIRCUIT_DIRTINESS); |
3712 | 0 | options->MaxCircuitDirtiness = MIN_MAX_CIRCUIT_DIRTINESS; |
3713 | 0 | } |
3714 | |
|
3715 | 0 | if (options->MaxCircuitDirtiness > MAX_MAX_CIRCUIT_DIRTINESS) { |
3716 | 0 | log_warn(LD_CONFIG, "MaxCircuitDirtiness option is too high; " |
3717 | 0 | "setting to %d days.", MAX_MAX_CIRCUIT_DIRTINESS/86400); |
3718 | 0 | options->MaxCircuitDirtiness = MAX_MAX_CIRCUIT_DIRTINESS; |
3719 | 0 | } |
3720 | |
|
3721 | 0 | if (options->CircuitStreamTimeout && |
3722 | 0 | options->CircuitStreamTimeout < MIN_CIRCUIT_STREAM_TIMEOUT) { |
3723 | 0 | log_warn(LD_CONFIG, "CircuitStreamTimeout option is too short; " |
3724 | 0 | "raising to %d seconds.", MIN_CIRCUIT_STREAM_TIMEOUT); |
3725 | 0 | options->CircuitStreamTimeout = MIN_CIRCUIT_STREAM_TIMEOUT; |
3726 | 0 | } |
3727 | |
|
3728 | 0 | if (options->HeartbeatPeriod && |
3729 | 0 | options->HeartbeatPeriod < MIN_HEARTBEAT_PERIOD && |
3730 | 0 | !options->TestingTorNetwork) { |
3731 | 0 | log_warn(LD_CONFIG, "HeartbeatPeriod option is too short; " |
3732 | 0 | "raising to %d seconds.", MIN_HEARTBEAT_PERIOD); |
3733 | 0 | options->HeartbeatPeriod = MIN_HEARTBEAT_PERIOD; |
3734 | 0 | } |
3735 | |
|
3736 | 0 | if (options->KeepalivePeriod < 1) |
3737 | 0 | REJECT("KeepalivePeriod option must be positive."); |
3738 | | |
3739 | 0 | if (config_ensure_bandwidth_cap(&options->BandwidthRate, |
3740 | 0 | "BandwidthRate", msg) < 0) |
3741 | 0 | return -1; |
3742 | 0 | if (config_ensure_bandwidth_cap(&options->BandwidthBurst, |
3743 | 0 | "BandwidthBurst", msg) < 0) |
3744 | 0 | return -1; |
3745 | | |
3746 | 0 | if (options_validate_relay_bandwidth(old_options, options, msg) < 0) |
3747 | 0 | return -1; |
3748 | | |
3749 | 0 | if (options->BandwidthRate > options->BandwidthBurst) |
3750 | 0 | REJECT("BandwidthBurst must be at least equal to BandwidthRate."); |
3751 | | |
3752 | 0 | if (options_validate_relay_accounting(old_options, options, msg) < 0) |
3753 | 0 | return -1; |
3754 | | |
3755 | 0 | if (options_validate_relay_mode(old_options, options, msg) < 0) |
3756 | 0 | return -1; |
3757 | | |
3758 | 0 | if (options->HTTPProxy) { /* parse it now */ |
3759 | 0 | if (tor_addr_port_lookup(options->HTTPProxy, |
3760 | 0 | &options->HTTPProxyAddr, &options->HTTPProxyPort) < 0) |
3761 | 0 | REJECT("HTTPProxy failed to parse or resolve. Please fix."); |
3762 | 0 | if (options->HTTPProxyPort == 0) { /* give it a default */ |
3763 | 0 | options->HTTPProxyPort = 80; |
3764 | 0 | } |
3765 | 0 | } |
3766 | | |
3767 | 0 | if (options->HTTPProxyAuthenticator) { |
3768 | 0 | if (strlen(options->HTTPProxyAuthenticator) >= 512) |
3769 | 0 | REJECT("HTTPProxyAuthenticator is too long (>= 512 chars)."); |
3770 | 0 | } |
3771 | | |
3772 | 0 | if (options->HTTPSProxy) { /* parse it now */ |
3773 | 0 | if (tor_addr_port_lookup(options->HTTPSProxy, |
3774 | 0 | &options->HTTPSProxyAddr, &options->HTTPSProxyPort) <0) |
3775 | 0 | REJECT("HTTPSProxy failed to parse or resolve. Please fix."); |
3776 | 0 | if (options->HTTPSProxyPort == 0) { /* give it a default */ |
3777 | 0 | options->HTTPSProxyPort = 443; |
3778 | 0 | } |
3779 | 0 | } |
3780 | | |
3781 | 0 | if (options->HTTPSProxyAuthenticator) { |
3782 | 0 | if (strlen(options->HTTPSProxyAuthenticator) >= 512) |
3783 | 0 | REJECT("HTTPSProxyAuthenticator is too long (>= 512 chars)."); |
3784 | 0 | } |
3785 | | |
3786 | 0 | if (options->Socks4Proxy) { /* parse it now */ |
3787 | 0 | if (tor_addr_port_lookup(options->Socks4Proxy, |
3788 | 0 | &options->Socks4ProxyAddr, |
3789 | 0 | &options->Socks4ProxyPort) <0) |
3790 | 0 | REJECT("Socks4Proxy failed to parse or resolve. Please fix."); |
3791 | 0 | if (options->Socks4ProxyPort == 0) { /* give it a default */ |
3792 | 0 | options->Socks4ProxyPort = 1080; |
3793 | 0 | } |
3794 | 0 | } |
3795 | | |
3796 | 0 | if (options->Socks5Proxy) { /* parse it now */ |
3797 | 0 | if (tor_addr_port_lookup(options->Socks5Proxy, |
3798 | 0 | &options->Socks5ProxyAddr, |
3799 | 0 | &options->Socks5ProxyPort) <0) |
3800 | 0 | REJECT("Socks5Proxy failed to parse or resolve. Please fix."); |
3801 | 0 | if (options->Socks5ProxyPort == 0) { /* give it a default */ |
3802 | 0 | options->Socks5ProxyPort = 1080; |
3803 | 0 | } |
3804 | 0 | } |
3805 | | |
3806 | 0 | if (options->TCPProxy) { |
3807 | 0 | int res = parse_tcp_proxy_line(options->TCPProxy, options, msg); |
3808 | 0 | if (res < 0) { |
3809 | 0 | return res; |
3810 | 0 | } |
3811 | 0 | } |
3812 | | |
3813 | | /* Check if more than one exclusive proxy type has been enabled. */ |
3814 | 0 | if (!!options->Socks4Proxy + !!options->Socks5Proxy + |
3815 | 0 | !!options->HTTPSProxy + !!options->TCPProxy > 1) |
3816 | 0 | REJECT("You have configured more than one proxy type. " |
3817 | 0 | "(Socks4Proxy|Socks5Proxy|HTTPSProxy|TCPProxy)"); |
3818 | | |
3819 | | /* Check if the proxies will give surprising behavior. */ |
3820 | 0 | if (options->HTTPProxy && !(options->Socks4Proxy || |
3821 | 0 | options->Socks5Proxy || |
3822 | 0 | options->HTTPSProxy || |
3823 | 0 | options->TCPProxy)) { |
3824 | 0 | log_warn(LD_CONFIG, "HTTPProxy configured, but no SOCKS proxy, " |
3825 | 0 | "HTTPS proxy, or any other TCP proxy configured. Watch out: " |
3826 | 0 | "this configuration will proxy unencrypted directory " |
3827 | 0 | "connections only."); |
3828 | 0 | } |
3829 | |
|
3830 | 0 | if (options->Socks5ProxyUsername) { |
3831 | 0 | size_t len; |
3832 | |
|
3833 | 0 | len = strlen(options->Socks5ProxyUsername); |
3834 | 0 | if (len < 1 || len > MAX_SOCKS5_AUTH_FIELD_SIZE) |
3835 | 0 | REJECT("Socks5ProxyUsername must be between 1 and 255 characters."); |
3836 | | |
3837 | 0 | if (!options->Socks5ProxyPassword) |
3838 | 0 | REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername."); |
3839 | | |
3840 | 0 | len = strlen(options->Socks5ProxyPassword); |
3841 | 0 | if (len < 1 || len > MAX_SOCKS5_AUTH_FIELD_SIZE) |
3842 | 0 | REJECT("Socks5ProxyPassword must be between 1 and 255 characters."); |
3843 | 0 | } else if (options->Socks5ProxyPassword) |
3844 | 0 | REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername."); |
3845 | | |
3846 | 0 | if (options->HashedControlPassword) { |
3847 | 0 | smartlist_t *sl = decode_hashed_passwords(options->HashedControlPassword); |
3848 | 0 | if (!sl) { |
3849 | 0 | REJECT("Bad HashedControlPassword: wrong length or bad encoding"); |
3850 | 0 | } else { |
3851 | 0 | SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp)); |
3852 | 0 | smartlist_free(sl); |
3853 | 0 | } |
3854 | 0 | } |
3855 | | |
3856 | 0 | if (options->HashedControlSessionPassword) { |
3857 | 0 | smartlist_t *sl = decode_hashed_passwords( |
3858 | 0 | options->HashedControlSessionPassword); |
3859 | 0 | if (!sl) { |
3860 | 0 | REJECT("Bad HashedControlSessionPassword: wrong length or bad encoding"); |
3861 | 0 | } else { |
3862 | 0 | SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp)); |
3863 | 0 | smartlist_free(sl); |
3864 | 0 | } |
3865 | 0 | } |
3866 | | |
3867 | 0 | if (options->OwningControllerProcess) { |
3868 | 0 | const char *validate_pspec_msg = NULL; |
3869 | 0 | if (tor_validate_process_specifier(options->OwningControllerProcess, |
3870 | 0 | &validate_pspec_msg)) { |
3871 | 0 | tor_asprintf(msg, "Bad OwningControllerProcess: %s", |
3872 | 0 | validate_pspec_msg); |
3873 | 0 | return -1; |
3874 | 0 | } |
3875 | 0 | } |
3876 | | |
3877 | 0 | if ((options->ControlPort_set || world_writable_control_socket) && |
3878 | 0 | !options->HashedControlPassword && |
3879 | 0 | !options->HashedControlSessionPassword && |
3880 | 0 | !options->CookieAuthentication) { |
3881 | 0 | log_warn(LD_CONFIG, "Control%s is %s, but no authentication method " |
3882 | 0 | "has been configured. This means that any program on your " |
3883 | 0 | "computer can reconfigure your Tor. That's bad! You should " |
3884 | 0 | "upgrade your Tor controller as soon as possible.", |
3885 | 0 | options->ControlPort_set ? "Port" : "Socket", |
3886 | 0 | options->ControlPort_set ? "open" : "world writable"); |
3887 | 0 | } |
3888 | |
|
3889 | 0 | if (options->CookieAuthFileGroupReadable && !options->CookieAuthFile) { |
3890 | 0 | log_warn(LD_CONFIG, "CookieAuthFileGroupReadable is set, but will have " |
3891 | 0 | "no effect: you must specify an explicit CookieAuthFile to " |
3892 | 0 | "have it group-readable."); |
3893 | 0 | } |
3894 | |
|
3895 | 0 | for (cl = options->NodeFamilies; cl; cl = cl->next) { |
3896 | 0 | routerset_t *rs = routerset_new(); |
3897 | 0 | if (routerset_parse(rs, cl->value, cl->key)) { |
3898 | 0 | routerset_free(rs); |
3899 | 0 | return -1; |
3900 | 0 | } |
3901 | 0 | routerset_free(rs); |
3902 | 0 | } |
3903 | | |
3904 | 0 | if (validate_addr_policies(options, msg) < 0) |
3905 | 0 | return -1; |
3906 | | |
3907 | | /* If FallbackDir is set, we don't UseDefaultFallbackDirs */ |
3908 | 0 | if (options->UseDefaultFallbackDirs && options->FallbackDir) { |
3909 | 0 | log_info(LD_CONFIG, "You have set UseDefaultFallbackDirs 1 and " |
3910 | 0 | "FallbackDir(s). Ignoring UseDefaultFallbackDirs, and " |
3911 | 0 | "using the FallbackDir(s) you have set."); |
3912 | 0 | } |
3913 | |
|
3914 | 0 | if (validate_dir_servers(options, old_options) < 0) |
3915 | 0 | REJECT("Directory authority/fallback line did not parse. See logs " |
3916 | 0 | "for details."); |
3917 | | |
3918 | 0 | if (options->UseBridges && !options->Bridges) |
3919 | 0 | REJECT("If you set UseBridges, you must specify at least one bridge."); |
3920 | | |
3921 | 0 | for (cl = options->Bridges; cl; cl = cl->next) { |
3922 | 0 | bridge_line_t *bridge_line = parse_bridge_line(cl->value); |
3923 | 0 | if (!bridge_line) |
3924 | 0 | REJECT("Bridge line did not parse. See logs for details."); |
3925 | 0 | bridge_line_free(bridge_line); |
3926 | 0 | } |
3927 | | |
3928 | 0 | for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { |
3929 | 0 | if (pt_parse_transport_line(options, cl->value, 1, 0) < 0) |
3930 | 0 | REJECT("Invalid client transport line. See logs for details."); |
3931 | 0 | } |
3932 | | |
3933 | 0 | if (options_validate_server_transport(old_options, options, msg) < 0) |
3934 | 0 | return -1; |
3935 | | |
3936 | 0 | if (options->ConstrainedSockets) { |
3937 | | /* If the user wants to constrain socket buffer use, make sure the desired |
3938 | | * limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */ |
3939 | 0 | if (options->ConstrainedSockSize < MIN_CONSTRAINED_TCP_BUFFER || |
3940 | 0 | options->ConstrainedSockSize > MAX_CONSTRAINED_TCP_BUFFER || |
3941 | 0 | options->ConstrainedSockSize % 1024) { |
3942 | 0 | tor_asprintf(msg, |
3943 | 0 | "ConstrainedSockSize is invalid. Must be a value between %d and %d " |
3944 | 0 | "in 1024 byte increments.", |
3945 | 0 | MIN_CONSTRAINED_TCP_BUFFER, MAX_CONSTRAINED_TCP_BUFFER); |
3946 | 0 | return -1; |
3947 | 0 | } |
3948 | 0 | } |
3949 | | |
3950 | 0 | if (options_validate_dirauth_schedule(old_options, options, msg) < 0) |
3951 | 0 | return -1; |
3952 | | |
3953 | 0 | if (hs_config_service_all(options, 1) < 0) |
3954 | 0 | REJECT("Failed to configure rendezvous options. See logs for details."); |
3955 | | |
3956 | | /* Parse client-side authorization for hidden services. */ |
3957 | 0 | if (hs_config_client_auth_all(options, 1) < 0) |
3958 | 0 | REJECT("Failed to configure client authorization for hidden services. " |
3959 | 0 | "See logs for details."); |
3960 | | |
3961 | 0 | if (parse_virtual_addr_network(options->VirtualAddrNetworkIPv4, |
3962 | 0 | AF_INET, 1, msg)<0) |
3963 | 0 | return -1; |
3964 | 0 | if (parse_virtual_addr_network(options->VirtualAddrNetworkIPv6, |
3965 | 0 | AF_INET6, 1, msg)<0) |
3966 | 0 | return -1; |
3967 | | |
3968 | 0 | if (options->TestingTorNetwork && |
3969 | 0 | !(options->DirAuthorities || |
3970 | 0 | (options->AlternateDirAuthority && |
3971 | 0 | options->AlternateBridgeAuthority))) { |
3972 | 0 | REJECT("TestingTorNetwork may only be configured in combination with " |
3973 | 0 | "a non-default set of DirAuthority or both of " |
3974 | 0 | "AlternateDirAuthority and AlternateBridgeAuthority configured."); |
3975 | 0 | } |
3976 | | |
3977 | 0 | #define CHECK_DEFAULT(arg) \ |
3978 | 0 | STMT_BEGIN \ |
3979 | 0 | if (!config_is_same(get_options_mgr(),options, \ |
3980 | 0 | dflt_options,#arg)) { \ |
3981 | 0 | or_options_free(dflt_options); \ |
3982 | 0 | REJECT(#arg " may only be changed in testing Tor " \ |
3983 | 0 | "networks!"); \ |
3984 | 0 | } \ |
3985 | 0 | STMT_END |
3986 | | |
3987 | | /* Check for options that can only be changed from the defaults in testing |
3988 | | networks. */ |
3989 | 0 | if (! options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) { |
3990 | 0 | or_options_t *dflt_options = options_new(); |
3991 | 0 | options_init(dflt_options); |
3992 | | /* 31851: some of these options are dirauth or relay only */ |
3993 | 0 | CHECK_DEFAULT(TestingV3AuthInitialVotingInterval); |
3994 | 0 | CHECK_DEFAULT(TestingV3AuthInitialVoteDelay); |
3995 | 0 | CHECK_DEFAULT(TestingV3AuthInitialDistDelay); |
3996 | 0 | CHECK_DEFAULT(TestingV3AuthVotingStartOffset); |
3997 | 0 | CHECK_DEFAULT(TestingAuthDirTimeToLearnReachability); |
3998 | 0 | CHECK_DEFAULT(TestingServerDownloadInitialDelay); |
3999 | 0 | CHECK_DEFAULT(TestingClientDownloadInitialDelay); |
4000 | 0 | CHECK_DEFAULT(TestingServerConsensusDownloadInitialDelay); |
4001 | 0 | CHECK_DEFAULT(TestingClientConsensusDownloadInitialDelay); |
4002 | 0 | CHECK_DEFAULT(TestingBridgeDownloadInitialDelay); |
4003 | 0 | CHECK_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay); |
4004 | 0 | CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest); |
4005 | 0 | CHECK_DEFAULT(TestingDirConnectionMaxStall); |
4006 | 0 | CHECK_DEFAULT(TestingAuthKeyLifetime); |
4007 | 0 | CHECK_DEFAULT(TestingLinkCertLifetime); |
4008 | 0 | CHECK_DEFAULT(TestingSigningKeySlop); |
4009 | 0 | CHECK_DEFAULT(TestingAuthKeySlop); |
4010 | 0 | CHECK_DEFAULT(TestingLinkKeySlop); |
4011 | 0 | CHECK_DEFAULT(TestingMinTimeToReportBandwidth); |
4012 | 0 | or_options_free(dflt_options); |
4013 | 0 | } |
4014 | 0 | #undef CHECK_DEFAULT |
4015 | | |
4016 | 0 | if (!options->ClientDNSRejectInternalAddresses && |
4017 | 0 | !(options->DirAuthorities || |
4018 | 0 | (options->AlternateDirAuthority && options->AlternateBridgeAuthority))) |
4019 | 0 | REJECT("ClientDNSRejectInternalAddresses used for default network."); |
4020 | | |
4021 | 0 | if (options_validate_relay_testing(old_options, options, msg) < 0) |
4022 | 0 | return -1; |
4023 | 0 | if (options_validate_dirauth_testing(old_options, options, msg) < 0) |
4024 | 0 | return -1; |
4025 | | |
4026 | 0 | if (options->TestingClientMaxIntervalWithoutRequest < 1) { |
4027 | 0 | REJECT("TestingClientMaxIntervalWithoutRequest is way too low."); |
4028 | 0 | } else if (options->TestingClientMaxIntervalWithoutRequest > 3600) { |
4029 | 0 | COMPLAIN("TestingClientMaxIntervalWithoutRequest is insanely high."); |
4030 | 0 | } |
4031 | | |
4032 | 0 | if (options->TestingDirConnectionMaxStall < 5) { |
4033 | 0 | REJECT("TestingDirConnectionMaxStall is way too low."); |
4034 | 0 | } else if (options->TestingDirConnectionMaxStall > 3600) { |
4035 | 0 | COMPLAIN("TestingDirConnectionMaxStall is insanely high."); |
4036 | 0 | } |
4037 | | |
4038 | 0 | if (options->ClientBootstrapConsensusMaxInProgressTries < 1) { |
4039 | 0 | REJECT("ClientBootstrapConsensusMaxInProgressTries must be greater " |
4040 | 0 | "than 0."); |
4041 | 0 | } else if (options->ClientBootstrapConsensusMaxInProgressTries |
4042 | 0 | > 100) { |
4043 | 0 | COMPLAIN("ClientBootstrapConsensusMaxInProgressTries is insanely " |
4044 | 0 | "high."); |
4045 | 0 | } |
4046 | | |
4047 | 0 | if (options->TestingEnableConnBwEvent && |
4048 | 0 | !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) { |
4049 | 0 | REJECT("TestingEnableConnBwEvent may only be changed in testing " |
4050 | 0 | "Tor networks!"); |
4051 | 0 | } |
4052 | | |
4053 | 0 | if (options->TestingEnableCellStatsEvent && |
4054 | 0 | !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) { |
4055 | 0 | REJECT("TestingEnableCellStatsEvent may only be changed in testing " |
4056 | 0 | "Tor networks!"); |
4057 | 0 | } |
4058 | | |
4059 | 0 | if (options->TestingTorNetwork) { |
4060 | 0 | log_warn(LD_CONFIG, "TestingTorNetwork is set. This will make your node " |
4061 | 0 | "almost unusable in the public Tor network, and is " |
4062 | 0 | "therefore only advised if you are building a " |
4063 | 0 | "testing Tor network!"); |
4064 | 0 | } |
4065 | |
|
4066 | 0 | if (options_validate_scheduler(options, msg) < 0) { |
4067 | 0 | return -1; |
4068 | 0 | } |
4069 | | |
4070 | 0 | return 0; |
4071 | 0 | } |
4072 | | |
4073 | | #undef REJECT |
4074 | | #undef COMPLAIN |
4075 | | |
4076 | | /* Given the value that the user has set for MaxMemInQueues, compute the |
4077 | | * actual maximum value. We clip this value if it's too low, and autodetect |
4078 | | * it if it's set to 0. */ |
4079 | | STATIC uint64_t |
4080 | | compute_real_max_mem_in_queues(const uint64_t val, bool is_server) |
4081 | 0 | { |
4082 | 0 | #define MIN_SERVER_MB 64 |
4083 | 0 | #define MIN_UNWARNED_SERVER_MB 256 |
4084 | 0 | #define MIN_UNWARNED_CLIENT_MB 64 |
4085 | 0 | uint64_t result; |
4086 | |
|
4087 | 0 | if (val == 0) { |
4088 | 0 | #define ONE_GIGABYTE (UINT64_C(1) << 30) |
4089 | 0 | #define ONE_MEGABYTE (UINT64_C(1) << 20) |
4090 | | /* The user didn't pick a memory limit. Choose a very large one |
4091 | | * that is still smaller than the system memory */ |
4092 | 0 | static int notice_sent = 0; |
4093 | 0 | size_t ram = 0; |
4094 | 0 | if (get_total_system_memory(&ram) < 0) { |
4095 | | /* We couldn't determine our total system memory! */ |
4096 | 0 | #if SIZEOF_VOID_P >= 8 |
4097 | | /* 64-bit system. Let's hope for 8 GB. */ |
4098 | 0 | result = 8 * ONE_GIGABYTE; |
4099 | | #else |
4100 | | /* (presumably) 32-bit system. Let's hope for 1 GB. */ |
4101 | | result = ONE_GIGABYTE; |
4102 | | #endif /* SIZEOF_VOID_P >= 8 */ |
4103 | 0 | } else { |
4104 | | /* We detected the amount of memory available. */ |
4105 | 0 | uint64_t avail = 0; |
4106 | |
|
4107 | 0 | #if SIZEOF_SIZE_T > 4 |
4108 | | /* On a 64-bit platform, we consider 8GB "very large". */ |
4109 | 0 | #define RAM_IS_VERY_LARGE(x) ((x) >= (8 * ONE_GIGABYTE)) |
4110 | | #else |
4111 | | /* On a 32-bit platform, we can't have 8GB of ram. */ |
4112 | | #define RAM_IS_VERY_LARGE(x) (0) |
4113 | | #endif /* SIZEOF_SIZE_T > 4 */ |
4114 | |
|
4115 | 0 | if (RAM_IS_VERY_LARGE(ram)) { |
4116 | | /* If we have 8 GB, or more, RAM available, we set the MaxMemInQueues |
4117 | | * to 0.4 * RAM. The idea behind this value is that the amount of RAM |
4118 | | * is more than enough for a single relay and should allow the relay |
4119 | | * operator to run two relays if they have additional bandwidth |
4120 | | * available. |
4121 | | */ |
4122 | 0 | avail = (ram / 5) * 2; |
4123 | 0 | } else { |
4124 | | /* If we have less than 8 GB of RAM available, we use the "old" default |
4125 | | * for MaxMemInQueues of 0.75 * RAM. |
4126 | | */ |
4127 | 0 | avail = (ram / 4) * 3; |
4128 | 0 | } |
4129 | | |
4130 | | /* Make sure it's in range from 0.25 GB to 8 GB for 64-bit and 0.25 to 2 |
4131 | | * GB for 32-bit. */ |
4132 | 0 | if (avail > MAX_DEFAULT_MEMORY_QUEUE_SIZE) { |
4133 | | /* If you want to use more than this much RAM, you need to configure |
4134 | | it yourself */ |
4135 | 0 | result = MAX_DEFAULT_MEMORY_QUEUE_SIZE; |
4136 | 0 | } else if (avail < ONE_GIGABYTE / 4) { |
4137 | 0 | result = ONE_GIGABYTE / 4; |
4138 | 0 | } else { |
4139 | 0 | result = avail; |
4140 | 0 | } |
4141 | 0 | } |
4142 | 0 | if (is_server && ! notice_sent) { |
4143 | 0 | log_notice(LD_CONFIG, "%sMaxMemInQueues is set to %"PRIu64" MB. " |
4144 | 0 | "You can override this by setting MaxMemInQueues by hand.", |
4145 | 0 | ram ? "Based on detected system memory, " : "", |
4146 | 0 | (result / ONE_MEGABYTE)); |
4147 | 0 | notice_sent = 1; |
4148 | 0 | } |
4149 | 0 | return result; |
4150 | 0 | } else if (is_server && val < ONE_MEGABYTE * MIN_SERVER_MB) { |
4151 | | /* We can't configure less than this much on a server. */ |
4152 | 0 | log_warn(LD_CONFIG, "MaxMemInQueues must be at least %d MB on servers " |
4153 | 0 | "for now. Ideally, have it as large as you can afford.", |
4154 | 0 | MIN_SERVER_MB); |
4155 | 0 | return MIN_SERVER_MB * ONE_MEGABYTE; |
4156 | 0 | } else if (is_server && val < ONE_MEGABYTE * MIN_UNWARNED_SERVER_MB) { |
4157 | | /* On a server, if it's less than this much, we warn that things |
4158 | | * may go badly. */ |
4159 | 0 | log_warn(LD_CONFIG, "MaxMemInQueues is set to a low value; if your " |
4160 | 0 | "relay doesn't work, this may be the reason why."); |
4161 | 0 | return val; |
4162 | 0 | } else if (! is_server && val < ONE_MEGABYTE * MIN_UNWARNED_CLIENT_MB) { |
4163 | | /* On a client, if it's less than this much, we warn that things |
4164 | | * may go badly. */ |
4165 | 0 | log_warn(LD_CONFIG, "MaxMemInQueues is set to a low value; if your " |
4166 | 0 | "client doesn't work, this may be the reason why."); |
4167 | 0 | return val; |
4168 | 0 | } else { |
4169 | | /* The value was fine all along */ |
4170 | 0 | return val; |
4171 | 0 | } |
4172 | 0 | } |
4173 | | |
4174 | | /** Helper: return true iff s1 and s2 are both NULL, or both non-NULL |
4175 | | * equal strings. */ |
4176 | | static int |
4177 | | opt_streq(const char *s1, const char *s2) |
4178 | 0 | { |
4179 | 0 | return 0 == strcmp_opt(s1, s2); |
4180 | 0 | } |
4181 | | |
4182 | | /** Check if any config options have changed but aren't allowed to. */ |
4183 | | static int |
4184 | | options_check_transition_cb(const void *old_, |
4185 | | const void *new_val_, |
4186 | | char **msg) |
4187 | 0 | { |
4188 | 0 | CHECK_OPTIONS_MAGIC(old_); |
4189 | 0 | CHECK_OPTIONS_MAGIC(new_val_); |
4190 | |
|
4191 | 0 | const or_options_t *old = old_; |
4192 | 0 | const or_options_t *new_val = new_val_; |
4193 | |
|
4194 | 0 | if (BUG(!old)) |
4195 | 0 | return 0; |
4196 | | |
4197 | 0 | #define BAD_CHANGE_TO(opt, how) do { \ |
4198 | 0 | *msg = tor_strdup("While Tor is running"how", changing " #opt \ |
4199 | 0 | " is not allowed"); \ |
4200 | 0 | return -1; \ |
4201 | 0 | } while (0) |
4202 | | |
4203 | 0 | if (sandbox_is_active()) { |
4204 | 0 | #define SB_NOCHANGE_STR(opt) \ |
4205 | 0 | if (! CFG_EQ_STRING(old, new_val, opt)) \ |
4206 | 0 | BAD_CHANGE_TO(opt," with Sandbox active") |
4207 | 0 | #define SB_NOCHANGE_LINELIST(opt) \ |
4208 | 0 | if (! CFG_EQ_LINELIST(old, new_val, opt)) \ |
4209 | 0 | BAD_CHANGE_TO(opt," with Sandbox active") |
4210 | 0 | #define SB_NOCHANGE_INT(opt) \ |
4211 | 0 | if (! CFG_EQ_INT(old, new_val, opt)) \ |
4212 | 0 | BAD_CHANGE_TO(opt," with Sandbox active") |
4213 | |
|
4214 | 0 | SB_NOCHANGE_LINELIST(Address); |
4215 | 0 | SB_NOCHANGE_STR(ServerDNSResolvConfFile); |
4216 | 0 | SB_NOCHANGE_STR(DirPortFrontPage); |
4217 | 0 | SB_NOCHANGE_STR(CookieAuthFile); |
4218 | 0 | SB_NOCHANGE_STR(ExtORPortCookieAuthFile); |
4219 | 0 | SB_NOCHANGE_LINELIST(Logs); |
4220 | 0 | SB_NOCHANGE_INT(ConnLimit); |
4221 | | |
4222 | 0 | if (server_mode(old) != server_mode(new_val)) { |
4223 | 0 | *msg = tor_strdup("Can't start/stop being a server while " |
4224 | 0 | "Sandbox is active"); |
4225 | 0 | return -1; |
4226 | 0 | } |
4227 | 0 | } |
4228 | | |
4229 | 0 | #undef SB_NOCHANGE_LINELIST |
4230 | 0 | #undef SB_NOCHANGE_STR |
4231 | 0 | #undef SB_NOCHANGE_INT |
4232 | 0 | #undef BAD_CHANGE_TO |
4233 | 0 | #undef NO_CHANGE_BOOL |
4234 | 0 | #undef NO_CHANGE_INT |
4235 | 0 | #undef NO_CHANGE_STRING |
4236 | 0 | return 0; |
4237 | 0 | } |
4238 | | |
4239 | | #ifdef _WIN32 |
4240 | | /** Return the directory on windows where we expect to find our application |
4241 | | * data. */ |
4242 | | static char * |
4243 | | get_windows_conf_root(void) |
4244 | | { |
4245 | | static int is_set = 0; |
4246 | | static char path[MAX_PATH*2+1]; |
4247 | | TCHAR tpath[MAX_PATH] = {0}; |
4248 | | |
4249 | | LPITEMIDLIST idl; |
4250 | | IMalloc *m; |
4251 | | HRESULT result; |
4252 | | |
4253 | | if (is_set) |
4254 | | return path; |
4255 | | |
4256 | | /* Find X:\documents and settings\username\application data\ . |
4257 | | * We would use SHGetSpecialFolder path, but that wasn't added until IE4. |
4258 | | */ |
4259 | | #ifdef ENABLE_LOCAL_APPDATA |
4260 | | #define APPDATA_PATH CSIDL_LOCAL_APPDATA |
4261 | | #else |
4262 | | #define APPDATA_PATH CSIDL_APPDATA |
4263 | | #endif |
4264 | | if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, APPDATA_PATH, &idl))) { |
4265 | | getcwd(path,MAX_PATH); |
4266 | | is_set = 1; |
4267 | | log_warn(LD_CONFIG, |
4268 | | "I couldn't find your application data folder: are you " |
4269 | | "running an ancient version of Windows 95? Defaulting to \"%s\"", |
4270 | | path); |
4271 | | return path; |
4272 | | } |
4273 | | /* Convert the path from an "ID List" (whatever that is!) to a path. */ |
4274 | | result = SHGetPathFromIDList(idl, tpath); |
4275 | | #ifdef UNICODE |
4276 | | wcstombs(path,tpath,sizeof(path)); |
4277 | | path[sizeof(path)-1] = '\0'; |
4278 | | #else |
4279 | | strlcpy(path,tpath,sizeof(path)); |
4280 | | #endif /* defined(UNICODE) */ |
4281 | | |
4282 | | /* Now we need to free the memory that the path-idl was stored in. In |
4283 | | * typical Windows fashion, we can't just call 'free()' on it. */ |
4284 | | SHGetMalloc(&m); |
4285 | | if (m) { |
4286 | | m->lpVtbl->Free(m, idl); |
4287 | | m->lpVtbl->Release(m); |
4288 | | } |
4289 | | if (!SUCCEEDED(result)) { |
4290 | | return NULL; |
4291 | | } |
4292 | | strlcat(path,"\\tor",MAX_PATH); |
4293 | | is_set = 1; |
4294 | | return path; |
4295 | | } |
4296 | | #endif /* defined(_WIN32) */ |
4297 | | |
4298 | | /** Return the default location for our torrc file (if <b>defaults_file</b> is |
4299 | | * false), or for the torrc-defaults file (if <b>defaults_file</b> is true). */ |
4300 | | static const char * |
4301 | | get_default_conf_file(int defaults_file) |
4302 | 0 | { |
4303 | | #ifdef DISABLE_SYSTEM_TORRC |
4304 | | (void) defaults_file; |
4305 | | return NULL; |
4306 | | #elif defined(_WIN32) |
4307 | | if (defaults_file) { |
4308 | | static char defaults_path[MAX_PATH+1]; |
4309 | | tor_snprintf(defaults_path, MAX_PATH, "%s\\torrc-defaults", |
4310 | | get_windows_conf_root()); |
4311 | | return defaults_path; |
4312 | | } else { |
4313 | | static char path[MAX_PATH+1]; |
4314 | | tor_snprintf(path, MAX_PATH, "%s\\torrc", |
4315 | | get_windows_conf_root()); |
4316 | | return path; |
4317 | | } |
4318 | | #else |
4319 | 0 | return defaults_file ? CONFDIR "/torrc-defaults" : CONFDIR "/torrc"; |
4320 | 0 | #endif /* defined(DISABLE_SYSTEM_TORRC) || ... */ |
4321 | 0 | } |
4322 | | |
4323 | | /** Learn config file name from command line arguments, or use the default. |
4324 | | * |
4325 | | * If <b>defaults_file</b> is true, we're looking for torrc-defaults; |
4326 | | * otherwise, we're looking for the regular torrc_file. |
4327 | | * |
4328 | | * Set *<b>using_default_fname</b> to true if we're using the default |
4329 | | * configuration file name; or false if we've set it from the command line. |
4330 | | * |
4331 | | * Set *<b>ignore_missing_torrc</b> to true if we should ignore the resulting |
4332 | | * filename if it doesn't exist. |
4333 | | */ |
4334 | | static char * |
4335 | | find_torrc_filename(const config_line_t *cmd_arg, |
4336 | | int defaults_file, |
4337 | | int *using_default_fname, int *ignore_missing_torrc) |
4338 | 0 | { |
4339 | 0 | char *fname=NULL; |
4340 | 0 | const config_line_t *p_index; |
4341 | 0 | const char *fname_opt = defaults_file ? "--defaults-torrc" : "-f"; |
4342 | 0 | const char *fname_long_opt = defaults_file ? "--defaults-torrc" : |
4343 | 0 | "--torrc-file"; |
4344 | 0 | const char *ignore_opt = defaults_file ? NULL : "--ignore-missing-torrc"; |
4345 | 0 | const char *keygen_opt = "--keygen"; |
4346 | |
|
4347 | 0 | if (defaults_file) |
4348 | 0 | *ignore_missing_torrc = 1; |
4349 | |
|
4350 | 0 | for (p_index = cmd_arg; p_index; p_index = p_index->next) { |
4351 | | // options_init_from_torrc ensures only the short or long name is present |
4352 | 0 | if (!strcmp(p_index->key, fname_opt) || |
4353 | 0 | !strcmp(p_index->key, fname_long_opt)) { |
4354 | 0 | if (fname) { |
4355 | 0 | log_warn(LD_CONFIG, "Duplicate %s options on command line.", |
4356 | 0 | p_index->key); |
4357 | 0 | tor_free(fname); |
4358 | 0 | } |
4359 | 0 | fname = expand_filename(p_index->value); |
4360 | |
|
4361 | 0 | { |
4362 | 0 | char *absfname; |
4363 | 0 | absfname = make_path_absolute(fname); |
4364 | 0 | tor_free(fname); |
4365 | 0 | fname = absfname; |
4366 | 0 | } |
4367 | |
|
4368 | 0 | *using_default_fname = 0; |
4369 | 0 | } else if ((ignore_opt && !strcmp(p_index->key, ignore_opt)) || |
4370 | 0 | (keygen_opt && !strcmp(p_index->key, keygen_opt))) { |
4371 | 0 | *ignore_missing_torrc = 1; |
4372 | 0 | } |
4373 | 0 | } |
4374 | |
|
4375 | 0 | if (*using_default_fname) { |
4376 | | /* didn't find one, try CONFDIR */ |
4377 | 0 | const char *dflt = get_default_conf_file(defaults_file); |
4378 | 0 | file_status_t st = file_status(dflt); |
4379 | 0 | if (dflt && (st == FN_FILE || st == FN_EMPTY)) { |
4380 | 0 | fname = tor_strdup(dflt); |
4381 | 0 | } else { |
4382 | 0 | #ifndef _WIN32 |
4383 | 0 | char *fn = NULL; |
4384 | 0 | if (!defaults_file) { |
4385 | 0 | fn = expand_filename("~/.torrc"); |
4386 | 0 | } |
4387 | 0 | if (fn) { |
4388 | 0 | file_status_t hmst = file_status(fn); |
4389 | 0 | if (hmst == FN_FILE || hmst == FN_EMPTY || dflt == NULL) { |
4390 | 0 | fname = fn; |
4391 | 0 | } else { |
4392 | 0 | tor_free(fn); |
4393 | 0 | fname = tor_strdup(dflt); |
4394 | 0 | } |
4395 | 0 | } else { |
4396 | 0 | fname = dflt ? tor_strdup(dflt) : NULL; |
4397 | 0 | } |
4398 | | #else /* defined(_WIN32) */ |
4399 | | fname = dflt ? tor_strdup(dflt) : NULL; |
4400 | | #endif /* !defined(_WIN32) */ |
4401 | 0 | } |
4402 | 0 | } |
4403 | 0 | return fname; |
4404 | 0 | } |
4405 | | |
4406 | | /** Read the torrc from standard input and return it as a string. |
4407 | | * Upon failure, return NULL. |
4408 | | */ |
4409 | | static char * |
4410 | | load_torrc_from_stdin(void) |
4411 | 0 | { |
4412 | 0 | size_t sz_out; |
4413 | |
|
4414 | 0 | return read_file_to_str_until_eof(STDIN_FILENO,SIZE_MAX,&sz_out); |
4415 | 0 | } |
4416 | | |
4417 | | /** Load a configuration file from disk, setting torrc_fname or |
4418 | | * torrc_defaults_fname if successful. |
4419 | | * |
4420 | | * If <b>defaults_file</b> is true, load torrc-defaults; otherwise load torrc. |
4421 | | * |
4422 | | * Return the contents of the file on success, and NULL on failure. |
4423 | | */ |
4424 | | static char * |
4425 | | load_torrc_from_disk(const config_line_t *cmd_arg, int defaults_file) |
4426 | 0 | { |
4427 | 0 | char *fname=NULL; |
4428 | 0 | char *cf = NULL; |
4429 | 0 | int using_default_torrc = 1; |
4430 | 0 | int ignore_missing_torrc = 0; |
4431 | 0 | char **fname_var = defaults_file ? &torrc_defaults_fname : &torrc_fname; |
4432 | |
|
4433 | 0 | if (*fname_var == NULL) { |
4434 | 0 | fname = find_torrc_filename(cmd_arg, defaults_file, |
4435 | 0 | &using_default_torrc, &ignore_missing_torrc); |
4436 | 0 | tor_free(*fname_var); |
4437 | 0 | *fname_var = fname; |
4438 | 0 | } else { |
4439 | 0 | fname = *fname_var; |
4440 | 0 | } |
4441 | 0 | log_debug(LD_CONFIG, "Opening config file \"%s\"", fname?fname:"<NULL>"); |
4442 | | |
4443 | | /* Open config file */ |
4444 | 0 | file_status_t st = fname ? file_status(fname) : FN_EMPTY; |
4445 | 0 | if (fname == NULL || |
4446 | 0 | !(st == FN_FILE || st == FN_EMPTY) || |
4447 | 0 | !(cf = read_file_to_str(fname,0,NULL))) { |
4448 | 0 | if (using_default_torrc == 1 || ignore_missing_torrc) { |
4449 | 0 | if (!defaults_file) |
4450 | 0 | log_notice(LD_CONFIG, "Configuration file \"%s\" not present, " |
4451 | 0 | "using reasonable defaults.", fname); |
4452 | 0 | tor_free(fname); /* sets fname to NULL */ |
4453 | 0 | *fname_var = NULL; |
4454 | 0 | cf = tor_strdup(""); |
4455 | 0 | } else { |
4456 | 0 | log_warn(LD_CONFIG, |
4457 | 0 | "Unable to open configuration file \"%s\".", fname); |
4458 | 0 | goto err; |
4459 | 0 | } |
4460 | 0 | } else { |
4461 | 0 | log_notice(LD_CONFIG, "Read configuration file \"%s\".", fname); |
4462 | 0 | } |
4463 | | |
4464 | 0 | return cf; |
4465 | 0 | err: |
4466 | 0 | tor_free(fname); |
4467 | 0 | *fname_var = NULL; |
4468 | 0 | return NULL; |
4469 | 0 | } |
4470 | | |
4471 | | /** Read a configuration file into <b>options</b>, finding the configuration |
4472 | | * file location based on the command line. After loading the file |
4473 | | * call options_init_from_string() to load the config. |
4474 | | * Return 0 if success, -1 if failure, and 1 if we succeeded but should exit |
4475 | | * anyway. */ |
4476 | | int |
4477 | | options_init_from_torrc(int argc, char **argv) |
4478 | 0 | { |
4479 | 0 | char *cf=NULL, *cf_defaults=NULL; |
4480 | 0 | int retval = -1; |
4481 | 0 | char *errmsg=NULL; |
4482 | 0 | const config_line_t *cmdline_only_options; |
4483 | | |
4484 | | /* Go through command-line variables */ |
4485 | 0 | if (global_cmdline == NULL) { |
4486 | | /* Or we could redo the list every time we pass this place. |
4487 | | * It does not really matter */ |
4488 | 0 | global_cmdline = config_parse_commandline(argc, argv, 0); |
4489 | 0 | if (global_cmdline == NULL) { |
4490 | 0 | goto err; |
4491 | 0 | } |
4492 | 0 | } |
4493 | 0 | cmdline_only_options = global_cmdline->cmdline_opts; |
4494 | |
|
4495 | 0 | if (config_line_find(cmdline_only_options, "-h") || |
4496 | 0 | config_line_find(cmdline_only_options, "--help")) { |
4497 | 0 | print_usage(); |
4498 | 0 | return 1; |
4499 | 0 | } |
4500 | 0 | if (config_line_find(cmdline_only_options, "--list-torrc-options")) { |
4501 | | /* For validating whether we've documented everything. */ |
4502 | 0 | list_torrc_options(); |
4503 | 0 | return 1; |
4504 | 0 | } |
4505 | 0 | if (config_line_find(cmdline_only_options, "--list-deprecated-options")) { |
4506 | | /* For validating whether what we have deprecated really exists. */ |
4507 | 0 | list_deprecated_options(); |
4508 | 0 | return 1; |
4509 | 0 | } |
4510 | 0 | if (config_line_find(cmdline_only_options, "--dbg-dump-subsystem-list")) { |
4511 | 0 | subsystems_dump_list(); |
4512 | 0 | return 1; |
4513 | 0 | } |
4514 | | |
4515 | 0 | if (config_line_find(cmdline_only_options, "--version")) { |
4516 | 0 | printf("Tor version %s.\n",get_version()); |
4517 | | #ifdef ENABLE_GPL |
4518 | | printf("This build of Tor is covered by the GNU General Public License " |
4519 | | "(https://www.gnu.org/licenses/gpl-3.0.en.html)\n"); |
4520 | | #endif |
4521 | 0 | printf("Tor is running on %s with Libevent %s, " |
4522 | 0 | "%s %s, Zlib %s, Liblzma %s, Libzstd %s and %s %s as libc.\n", |
4523 | 0 | get_uname(), |
4524 | 0 | tor_libevent_get_version_str(), |
4525 | 0 | crypto_get_library_name(), |
4526 | 0 | crypto_get_library_version_string(), |
4527 | 0 | tor_compress_supports_method(ZLIB_METHOD) ? |
4528 | 0 | tor_compress_version_str(ZLIB_METHOD) : "N/A", |
4529 | 0 | tor_compress_supports_method(LZMA_METHOD) ? |
4530 | 0 | tor_compress_version_str(LZMA_METHOD) : "N/A", |
4531 | 0 | tor_compress_supports_method(ZSTD_METHOD) ? |
4532 | 0 | tor_compress_version_str(ZSTD_METHOD) : "N/A", |
4533 | 0 | tor_libc_get_name() ? |
4534 | 0 | tor_libc_get_name() : "Unknown", |
4535 | 0 | tor_libc_get_version_str()); |
4536 | 0 | printf("Tor compiled with %s version %s\n", |
4537 | 0 | strcmp(COMPILER_VENDOR, "gnu") == 0? |
4538 | 0 | COMPILER:COMPILER_VENDOR, COMPILER_VERSION); |
4539 | |
|
4540 | 0 | return 1; |
4541 | 0 | } |
4542 | | |
4543 | 0 | if (config_line_find(cmdline_only_options, "--list-modules")) { |
4544 | 0 | list_enabled_modules(); |
4545 | 0 | return 1; |
4546 | 0 | } |
4547 | | |
4548 | 0 | if (config_line_find(cmdline_only_options, "--library-versions")) { |
4549 | 0 | print_library_versions(); |
4550 | 0 | return 1; |
4551 | 0 | } |
4552 | | |
4553 | 0 | int command = global_cmdline->command; |
4554 | 0 | const char *command_arg = global_cmdline->command_arg; |
4555 | | /* "immediate" has already been handled by this point. */ |
4556 | 0 | tor_assert(command != CMD_IMMEDIATE); |
4557 | | |
4558 | 0 | if (command == CMD_HASH_PASSWORD) { |
4559 | 0 | cf_defaults = tor_strdup(""); |
4560 | 0 | cf = tor_strdup(""); |
4561 | 0 | } else { |
4562 | 0 | cf_defaults = load_torrc_from_disk(cmdline_only_options, 1); |
4563 | 0 | const config_line_t *f_line = config_line_find(cmdline_only_options, "-f"); |
4564 | 0 | const config_line_t *f_line_long = config_line_find(cmdline_only_options, |
4565 | 0 | "--torrc-file"); |
4566 | 0 | if (f_line && f_line_long) { |
4567 | 0 | log_err(LD_CONFIG, "-f and --torrc-file cannot be used together."); |
4568 | 0 | retval = -1; |
4569 | 0 | goto err; |
4570 | 0 | } else if (f_line_long) { |
4571 | 0 | f_line = f_line_long; |
4572 | 0 | } |
4573 | | |
4574 | 0 | const int read_torrc_from_stdin = |
4575 | 0 | (f_line != NULL && strcmp(f_line->value, "-") == 0); |
4576 | |
|
4577 | 0 | if (read_torrc_from_stdin) { |
4578 | 0 | cf = load_torrc_from_stdin(); |
4579 | 0 | } else { |
4580 | 0 | cf = load_torrc_from_disk(cmdline_only_options, 0); |
4581 | 0 | } |
4582 | |
|
4583 | 0 | if (!cf) { |
4584 | 0 | if (config_line_find(cmdline_only_options, "--allow-missing-torrc")) { |
4585 | 0 | cf = tor_strdup(""); |
4586 | 0 | } else { |
4587 | 0 | goto err; |
4588 | 0 | } |
4589 | 0 | } |
4590 | 0 | } |
4591 | | |
4592 | 0 | retval = options_init_from_string(cf_defaults, cf, command, command_arg, |
4593 | 0 | &errmsg); |
4594 | 0 | if (retval < 0) |
4595 | 0 | goto err; |
4596 | | |
4597 | 0 | if (config_line_find(cmdline_only_options, "--no-passphrase")) { |
4598 | 0 | if (handle_cmdline_no_passphrase(command) < 0) { |
4599 | 0 | retval = -1; |
4600 | 0 | goto err; |
4601 | 0 | } |
4602 | 0 | } |
4603 | | |
4604 | 0 | const config_line_t *format_line = config_line_find(cmdline_only_options, |
4605 | 0 | "--format"); |
4606 | 0 | if (format_line) { |
4607 | 0 | if (handle_cmdline_format(command, format_line->value) < 0) { |
4608 | 0 | retval = -1; |
4609 | 0 | goto err; |
4610 | 0 | } |
4611 | 0 | } else { |
4612 | 0 | get_options_mutable()->key_expiration_format = |
4613 | 0 | KEY_EXPIRATION_FORMAT_ISO8601; |
4614 | 0 | } |
4615 | | |
4616 | 0 | if (config_line_find(cmdline_only_options, "--newpass")) { |
4617 | 0 | if (handle_cmdline_newpass(command) < 0) { |
4618 | 0 | retval = -1; |
4619 | 0 | goto err; |
4620 | 0 | } |
4621 | 0 | } |
4622 | | |
4623 | 0 | const config_line_t *fd_line = config_line_find(cmdline_only_options, |
4624 | 0 | "--passphrase-fd"); |
4625 | 0 | if (fd_line) { |
4626 | 0 | if (handle_cmdline_passphrase_fd(command, fd_line->value) < 0) { |
4627 | 0 | retval = -1; |
4628 | 0 | goto err; |
4629 | 0 | } |
4630 | 0 | } |
4631 | | |
4632 | 0 | const config_line_t *key_line = config_line_find(cmdline_only_options, |
4633 | 0 | "--master-key"); |
4634 | 0 | if (key_line) { |
4635 | 0 | if (handle_cmdline_master_key(command, key_line->value) < 0) { |
4636 | 0 | retval = -1; |
4637 | 0 | goto err; |
4638 | 0 | } |
4639 | 0 | } |
4640 | | |
4641 | 0 | err: |
4642 | 0 | tor_free(cf); |
4643 | 0 | tor_free(cf_defaults); |
4644 | 0 | if (errmsg) { |
4645 | 0 | log_warn(LD_CONFIG,"%s", errmsg); |
4646 | 0 | tor_free(errmsg); |
4647 | 0 | } |
4648 | 0 | return retval < 0 ? -1 : 0; |
4649 | 0 | } |
4650 | | |
4651 | | /** Load the options from the configuration in <b>cf</b>, validate |
4652 | | * them for consistency and take actions based on them. |
4653 | | * |
4654 | | * Return 0 if success, negative on error: |
4655 | | * * -1 for general errors. |
4656 | | * * -2 for failure to parse/validate, |
4657 | | * * -3 for transition not allowed |
4658 | | * * -4 for error while setting the new options |
4659 | | */ |
4660 | | setopt_err_t |
4661 | | options_init_from_string(const char *cf_defaults, const char *cf, |
4662 | |