/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 | 225 | { |
1138 | 225 | if (get_options()->SafeLogging_ == SAFELOG_SCRUB_ALL) |
1139 | 225 | return "[scrubbed]"; |
1140 | 0 | else |
1141 | 0 | return escaped(address); |
1142 | 225 | } |
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 | | int command, const char *command_arg, |
4663 | | char **msg) |
4664 | 0 | { |
4665 | 0 | bool retry = false; |
4666 | 0 | or_options_t *oldoptions, *newoptions, *newdefaultoptions=NULL; |
4667 | 0 | config_line_t *cl; |
4668 | 0 | int retval; |
4669 | 0 | setopt_err_t err = SETOPT_ERR_MISC; |
4670 | 0 | int cf_has_include = 0; |
4671 | 0 | tor_assert(msg); |
4672 | | |
4673 | 0 | oldoptions = global_options; /* get_options unfortunately asserts if |
4674 | | this is the first time we run*/ |
4675 | |
|
4676 | 0 | newoptions = options_new(); |
4677 | 0 | options_init(newoptions); |
4678 | 0 | newoptions->command = command; |
4679 | 0 | newoptions->command_arg = command_arg ? tor_strdup(command_arg) : NULL; |
4680 | |
|
4681 | 0 | smartlist_t *opened_files = smartlist_new(); |
4682 | 0 | for (int i = 0; i < 2; ++i) { |
4683 | 0 | const char *body = i==0 ? cf_defaults : cf; |
4684 | 0 | if (!body) |
4685 | 0 | continue; |
4686 | | |
4687 | | /* get config lines, assign them */ |
4688 | 0 | retval = config_get_lines_include(body, &cl, 1, |
4689 | 0 | body == cf ? &cf_has_include : NULL, |
4690 | 0 | opened_files); |
4691 | 0 | if (retval < 0) { |
4692 | 0 | err = SETOPT_ERR_PARSE; |
4693 | 0 | goto err; |
4694 | 0 | } |
4695 | 0 | retval = config_assign(get_options_mgr(), newoptions, cl, |
4696 | 0 | CAL_WARN_DEPRECATIONS, msg); |
4697 | 0 | config_free_lines(cl); |
4698 | 0 | if (retval < 0) { |
4699 | 0 | err = SETOPT_ERR_PARSE; |
4700 | 0 | goto err; |
4701 | 0 | } |
4702 | 0 | if (i==0) |
4703 | 0 | newdefaultoptions = config_dup(get_options_mgr(), newoptions); |
4704 | 0 | } |
4705 | | |
4706 | 0 | if (newdefaultoptions == NULL) { |
4707 | 0 | newdefaultoptions = config_dup(get_options_mgr(), global_default_options); |
4708 | 0 | } |
4709 | | |
4710 | | /* Go through command-line variables too */ |
4711 | 0 | { |
4712 | 0 | config_line_t *other_opts = NULL; |
4713 | 0 | if (global_cmdline) { |
4714 | 0 | other_opts = global_cmdline->other_opts; |
4715 | 0 | } |
4716 | 0 | retval = config_assign(get_options_mgr(), newoptions, |
4717 | 0 | other_opts, |
4718 | 0 | CAL_WARN_DEPRECATIONS, msg); |
4719 | 0 | } |
4720 | 0 | if (retval < 0) { |
4721 | 0 | err = SETOPT_ERR_PARSE; |
4722 | 0 | goto err; |
4723 | 0 | } |
4724 | | |
4725 | 0 | newoptions->IncludeUsed = cf_has_include; |
4726 | 0 | newoptions->FilesOpenedByIncludes = opened_files; |
4727 | 0 | opened_files = NULL; // prevent double-free. |
4728 | | |
4729 | | /* If this is a testing network configuration, change defaults |
4730 | | * for a list of dependent config options, and try this function again. */ |
4731 | 0 | if (newoptions->TestingTorNetwork && ! testing_network_configured) { |
4732 | | // retry with the testing defaults. |
4733 | 0 | testing_network_configured = true; |
4734 | 0 | retry = true; |
4735 | 0 | goto err; |
4736 | 0 | } |
4737 | | |
4738 | 0 | err = options_validate_and_set(oldoptions, newoptions, msg); |
4739 | 0 | if (err < 0) { |
4740 | 0 | newoptions = NULL; // This was already freed in options_validate_and_set. |
4741 | 0 | goto err; |
4742 | 0 | } |
4743 | | |
4744 | 0 | or_options_free(global_default_options); |
4745 | 0 | global_default_options = newdefaultoptions; |
4746 | |
|
4747 | 0 | return SETOPT_OK; |
4748 | | |
4749 | 0 | err: |
4750 | 0 | in_option_validation = 0; |
4751 | 0 | if (opened_files) { |
4752 | 0 | SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f)); |
4753 | 0 | smartlist_free(opened_files); |
4754 | 0 | } |
4755 | 0 | or_options_free(newdefaultoptions); |
4756 | 0 | or_options_free(newoptions); |
4757 | 0 | if (*msg) { |
4758 | 0 | char *old_msg = *msg; |
4759 | 0 | tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg); |
4760 | 0 | tor_free(old_msg); |
4761 | 0 | } |
4762 | 0 | if (retry) |
4763 | 0 | return options_init_from_string(cf_defaults, cf, command, command_arg, |
4764 | 0 | msg); |
4765 | 0 | return err; |
4766 | 0 | } |
4767 | | |
4768 | | /** Return the location for our configuration file. May return NULL. |
4769 | | */ |
4770 | | const char * |
4771 | | get_torrc_fname(int defaults_fname) |
4772 | 0 | { |
4773 | 0 | const char *fname = defaults_fname ? torrc_defaults_fname : torrc_fname; |
4774 | |
|
4775 | 0 | if (fname) |
4776 | 0 | return fname; |
4777 | 0 | else |
4778 | 0 | return get_default_conf_file(defaults_fname); |
4779 | 0 | } |
4780 | | |
4781 | | /** Adjust the address map based on the MapAddress elements in the |
4782 | | * configuration <b>options</b> |
4783 | | */ |
4784 | | void |
4785 | | config_register_addressmaps(const or_options_t *options) |
4786 | 0 | { |
4787 | 0 | smartlist_t *elts; |
4788 | 0 | config_line_t *opt; |
4789 | 0 | const char *from, *to, *msg; |
4790 | |
|
4791 | 0 | addressmap_clear_configured(); |
4792 | 0 | elts = smartlist_new(); |
4793 | 0 | for (opt = options->AddressMap; opt; opt = opt->next) { |
4794 | 0 | smartlist_split_string(elts, opt->value, NULL, |
4795 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); |
4796 | 0 | if (smartlist_len(elts) < 2) { |
4797 | 0 | log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.", |
4798 | 0 | opt->value); |
4799 | 0 | goto cleanup; |
4800 | 0 | } |
4801 | | |
4802 | 0 | from = smartlist_get(elts,0); |
4803 | 0 | to = smartlist_get(elts,1); |
4804 | |
|
4805 | 0 | if (to[0] == '.' || from[0] == '.') { |
4806 | 0 | log_warn(LD_CONFIG,"MapAddress '%s' is ambiguous - address starts with a" |
4807 | 0 | "'.'. Ignoring.",opt->value); |
4808 | 0 | goto cleanup; |
4809 | 0 | } |
4810 | | |
4811 | 0 | if (addressmap_register_auto(from, to, 0, ADDRMAPSRC_TORRC, &msg) < 0) { |
4812 | 0 | log_warn(LD_CONFIG,"MapAddress '%s' failed: %s. Ignoring.", opt->value, |
4813 | 0 | msg); |
4814 | 0 | goto cleanup; |
4815 | 0 | } |
4816 | | |
4817 | 0 | if (smartlist_len(elts) > 2) |
4818 | 0 | log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress."); |
4819 | |
|
4820 | 0 | cleanup: |
4821 | 0 | SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp)); |
4822 | 0 | smartlist_clear(elts); |
4823 | 0 | } |
4824 | 0 | smartlist_free(elts); |
4825 | 0 | } |
4826 | | |
4827 | | /** As addressmap_register(), but detect the wildcarded status of "from" and |
4828 | | * "to", and do not steal a reference to <b>to</b>. */ |
4829 | | /* XXXX move to connection_edge.c */ |
4830 | | int |
4831 | | addressmap_register_auto(const char *from, const char *to, |
4832 | | time_t expires, |
4833 | | addressmap_entry_source_t addrmap_source, |
4834 | | const char **msg) |
4835 | 0 | { |
4836 | 0 | int from_wildcard = 0, to_wildcard = 0; |
4837 | |
|
4838 | 0 | *msg = "whoops, forgot the error message"; |
4839 | |
|
4840 | 0 | if (!strcmp(to, "*") || !strcmp(from, "*")) { |
4841 | 0 | *msg = "can't remap from or to *"; |
4842 | 0 | return -1; |
4843 | 0 | } |
4844 | | /* Detect asterisks in expressions of type: '*.example.com' */ |
4845 | 0 | if (!strncmp(from,"*.",2)) { |
4846 | 0 | from += 2; |
4847 | 0 | from_wildcard = 1; |
4848 | 0 | } |
4849 | 0 | if (!strncmp(to,"*.",2)) { |
4850 | 0 | to += 2; |
4851 | 0 | to_wildcard = 1; |
4852 | 0 | } |
4853 | |
|
4854 | 0 | if (to_wildcard && !from_wildcard) { |
4855 | 0 | *msg = "can only use wildcard (i.e. '*.') if 'from' address " |
4856 | 0 | "uses wildcard also"; |
4857 | 0 | return -1; |
4858 | 0 | } |
4859 | | |
4860 | 0 | if (address_is_invalid_destination(to, 1)) { |
4861 | 0 | *msg = "destination is invalid"; |
4862 | 0 | return -1; |
4863 | 0 | } |
4864 | | |
4865 | 0 | addressmap_register(from, tor_strdup(to), expires, addrmap_source, |
4866 | 0 | from_wildcard, to_wildcard, 0); |
4867 | |
|
4868 | 0 | return 0; |
4869 | 0 | } |
4870 | | |
4871 | | /** |
4872 | | * As add_file_log, but open the file as appropriate. |
4873 | | */ |
4874 | | STATIC int |
4875 | | open_and_add_file_log(const log_severity_list_t *severity, |
4876 | | const char *filename, int truncate_log) |
4877 | 0 | { |
4878 | 0 | int open_flags = O_WRONLY|O_CREAT; |
4879 | 0 | open_flags |= truncate_log ? O_TRUNC : O_APPEND; |
4880 | |
|
4881 | 0 | int fd = tor_open_cloexec(filename, open_flags, 0640); |
4882 | 0 | if (fd < 0) |
4883 | 0 | return -1; |
4884 | | |
4885 | 0 | return add_file_log(severity, filename, fd); |
4886 | 0 | } |
4887 | | |
4888 | | /** |
4889 | | * Try to set our global log granularity from `options->LogGranularity`, |
4890 | | * adjusting it as needed so that we are an even divisor of a second, or an |
4891 | | * even multiple of seconds. Return 0 on success, -1 on failure. |
4892 | | **/ |
4893 | | static int |
4894 | | options_init_log_granularity(const or_options_t *options, |
4895 | | int validate_only) |
4896 | 0 | { |
4897 | 0 | if (options->LogTimeGranularity <= 0) { |
4898 | 0 | log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.", |
4899 | 0 | options->LogTimeGranularity); |
4900 | 0 | return -1; |
4901 | 0 | } else if (1000 % options->LogTimeGranularity != 0 && |
4902 | 0 | options->LogTimeGranularity % 1000 != 0) { |
4903 | 0 | int granularity = options->LogTimeGranularity; |
4904 | 0 | if (granularity < 40) { |
4905 | 0 | do granularity++; |
4906 | 0 | while (1000 % granularity != 0); |
4907 | 0 | } else if (granularity < 1000) { |
4908 | 0 | granularity = 1000 / granularity; |
4909 | 0 | while (1000 % granularity != 0) |
4910 | 0 | granularity--; |
4911 | 0 | granularity = 1000 / granularity; |
4912 | 0 | } else { |
4913 | 0 | granularity = 1000 * ((granularity / 1000) + 1); |
4914 | 0 | } |
4915 | 0 | log_warn(LD_CONFIG, "Log time granularity '%d' has to be either a " |
4916 | 0 | "divisor or a multiple of 1 second. Changing to " |
4917 | 0 | "'%d'.", |
4918 | 0 | options->LogTimeGranularity, granularity); |
4919 | 0 | if (!validate_only) |
4920 | 0 | set_log_time_granularity(granularity); |
4921 | 0 | } else { |
4922 | 0 | if (!validate_only) |
4923 | 0 | set_log_time_granularity(options->LogTimeGranularity); |
4924 | 0 | } |
4925 | | |
4926 | 0 | return 0; |
4927 | 0 | } |
4928 | | |
4929 | | /** |
4930 | | * Initialize the logs based on the configuration file. |
4931 | | */ |
4932 | | STATIC int |
4933 | | options_init_logs(const or_options_t *old_options, const or_options_t *options, |
4934 | | int validate_only) |
4935 | 0 | { |
4936 | 0 | config_line_t *opt; |
4937 | 0 | int ok; |
4938 | 0 | smartlist_t *elts; |
4939 | 0 | int run_as_daemon = |
4940 | | #ifdef _WIN32 |
4941 | | 0; |
4942 | | #else |
4943 | 0 | options->RunAsDaemon; |
4944 | 0 | #endif |
4945 | |
|
4946 | 0 | if (options_init_log_granularity(options, validate_only) < 0) |
4947 | 0 | return -1; |
4948 | | |
4949 | 0 | ok = 1; |
4950 | 0 | elts = smartlist_new(); |
4951 | |
|
4952 | 0 | if (options->Logs == NULL && !run_as_daemon && !validate_only) { |
4953 | | /* When no logs are given, the default behavior is to log nothing (if |
4954 | | RunAsDaemon is set) or to log based on the quiet level otherwise. */ |
4955 | 0 | add_default_log_for_quiet_level(quiet_level); |
4956 | 0 | } |
4957 | |
|
4958 | 0 | for (opt = options->Logs; opt; opt = opt->next) { |
4959 | 0 | log_severity_list_t *severity; |
4960 | 0 | const char *cfg = opt->value; |
4961 | 0 | severity = tor_malloc_zero(sizeof(log_severity_list_t)); |
4962 | 0 | if (parse_log_severity_config(&cfg, severity) < 0) { |
4963 | 0 | log_warn(LD_CONFIG, "Couldn't parse log levels in Log option 'Log %s'", |
4964 | 0 | opt->value); |
4965 | 0 | ok = 0; goto cleanup; |
4966 | 0 | } |
4967 | | |
4968 | 0 | smartlist_split_string(elts, cfg, NULL, |
4969 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); |
4970 | |
|
4971 | 0 | if (smartlist_len(elts) == 0) |
4972 | 0 | smartlist_add_strdup(elts, "stdout"); |
4973 | |
|
4974 | 0 | if (smartlist_len(elts) == 1 && |
4975 | 0 | (!strcasecmp(smartlist_get(elts,0), "stdout") || |
4976 | 0 | !strcasecmp(smartlist_get(elts,0), "stderr"))) { |
4977 | 0 | int err = smartlist_len(elts) && |
4978 | 0 | !strcasecmp(smartlist_get(elts,0), "stderr"); |
4979 | 0 | if (!validate_only) { |
4980 | 0 | if (run_as_daemon) { |
4981 | 0 | log_warn(LD_CONFIG, |
4982 | 0 | "Can't log to %s with RunAsDaemon set; skipping stdout", |
4983 | 0 | err?"stderr":"stdout"); |
4984 | 0 | } else { |
4985 | 0 | add_stream_log(severity, err?"<stderr>":"<stdout>", |
4986 | 0 | fileno(err?stderr:stdout)); |
4987 | 0 | } |
4988 | 0 | } |
4989 | 0 | goto cleanup; |
4990 | 0 | } |
4991 | 0 | if (smartlist_len(elts) == 1) { |
4992 | 0 | if (!strcasecmp(smartlist_get(elts,0), "syslog")) { |
4993 | 0 | #ifdef HAVE_SYSLOG_H |
4994 | 0 | if (!validate_only) { |
4995 | 0 | add_syslog_log(severity, options->SyslogIdentityTag); |
4996 | 0 | } |
4997 | | #else |
4998 | | log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry."); |
4999 | | #endif /* defined(HAVE_SYSLOG_H) */ |
5000 | 0 | goto cleanup; |
5001 | 0 | } |
5002 | | |
5003 | | /* We added this workaround in 0.4.5.x; we can remove it in 0.4.6 or |
5004 | | * later */ |
5005 | 0 | if (!strcasecmp(smartlist_get(elts, 0), "android")) { |
5006 | 0 | #ifdef HAVE_SYSLOG_H |
5007 | 0 | log_warn(LD_CONFIG, "The android logging API is no longer supported;" |
5008 | 0 | " adding a syslog instead. The 'android' logging " |
5009 | 0 | " type will no longer work in the future."); |
5010 | 0 | if (!validate_only) { |
5011 | 0 | add_syslog_log(severity, options->SyslogIdentityTag); |
5012 | 0 | } |
5013 | | #else /* !defined(HAVE_SYSLOG_H) */ |
5014 | | log_warn(LD_CONFIG, "The android logging API is no longer supported."); |
5015 | | #endif /* defined(HAVE_SYSLOG_H) */ |
5016 | 0 | goto cleanup; |
5017 | 0 | } |
5018 | 0 | } |
5019 | | |
5020 | 0 | if (smartlist_len(elts) == 2 && |
5021 | 0 | !strcasecmp(smartlist_get(elts,0), "file")) { |
5022 | 0 | if (!validate_only) { |
5023 | 0 | char *fname = expand_filename(smartlist_get(elts, 1)); |
5024 | | /* Truncate if TruncateLogFile is set and we haven't seen this option |
5025 | | line before. */ |
5026 | 0 | int truncate_log = 0; |
5027 | 0 | if (options->TruncateLogFile) { |
5028 | 0 | truncate_log = 1; |
5029 | 0 | if (old_options) { |
5030 | 0 | config_line_t *opt2; |
5031 | 0 | for (opt2 = old_options->Logs; opt2; opt2 = opt2->next) |
5032 | 0 | if (!strcmp(opt->value, opt2->value)) { |
5033 | 0 | truncate_log = 0; |
5034 | 0 | break; |
5035 | 0 | } |
5036 | 0 | } |
5037 | 0 | } |
5038 | 0 | if (open_and_add_file_log(severity, fname, truncate_log) < 0) { |
5039 | 0 | log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s", |
5040 | 0 | opt->value, strerror(errno)); |
5041 | 0 | ok = 0; |
5042 | 0 | } |
5043 | 0 | tor_free(fname); |
5044 | 0 | } |
5045 | 0 | goto cleanup; |
5046 | 0 | } |
5047 | | |
5048 | 0 | log_warn(LD_CONFIG, "Bad syntax on file Log option 'Log %s'", |
5049 | 0 | opt->value); |
5050 | 0 | ok = 0; goto cleanup; |
5051 | | |
5052 | 0 | cleanup: |
5053 | 0 | SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp)); |
5054 | 0 | smartlist_clear(elts); |
5055 | 0 | tor_free(severity); |
5056 | 0 | } |
5057 | 0 | smartlist_free(elts); |
5058 | |
|
5059 | 0 | if (ok && !validate_only) |
5060 | 0 | logs_set_domain_logging(options->LogMessageDomains); |
5061 | |
|
5062 | 0 | return ok?0:-1; |
5063 | 0 | } |
5064 | | |
5065 | | /** Given a smartlist of SOCKS arguments to be passed to a transport |
5066 | | * proxy in <b>args</b>, validate them and return -1 if they are |
5067 | | * corrupted. Return 0 if they seem OK. */ |
5068 | | static int |
5069 | | validate_transport_socks_arguments(const smartlist_t *args) |
5070 | 0 | { |
5071 | 0 | char *socks_string = NULL; |
5072 | 0 | size_t socks_string_len; |
5073 | |
|
5074 | 0 | tor_assert(args); |
5075 | 0 | tor_assert(smartlist_len(args) > 0); |
5076 | | |
5077 | 0 | SMARTLIST_FOREACH_BEGIN(args, const char *, s) { |
5078 | 0 | if (!string_is_key_value(LOG_WARN, s)) { /* items should be k=v items */ |
5079 | 0 | log_warn(LD_CONFIG, "'%s' is not a k=v item.", s); |
5080 | 0 | return -1; |
5081 | 0 | } |
5082 | 0 | } SMARTLIST_FOREACH_END(s); |
5083 | | |
5084 | 0 | socks_string = pt_stringify_socks_args(args); |
5085 | 0 | if (!socks_string) |
5086 | 0 | return -1; |
5087 | | |
5088 | 0 | socks_string_len = strlen(socks_string); |
5089 | 0 | tor_free(socks_string); |
5090 | |
|
5091 | 0 | if (socks_string_len > MAX_SOCKS5_AUTH_SIZE_TOTAL) { |
5092 | 0 | log_warn(LD_CONFIG, "SOCKS arguments can't be more than %u bytes (%lu).", |
5093 | 0 | MAX_SOCKS5_AUTH_SIZE_TOTAL, |
5094 | 0 | (unsigned long) socks_string_len); |
5095 | 0 | return -1; |
5096 | 0 | } |
5097 | | |
5098 | 0 | return 0; |
5099 | 0 | } |
5100 | | |
5101 | | /** Deallocate a bridge_line_t structure. */ |
5102 | | /* private */ void |
5103 | | bridge_line_free_(bridge_line_t *bridge_line) |
5104 | 0 | { |
5105 | 0 | if (!bridge_line) |
5106 | 0 | return; |
5107 | | |
5108 | 0 | if (bridge_line->socks_args) { |
5109 | 0 | SMARTLIST_FOREACH(bridge_line->socks_args, char*, s, tor_free(s)); |
5110 | 0 | smartlist_free(bridge_line->socks_args); |
5111 | 0 | } |
5112 | 0 | tor_free(bridge_line->transport_name); |
5113 | 0 | tor_free(bridge_line); |
5114 | 0 | } |
5115 | | |
5116 | | /** Parse the contents of a string, <b>line</b>, containing a Bridge line, |
5117 | | * into a bridge_line_t. |
5118 | | * |
5119 | | * Validates that the IP:PORT, fingerprint, and SOCKS arguments (given to the |
5120 | | * Pluggable Transport, if a one was specified) are well-formed. |
5121 | | * |
5122 | | * Returns NULL If the Bridge line could not be validated, and returns a |
5123 | | * bridge_line_t containing the parsed information otherwise. |
5124 | | * |
5125 | | * Bridge line format: |
5126 | | * Bridge [transport] IP:PORT [id-fingerprint] [k=v] [k=v] ... |
5127 | | */ |
5128 | | /* private */ bridge_line_t * |
5129 | | parse_bridge_line(const char *line) |
5130 | 0 | { |
5131 | 0 | smartlist_t *items = NULL; |
5132 | 0 | char *addrport=NULL, *fingerprint=NULL; |
5133 | 0 | char *field=NULL; |
5134 | 0 | bridge_line_t *bridge_line = tor_malloc_zero(sizeof(bridge_line_t)); |
5135 | |
|
5136 | 0 | items = smartlist_new(); |
5137 | 0 | smartlist_split_string(items, line, NULL, |
5138 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); |
5139 | 0 | if (smartlist_len(items) < 1) { |
5140 | 0 | log_warn(LD_CONFIG, "Too few arguments to Bridge line."); |
5141 | 0 | goto err; |
5142 | 0 | } |
5143 | | |
5144 | | /* first field is either a transport name or addrport */ |
5145 | 0 | field = smartlist_get(items, 0); |
5146 | 0 | smartlist_del_keeporder(items, 0); |
5147 | |
|
5148 | 0 | if (string_is_C_identifier(field)) { |
5149 | | /* It's a transport name. */ |
5150 | 0 | bridge_line->transport_name = field; |
5151 | 0 | if (smartlist_len(items) < 1) { |
5152 | 0 | log_warn(LD_CONFIG, "Too few items to Bridge line."); |
5153 | 0 | goto err; |
5154 | 0 | } |
5155 | 0 | addrport = smartlist_get(items, 0); /* Next field is addrport then. */ |
5156 | 0 | smartlist_del_keeporder(items, 0); |
5157 | 0 | } else { |
5158 | 0 | addrport = field; |
5159 | 0 | } |
5160 | | |
5161 | 0 | if (tor_addr_port_parse(LOG_INFO, addrport, |
5162 | 0 | &bridge_line->addr, &bridge_line->port, 443)<0) { |
5163 | 0 | log_warn(LD_CONFIG, "Error parsing Bridge address '%s'", addrport); |
5164 | 0 | goto err; |
5165 | 0 | } |
5166 | | |
5167 | | /* If transports are enabled, next field could be a fingerprint or a |
5168 | | socks argument. If transports are disabled, next field must be |
5169 | | a fingerprint. */ |
5170 | 0 | if (smartlist_len(items)) { |
5171 | 0 | if (bridge_line->transport_name) { /* transports enabled: */ |
5172 | 0 | field = smartlist_get(items, 0); |
5173 | 0 | smartlist_del_keeporder(items, 0); |
5174 | | |
5175 | | /* If it's a key=value pair, then it's a SOCKS argument for the |
5176 | | transport proxy... */ |
5177 | 0 | if (string_is_key_value(LOG_DEBUG, field)) { |
5178 | 0 | bridge_line->socks_args = smartlist_new(); |
5179 | 0 | smartlist_add(bridge_line->socks_args, field); |
5180 | 0 | } else { /* ...otherwise, it's the bridge fingerprint. */ |
5181 | 0 | fingerprint = field; |
5182 | 0 | } |
5183 | |
|
5184 | 0 | } else { /* transports disabled: */ |
5185 | 0 | fingerprint = smartlist_join_strings(items, "", 0, NULL); |
5186 | 0 | } |
5187 | 0 | } |
5188 | | |
5189 | | /* Handle fingerprint, if it was provided. */ |
5190 | 0 | if (fingerprint) { |
5191 | 0 | if (strlen(fingerprint) != HEX_DIGEST_LEN) { |
5192 | 0 | log_warn(LD_CONFIG, "Key digest for Bridge is wrong length."); |
5193 | 0 | goto err; |
5194 | 0 | } |
5195 | 0 | if (base16_decode(bridge_line->digest, DIGEST_LEN, |
5196 | 0 | fingerprint, HEX_DIGEST_LEN) != DIGEST_LEN) { |
5197 | 0 | log_warn(LD_CONFIG, "Unable to decode Bridge key digest."); |
5198 | 0 | goto err; |
5199 | 0 | } |
5200 | 0 | } |
5201 | | |
5202 | | /* If we are using transports, any remaining items in the smartlist |
5203 | | should be k=v values. */ |
5204 | 0 | if (bridge_line->transport_name && smartlist_len(items)) { |
5205 | 0 | if (!bridge_line->socks_args) |
5206 | 0 | bridge_line->socks_args = smartlist_new(); |
5207 | | |
5208 | | /* append remaining items of 'items' to 'socks_args' */ |
5209 | 0 | smartlist_add_all(bridge_line->socks_args, items); |
5210 | 0 | smartlist_clear(items); |
5211 | |
|
5212 | 0 | tor_assert(smartlist_len(bridge_line->socks_args) > 0); |
5213 | 0 | } |
5214 | | |
5215 | 0 | if (bridge_line->socks_args) { |
5216 | 0 | if (validate_transport_socks_arguments(bridge_line->socks_args) < 0) |
5217 | 0 | goto err; |
5218 | 0 | } |
5219 | | |
5220 | 0 | goto done; |
5221 | | |
5222 | 0 | err: |
5223 | 0 | bridge_line_free(bridge_line); |
5224 | 0 | bridge_line = NULL; |
5225 | |
|
5226 | 0 | done: |
5227 | 0 | SMARTLIST_FOREACH(items, char*, s, tor_free(s)); |
5228 | 0 | smartlist_free(items); |
5229 | 0 | tor_free(addrport); |
5230 | 0 | tor_free(fingerprint); |
5231 | |
|
5232 | 0 | return bridge_line; |
5233 | 0 | } |
5234 | | |
5235 | | /** Parse the contents of a TCPProxy line from <b>line</b> and put it |
5236 | | * in <b>options</b>. Return 0 if the line is well-formed, and -1 if it |
5237 | | * isn't. |
5238 | | * |
5239 | | * This will mutate only options->TCPProxyProtocol, options->TCPProxyAddr, |
5240 | | * and options->TCPProxyPort. |
5241 | | * |
5242 | | * On error, tor_strdup an error explanation into *<b>msg</b>. |
5243 | | */ |
5244 | | STATIC int |
5245 | | parse_tcp_proxy_line(const char *line, or_options_t *options, char **msg) |
5246 | 0 | { |
5247 | 0 | int ret = 0; |
5248 | 0 | tor_assert(line); |
5249 | 0 | tor_assert(options); |
5250 | 0 | tor_assert(msg); |
5251 | | |
5252 | 0 | smartlist_t *sl = smartlist_new(); |
5253 | | /* Split between the protocol and the address/port. */ |
5254 | 0 | smartlist_split_string(sl, line, " ", |
5255 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); |
5256 | | |
5257 | | /* The address/port is not specified. */ |
5258 | 0 | if (smartlist_len(sl) < 2) { |
5259 | 0 | *msg = tor_strdup("TCPProxy has no address/port. Please fix."); |
5260 | 0 | goto err; |
5261 | 0 | } |
5262 | | |
5263 | 0 | char *protocol_string = smartlist_get(sl, 0); |
5264 | 0 | char *addrport_string = smartlist_get(sl, 1); |
5265 | | |
5266 | | /* The only currently supported protocol is 'haproxy'. */ |
5267 | 0 | if (strcasecmp(protocol_string, "haproxy")) { |
5268 | 0 | *msg = tor_strdup("TCPProxy protocol is not supported. Currently " |
5269 | 0 | "the only supported protocol is 'haproxy'. " |
5270 | 0 | "Please fix."); |
5271 | 0 | goto err; |
5272 | 0 | } else { |
5273 | | /* Otherwise, set the correct protocol. */ |
5274 | 0 | options->TCPProxyProtocol = TCP_PROXY_PROTOCOL_HAPROXY; |
5275 | 0 | } |
5276 | | |
5277 | | /* Parse the address/port. */ |
5278 | 0 | if (tor_addr_port_lookup(addrport_string, &options->TCPProxyAddr, |
5279 | 0 | &options->TCPProxyPort) < 0) { |
5280 | 0 | *msg = tor_strdup("TCPProxy address/port failed to parse or resolve. " |
5281 | 0 | "Please fix."); |
5282 | 0 | goto err; |
5283 | 0 | } |
5284 | | |
5285 | | /* Success. */ |
5286 | 0 | ret = 0; |
5287 | 0 | goto end; |
5288 | | |
5289 | 0 | err: |
5290 | 0 | ret = -1; |
5291 | 0 | end: |
5292 | 0 | SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); |
5293 | 0 | smartlist_free(sl); |
5294 | 0 | return ret; |
5295 | 0 | } |
5296 | | |
5297 | | /** Read the contents of a ClientTransportPlugin or ServerTransportPlugin |
5298 | | * line from <b>line</b>, depending on the value of <b>server</b>. Return 0 |
5299 | | * if the line is well-formed, and -1 if it isn't. |
5300 | | * |
5301 | | * If <b>validate_only</b> is 0, the line is well-formed, and the transport is |
5302 | | * needed by some bridge: |
5303 | | * - If it's an external proxy line, add the transport described in the line to |
5304 | | * our internal transport list. |
5305 | | * - If it's a managed proxy line, launch the managed proxy. |
5306 | | */ |
5307 | | int |
5308 | | pt_parse_transport_line(const or_options_t *options, |
5309 | | const char *line, int validate_only, |
5310 | | int server) |
5311 | 0 | { |
5312 | |
|
5313 | 0 | smartlist_t *items = NULL; |
5314 | 0 | int r; |
5315 | 0 | const char *transports = NULL; |
5316 | 0 | smartlist_t *transport_list = NULL; |
5317 | 0 | char *type = NULL; |
5318 | 0 | char *addrport = NULL; |
5319 | 0 | tor_addr_t addr; |
5320 | 0 | uint16_t port = 0; |
5321 | 0 | int socks_ver = PROXY_NONE; |
5322 | | |
5323 | | /* managed proxy options */ |
5324 | 0 | int is_managed = 0; |
5325 | 0 | char **proxy_argv = NULL; |
5326 | 0 | char **tmp = NULL; |
5327 | 0 | int proxy_argc, i; |
5328 | 0 | int is_useless_proxy = 1; |
5329 | |
|
5330 | 0 | int line_length; |
5331 | | |
5332 | | /* Split the line into space-separated tokens */ |
5333 | 0 | items = smartlist_new(); |
5334 | 0 | smartlist_split_string(items, line, NULL, |
5335 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); |
5336 | 0 | line_length = smartlist_len(items); |
5337 | |
|
5338 | 0 | if (line_length < 3) { |
5339 | 0 | log_warn(LD_CONFIG, |
5340 | 0 | "Too few arguments on %sTransportPlugin line.", |
5341 | 0 | server ? "Server" : "Client"); |
5342 | 0 | goto err; |
5343 | 0 | } |
5344 | | |
5345 | | /* Get the first line element, split it to commas into |
5346 | | transport_list (in case it's multiple transports) and validate |
5347 | | the transport names. */ |
5348 | 0 | transports = smartlist_get(items, 0); |
5349 | 0 | transport_list = smartlist_new(); |
5350 | 0 | smartlist_split_string(transport_list, transports, ",", |
5351 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); |
5352 | 0 | SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) { |
5353 | | /* validate transport names */ |
5354 | 0 | if (!string_is_C_identifier(transport_name)) { |
5355 | 0 | log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).", |
5356 | 0 | transport_name); |
5357 | 0 | goto err; |
5358 | 0 | } |
5359 | | |
5360 | | /* see if we actually need the transports provided by this proxy */ |
5361 | 0 | if (!validate_only && transport_is_needed(transport_name)) |
5362 | 0 | is_useless_proxy = 0; |
5363 | 0 | } SMARTLIST_FOREACH_END(transport_name); |
5364 | | |
5365 | 0 | type = smartlist_get(items, 1); |
5366 | 0 | if (!strcmp(type, "exec")) { |
5367 | 0 | is_managed = 1; |
5368 | 0 | } else if (server && !strcmp(type, "proxy")) { |
5369 | | /* 'proxy' syntax only with ServerTransportPlugin */ |
5370 | 0 | is_managed = 0; |
5371 | 0 | } else if (!server && !strcmp(type, "socks4")) { |
5372 | | /* 'socks4' syntax only with ClientTransportPlugin */ |
5373 | 0 | is_managed = 0; |
5374 | 0 | socks_ver = PROXY_SOCKS4; |
5375 | 0 | } else if (!server && !strcmp(type, "socks5")) { |
5376 | | /* 'socks5' syntax only with ClientTransportPlugin */ |
5377 | 0 | is_managed = 0; |
5378 | 0 | socks_ver = PROXY_SOCKS5; |
5379 | 0 | } else { |
5380 | 0 | log_warn(LD_CONFIG, |
5381 | 0 | "Strange %sTransportPlugin type '%s'", |
5382 | 0 | server ? "Server" : "Client", type); |
5383 | 0 | goto err; |
5384 | 0 | } |
5385 | | |
5386 | 0 | if (is_managed && options->Sandbox) { |
5387 | 0 | log_warn(LD_CONFIG, |
5388 | 0 | "Managed proxies are not compatible with Sandbox mode." |
5389 | 0 | "(%sTransportPlugin line was %s)", |
5390 | 0 | server ? "Server" : "Client", escaped(line)); |
5391 | 0 | goto err; |
5392 | 0 | } |
5393 | | |
5394 | 0 | if (is_managed && options->NoExec) { |
5395 | 0 | log_warn(LD_CONFIG, |
5396 | 0 | "Managed proxies are not compatible with NoExec mode; ignoring." |
5397 | 0 | "(%sTransportPlugin line was %s)", |
5398 | 0 | server ? "Server" : "Client", escaped(line)); |
5399 | 0 | r = 0; |
5400 | 0 | goto done; |
5401 | 0 | } |
5402 | | |
5403 | 0 | if (is_managed) { |
5404 | | /* managed */ |
5405 | |
|
5406 | 0 | if (!server && !validate_only && is_useless_proxy) { |
5407 | 0 | log_info(LD_GENERAL, |
5408 | 0 | "Pluggable transport proxy (%s) does not provide " |
5409 | 0 | "any needed transports and will not be launched.", |
5410 | 0 | line); |
5411 | 0 | } |
5412 | | |
5413 | | /* |
5414 | | * If we are not just validating, use the rest of the line as the |
5415 | | * argv of the proxy to be launched. Also, make sure that we are |
5416 | | * only launching proxies that contribute useful transports. |
5417 | | */ |
5418 | |
|
5419 | 0 | if (!validate_only && (server || !is_useless_proxy)) { |
5420 | 0 | proxy_argc = line_length - 2; |
5421 | 0 | tor_assert(proxy_argc > 0); |
5422 | 0 | proxy_argv = tor_calloc((proxy_argc + 1), sizeof(char *)); |
5423 | 0 | tmp = proxy_argv; |
5424 | |
|
5425 | 0 | for (i = 0; i < proxy_argc; i++) { |
5426 | | /* store arguments */ |
5427 | 0 | *tmp++ = smartlist_get(items, 2); |
5428 | 0 | smartlist_del_keeporder(items, 2); |
5429 | 0 | } |
5430 | 0 | *tmp = NULL; /* terminated with NULL, just like execve() likes it */ |
5431 | | |
5432 | | /* kickstart the thing */ |
5433 | 0 | if (server) { |
5434 | 0 | pt_kickstart_server_proxy(transport_list, proxy_argv); |
5435 | 0 | } else { |
5436 | 0 | pt_kickstart_client_proxy(transport_list, proxy_argv); |
5437 | 0 | } |
5438 | 0 | } |
5439 | 0 | } else { |
5440 | | /* external */ |
5441 | | |
5442 | | /* ClientTransportPlugins connecting through a proxy is managed only. */ |
5443 | 0 | if (!server && (options->Socks4Proxy || options->Socks5Proxy || |
5444 | 0 | options->HTTPSProxy || options->TCPProxy)) { |
5445 | 0 | log_warn(LD_CONFIG, "You have configured an external proxy with another " |
5446 | 0 | "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy|" |
5447 | 0 | "TCPProxy)"); |
5448 | 0 | goto err; |
5449 | 0 | } |
5450 | | |
5451 | 0 | if (smartlist_len(transport_list) != 1) { |
5452 | 0 | log_warn(LD_CONFIG, |
5453 | 0 | "You can't have an external proxy with more than " |
5454 | 0 | "one transport."); |
5455 | 0 | goto err; |
5456 | 0 | } |
5457 | | |
5458 | 0 | addrport = smartlist_get(items, 2); |
5459 | |
|
5460 | 0 | if (tor_addr_port_lookup(addrport, &addr, &port) < 0) { |
5461 | 0 | log_warn(LD_CONFIG, |
5462 | 0 | "Error parsing transport address '%s'", addrport); |
5463 | 0 | goto err; |
5464 | 0 | } |
5465 | | |
5466 | 0 | if (!port) { |
5467 | 0 | log_warn(LD_CONFIG, |
5468 | 0 | "Transport address '%s' has no port.", addrport); |
5469 | 0 | goto err; |
5470 | 0 | } |
5471 | | |
5472 | 0 | if (!validate_only) { |
5473 | 0 | log_info(LD_DIR, "%s '%s' at %s.", |
5474 | 0 | server ? "Server transport" : "Transport", |
5475 | 0 | transports, fmt_addrport(&addr, port)); |
5476 | |
|
5477 | 0 | if (!server) { |
5478 | 0 | transport_add_from_config(&addr, port, |
5479 | 0 | smartlist_get(transport_list, 0), |
5480 | 0 | socks_ver); |
5481 | 0 | } |
5482 | 0 | } |
5483 | 0 | } |
5484 | | |
5485 | 0 | r = 0; |
5486 | 0 | goto done; |
5487 | | |
5488 | 0 | err: |
5489 | 0 | r = -1; |
5490 | |
|
5491 | 0 | done: |
5492 | 0 | SMARTLIST_FOREACH(items, char*, s, tor_free(s)); |
5493 | 0 | smartlist_free(items); |
5494 | 0 | if (transport_list) { |
5495 | 0 | SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s)); |
5496 | 0 | smartlist_free(transport_list); |
5497 | 0 | } |
5498 | |
|
5499 | 0 | return r; |
5500 | 0 | } |
5501 | | |
5502 | | /** |
5503 | | * Parse a flag describing an extra dirport for a directory authority. |
5504 | | * |
5505 | | * Right now, the supported format is exactly: |
5506 | | * `{upload,download,voting}=http://[IP:PORT]/`. |
5507 | | * Other URL schemes, and other suffixes, might be supported in the future. |
5508 | | * |
5509 | | * Only call this function if `flag` starts with one of the above strings. |
5510 | | * |
5511 | | * Return 0 on success, and -1 on failure. |
5512 | | * |
5513 | | * If `ds` is provided, then add any parsed dirport to `ds`. If `ds` is NULL, |
5514 | | * take no action other than parsing. |
5515 | | **/ |
5516 | | static int |
5517 | | parse_dirauth_dirport(dir_server_t *ds, const char *flag) |
5518 | 0 | { |
5519 | 0 | tor_assert(flag); |
5520 | | |
5521 | 0 | auth_dirport_usage_t usage; |
5522 | |
|
5523 | 0 | if (!strcasecmpstart(flag, "upload=")) { |
5524 | 0 | usage = AUTH_USAGE_UPLOAD; |
5525 | 0 | } else if (!strcasecmpstart(flag, "download=")) { |
5526 | 0 | usage = AUTH_USAGE_DOWNLOAD; |
5527 | 0 | } else if (!strcasecmpstart(flag, "vote=")) { |
5528 | 0 | usage = AUTH_USAGE_VOTING; |
5529 | 0 | } else { |
5530 | | // We shouldn't get called with a flag that we don't recognize. |
5531 | 0 | tor_assert_nonfatal_unreached(); |
5532 | 0 | return -1; |
5533 | 0 | } |
5534 | | |
5535 | 0 | const char *eq = strchr(flag, '='); |
5536 | 0 | tor_assert(eq); |
5537 | 0 | const char *target = eq + 1; |
5538 | | |
5539 | | // Find the part inside the http://{....}/ |
5540 | 0 | if (strcmpstart(target, "http://")) { |
5541 | 0 | log_warn(LD_CONFIG, "Unsupported URL scheme in authority flag %s", flag); |
5542 | 0 | return -1; |
5543 | 0 | } |
5544 | 0 | const char *addr = target + strlen("http://"); |
5545 | |
|
5546 | 0 | const char *eos = strchr(addr, '/'); |
5547 | 0 | size_t addr_len; |
5548 | 0 | if (eos && strcmp(eos, "/")) { |
5549 | 0 | log_warn(LD_CONFIG, "Unsupported URL prefix in authority flag %s", flag); |
5550 | 0 | return -1; |
5551 | 0 | } else if (eos) { |
5552 | 0 | addr_len = eos - addr; |
5553 | 0 | } else { |
5554 | 0 | addr_len = strlen(addr); |
5555 | 0 | } |
5556 | | |
5557 | | // Finally, parse the addr:port part. |
5558 | 0 | char *addr_string = tor_strndup(addr, addr_len); |
5559 | 0 | tor_addr_port_t dirport; |
5560 | 0 | memset(&dirport, 0, sizeof(dirport)); |
5561 | 0 | int rv = tor_addr_port_parse(LOG_WARN, addr_string, |
5562 | 0 | &dirport.addr, &dirport.port, -1); |
5563 | 0 | if (ds != NULL && rv == 0) { |
5564 | 0 | trusted_dir_server_add_dirport(ds, usage, &dirport); |
5565 | 0 | } else if (rv == -1) { |
5566 | 0 | log_warn(LD_CONFIG, "Unable to parse address in authority flag %s",flag); |
5567 | 0 | } |
5568 | |
|
5569 | 0 | tor_free(addr_string); |
5570 | 0 | return rv; |
5571 | 0 | } |
5572 | | |
5573 | | /** Read the contents of a DirAuthority line from <b>line</b>. If |
5574 | | * <b>validate_only</b> is 0, and the line is well-formed, and it |
5575 | | * shares any bits with <b>required_type</b> or <b>required_type</b> |
5576 | | * is NO_DIRINFO (zero), then add the dirserver described in the line |
5577 | | * (minus whatever bits it's missing) as a valid authority. |
5578 | | * Return 0 on success or filtering out by type, |
5579 | | * or -1 if the line isn't well-formed or if we can't add it. */ |
5580 | | STATIC int |
5581 | | parse_dir_authority_line(const char *line, dirinfo_type_t required_type, |
5582 | | int validate_only) |
5583 | 0 | { |
5584 | 0 | smartlist_t *items = NULL; |
5585 | 0 | int r; |
5586 | 0 | char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL; |
5587 | 0 | tor_addr_port_t ipv6_addrport, *ipv6_addrport_ptr = NULL; |
5588 | 0 | uint16_t dir_port = 0, or_port = 0; |
5589 | 0 | char digest[DIGEST_LEN]; |
5590 | 0 | char v3_digest[DIGEST_LEN]; |
5591 | 0 | dirinfo_type_t type = 0; |
5592 | 0 | double weight = 1.0; |
5593 | 0 | smartlist_t *extra_dirports = smartlist_new(); |
5594 | |
|
5595 | 0 | memset(v3_digest, 0, sizeof(v3_digest)); |
5596 | |
|
5597 | 0 | items = smartlist_new(); |
5598 | 0 | smartlist_split_string(items, line, NULL, |
5599 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); |
5600 | 0 | if (smartlist_len(items) < 1) { |
5601 | 0 | log_warn(LD_CONFIG, "No arguments on DirAuthority line."); |
5602 | 0 | goto err; |
5603 | 0 | } |
5604 | | |
5605 | 0 | if (is_legal_nickname(smartlist_get(items, 0))) { |
5606 | 0 | nickname = smartlist_get(items, 0); |
5607 | 0 | smartlist_del_keeporder(items, 0); |
5608 | 0 | } |
5609 | |
|
5610 | 0 | while (smartlist_len(items)) { |
5611 | 0 | char *flag = smartlist_get(items, 0); |
5612 | 0 | if (TOR_ISDIGIT(flag[0])) |
5613 | 0 | break; |
5614 | 0 | if (!strcasecmp(flag, "hs") || |
5615 | 0 | !strcasecmp(flag, "no-hs")) { |
5616 | 0 | log_warn(LD_CONFIG, "The DirAuthority options 'hs' and 'no-hs' are " |
5617 | 0 | "obsolete; you don't need them any more."); |
5618 | 0 | } else if (!strcasecmp(flag, "bridge")) { |
5619 | 0 | type |= BRIDGE_DIRINFO; |
5620 | 0 | } else if (!strcasecmp(flag, "no-v2")) { |
5621 | | /* obsolete, but may still be contained in DirAuthority lines generated |
5622 | 0 | by various tools */; |
5623 | 0 | } else if (!strcasecmpstart(flag, "orport=")) { |
5624 | 0 | int ok; |
5625 | 0 | char *portstring = flag + strlen("orport="); |
5626 | 0 | or_port = (uint16_t) tor_parse_long(portstring, 10, 1, 65535, &ok, NULL); |
5627 | 0 | if (!ok) |
5628 | 0 | log_warn(LD_CONFIG, "Invalid orport '%s' on DirAuthority line.", |
5629 | 0 | portstring); |
5630 | 0 | } else if (!strcmpstart(flag, "weight=")) { |
5631 | 0 | int ok; |
5632 | 0 | const char *wstring = flag + strlen("weight="); |
5633 | 0 | weight = tor_parse_double(wstring, 0, (double)UINT64_MAX, &ok, NULL); |
5634 | 0 | if (!ok) { |
5635 | 0 | log_warn(LD_CONFIG, "Invalid weight '%s' on DirAuthority line.",flag); |
5636 | 0 | weight=1.0; |
5637 | 0 | } |
5638 | 0 | } else if (!strcasecmpstart(flag, "v3ident=")) { |
5639 | 0 | char *idstr = flag + strlen("v3ident="); |
5640 | 0 | if (strlen(idstr) != HEX_DIGEST_LEN || |
5641 | 0 | base16_decode(v3_digest, DIGEST_LEN, |
5642 | 0 | idstr, HEX_DIGEST_LEN) != DIGEST_LEN) { |
5643 | 0 | log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirAuthority line", |
5644 | 0 | flag); |
5645 | 0 | } else { |
5646 | 0 | type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO; |
5647 | 0 | } |
5648 | 0 | } else if (!strcasecmpstart(flag, "ipv6=")) { |
5649 | 0 | if (ipv6_addrport_ptr) { |
5650 | 0 | log_warn(LD_CONFIG, "Redundant ipv6 addr/port on DirAuthority line"); |
5651 | 0 | } else { |
5652 | 0 | if (tor_addr_port_parse(LOG_WARN, flag+strlen("ipv6="), |
5653 | 0 | &ipv6_addrport.addr, &ipv6_addrport.port, |
5654 | 0 | -1) < 0 |
5655 | 0 | || tor_addr_family(&ipv6_addrport.addr) != AF_INET6) { |
5656 | 0 | log_warn(LD_CONFIG, "Bad ipv6 addr/port %s on DirAuthority line", |
5657 | 0 | escaped(flag)); |
5658 | 0 | goto err; |
5659 | 0 | } |
5660 | 0 | ipv6_addrport_ptr = &ipv6_addrport; |
5661 | 0 | } |
5662 | 0 | } else if (!strcasecmpstart(flag, "upload=") || |
5663 | 0 | !strcasecmpstart(flag, "download=") || |
5664 | 0 | !strcasecmpstart(flag, "vote=")) { |
5665 | | // We'll handle these after creating the authority object. |
5666 | 0 | smartlist_add(extra_dirports, flag); |
5667 | 0 | flag = NULL; // prevent double-free. |
5668 | 0 | } else { |
5669 | 0 | log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirAuthority line", |
5670 | 0 | flag); |
5671 | 0 | } |
5672 | 0 | tor_free(flag); |
5673 | 0 | smartlist_del_keeporder(items, 0); |
5674 | 0 | } |
5675 | | |
5676 | 0 | if (smartlist_len(items) < 2) { |
5677 | 0 | log_warn(LD_CONFIG, "Too few arguments to DirAuthority line."); |
5678 | 0 | goto err; |
5679 | 0 | } |
5680 | 0 | addrport = smartlist_get(items, 0); |
5681 | 0 | smartlist_del_keeporder(items, 0); |
5682 | |
|
5683 | 0 | if (tor_addr_port_split(LOG_WARN, addrport, &address, &dir_port) < 0) { |
5684 | 0 | log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s'.", addrport); |
5685 | 0 | goto err; |
5686 | 0 | } |
5687 | | |
5688 | 0 | if (!string_is_valid_ipv4_address(address)) { |
5689 | 0 | log_warn(LD_CONFIG, "Error parsing DirAuthority address '%s' " |
5690 | 0 | "(invalid IPv4 address)", address); |
5691 | 0 | goto err; |
5692 | 0 | } |
5693 | | |
5694 | 0 | if (!dir_port) { |
5695 | 0 | log_warn(LD_CONFIG, "Missing port in DirAuthority address '%s'",addrport); |
5696 | 0 | goto err; |
5697 | 0 | } |
5698 | | |
5699 | 0 | fingerprint = smartlist_join_strings(items, "", 0, NULL); |
5700 | 0 | if (strlen(fingerprint) != HEX_DIGEST_LEN) { |
5701 | 0 | log_warn(LD_CONFIG, "Key digest '%s' for DirAuthority is wrong length %d.", |
5702 | 0 | fingerprint, (int)strlen(fingerprint)); |
5703 | 0 | goto err; |
5704 | 0 | } |
5705 | 0 | if (base16_decode(digest, DIGEST_LEN, |
5706 | 0 | fingerprint, HEX_DIGEST_LEN) != DIGEST_LEN) { |
5707 | 0 | log_warn(LD_CONFIG, "Unable to decode DirAuthority key digest."); |
5708 | 0 | goto err; |
5709 | 0 | } |
5710 | | |
5711 | 0 | if (validate_only) { |
5712 | 0 | SMARTLIST_FOREACH_BEGIN(extra_dirports, const char *, cp) { |
5713 | 0 | if (parse_dirauth_dirport(NULL, cp) < 0) |
5714 | 0 | goto err; |
5715 | 0 | } SMARTLIST_FOREACH_END(cp); |
5716 | 0 | } |
5717 | | |
5718 | 0 | if (!validate_only && (!required_type || required_type & type)) { |
5719 | 0 | dir_server_t *ds; |
5720 | 0 | if (required_type) |
5721 | 0 | type &= required_type; /* pare down what we think of them as an |
5722 | | * authority for. */ |
5723 | 0 | log_debug(LD_DIR, "Trusted %d dirserver at %s:%d (%s)", (int)type, |
5724 | 0 | address, (int)dir_port, (char*)smartlist_get(items,0)); |
5725 | 0 | if (!(ds = trusted_dir_server_new(nickname, address, dir_port, or_port, |
5726 | 0 | ipv6_addrport_ptr, |
5727 | 0 | digest, v3_digest, type, weight))) |
5728 | 0 | goto err; |
5729 | | |
5730 | 0 | SMARTLIST_FOREACH_BEGIN(extra_dirports, const char *, cp) { |
5731 | 0 | if (parse_dirauth_dirport(ds, cp) < 0) |
5732 | 0 | goto err; |
5733 | 0 | } SMARTLIST_FOREACH_END(cp); |
5734 | 0 | dir_server_add(ds); |
5735 | 0 | } |
5736 | | |
5737 | 0 | r = 0; |
5738 | 0 | goto done; |
5739 | | |
5740 | 0 | err: |
5741 | 0 | r = -1; |
5742 | |
|
5743 | 0 | done: |
5744 | 0 | SMARTLIST_FOREACH(extra_dirports, char*, s, tor_free(s)); |
5745 | 0 | smartlist_free(extra_dirports); |
5746 | 0 | SMARTLIST_FOREACH(items, char*, s, tor_free(s)); |
5747 | 0 | smartlist_free(items); |
5748 | 0 | tor_free(addrport); |
5749 | 0 | tor_free(address); |
5750 | 0 | tor_free(nickname); |
5751 | 0 | tor_free(fingerprint); |
5752 | 0 | return r; |
5753 | 0 | } |
5754 | | |
5755 | | /** Read the contents of a FallbackDir line from <b>line</b>. If |
5756 | | * <b>validate_only</b> is 0, and the line is well-formed, then add the |
5757 | | * dirserver described in the line as a fallback directory. Return 0 on |
5758 | | * success, or -1 if the line isn't well-formed or if we can't add it. */ |
5759 | | int |
5760 | | parse_dir_fallback_line(const char *line, |
5761 | | int validate_only) |
5762 | 0 | { |
5763 | 0 | int r = -1; |
5764 | 0 | smartlist_t *items = smartlist_new(), *positional = smartlist_new(); |
5765 | 0 | int orport = -1; |
5766 | 0 | uint16_t dirport; |
5767 | 0 | tor_addr_t addr; |
5768 | 0 | int ok; |
5769 | 0 | char id[DIGEST_LEN]; |
5770 | 0 | char *address=NULL; |
5771 | 0 | tor_addr_port_t ipv6_addrport, *ipv6_addrport_ptr = NULL; |
5772 | 0 | double weight=1.0; |
5773 | |
|
5774 | 0 | memset(id, 0, sizeof(id)); |
5775 | 0 | smartlist_split_string(items, line, NULL, |
5776 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); |
5777 | 0 | SMARTLIST_FOREACH_BEGIN(items, const char *, cp) { |
5778 | 0 | const char *eq = strchr(cp, '='); |
5779 | 0 | ok = 1; |
5780 | 0 | if (! eq) { |
5781 | 0 | smartlist_add(positional, (char*)cp); |
5782 | 0 | continue; |
5783 | 0 | } |
5784 | 0 | if (!strcmpstart(cp, "orport=")) { |
5785 | 0 | orport = (int)tor_parse_long(cp+strlen("orport="), 10, |
5786 | 0 | 1, 65535, &ok, NULL); |
5787 | 0 | } else if (!strcmpstart(cp, "id=")) { |
5788 | 0 | ok = base16_decode(id, DIGEST_LEN, cp+strlen("id="), |
5789 | 0 | strlen(cp)-strlen("id=")) == DIGEST_LEN; |
5790 | 0 | } else if (!strcasecmpstart(cp, "ipv6=")) { |
5791 | 0 | if (ipv6_addrport_ptr) { |
5792 | 0 | log_warn(LD_CONFIG, "Redundant ipv6 addr/port on FallbackDir line"); |
5793 | 0 | } else { |
5794 | 0 | if (tor_addr_port_parse(LOG_WARN, cp+strlen("ipv6="), |
5795 | 0 | &ipv6_addrport.addr, &ipv6_addrport.port, |
5796 | 0 | -1) < 0 |
5797 | 0 | || tor_addr_family(&ipv6_addrport.addr) != AF_INET6) { |
5798 | 0 | log_warn(LD_CONFIG, "Bad ipv6 addr/port %s on FallbackDir line", |
5799 | 0 | escaped(cp)); |
5800 | 0 | goto end; |
5801 | 0 | } |
5802 | 0 | ipv6_addrport_ptr = &ipv6_addrport; |
5803 | 0 | } |
5804 | 0 | } else if (!strcmpstart(cp, "weight=")) { |
5805 | 0 | int num_ok; |
5806 | 0 | const char *wstring = cp + strlen("weight="); |
5807 | 0 | weight = tor_parse_double(wstring, 0, (double)UINT64_MAX, &num_ok, NULL); |
5808 | 0 | if (!num_ok) { |
5809 | 0 | log_warn(LD_CONFIG, "Invalid weight '%s' on FallbackDir line.", cp); |
5810 | 0 | weight=1.0; |
5811 | 0 | } |
5812 | 0 | } |
5813 | | |
5814 | 0 | if (!ok) { |
5815 | 0 | log_warn(LD_CONFIG, "Bad FallbackDir option %s", escaped(cp)); |
5816 | 0 | goto end; |
5817 | 0 | } |
5818 | 0 | } SMARTLIST_FOREACH_END(cp); |
5819 | | |
5820 | 0 | if (smartlist_len(positional) != 1) { |
5821 | 0 | log_warn(LD_CONFIG, "Couldn't parse FallbackDir line %s", escaped(line)); |
5822 | 0 | goto end; |
5823 | 0 | } |
5824 | | |
5825 | 0 | if (tor_digest_is_zero(id)) { |
5826 | 0 | log_warn(LD_CONFIG, "Missing identity on FallbackDir line"); |
5827 | 0 | goto end; |
5828 | 0 | } |
5829 | | |
5830 | 0 | if (orport <= 0) { |
5831 | 0 | log_warn(LD_CONFIG, "Missing orport on FallbackDir line"); |
5832 | 0 | goto end; |
5833 | 0 | } |
5834 | | |
5835 | 0 | if (tor_addr_port_split(LOG_INFO, smartlist_get(positional, 0), |
5836 | 0 | &address, &dirport) < 0 || |
5837 | 0 | tor_addr_parse(&addr, address)<0) { |
5838 | 0 | log_warn(LD_CONFIG, "Couldn't parse address:port %s on FallbackDir line", |
5839 | 0 | (const char*)smartlist_get(positional, 0)); |
5840 | 0 | goto end; |
5841 | 0 | } |
5842 | | |
5843 | 0 | if (!validate_only) { |
5844 | 0 | dir_server_t *ds; |
5845 | 0 | ds = fallback_dir_server_new(&addr, dirport, orport, ipv6_addrport_ptr, |
5846 | 0 | id, weight); |
5847 | 0 | if (!ds) { |
5848 | 0 | log_warn(LD_CONFIG, "Couldn't create FallbackDir %s", escaped(line)); |
5849 | 0 | goto end; |
5850 | 0 | } |
5851 | 0 | dir_server_add(ds); |
5852 | 0 | } |
5853 | | |
5854 | 0 | r = 0; |
5855 | |
|
5856 | 0 | end: |
5857 | 0 | SMARTLIST_FOREACH(items, char *, cp, tor_free(cp)); |
5858 | 0 | smartlist_free(items); |
5859 | 0 | smartlist_free(positional); |
5860 | 0 | tor_free(address); |
5861 | 0 | return r; |
5862 | 0 | } |
5863 | | |
5864 | | /** Allocate and return a new port_cfg_t with reasonable defaults. |
5865 | | * |
5866 | | * <b>namelen</b> is the length of the unix socket name |
5867 | | * (typically the filesystem path), not including the trailing NUL. |
5868 | | * It should be 0 for ports that are not zunix sockets. */ |
5869 | | port_cfg_t * |
5870 | | port_cfg_new(size_t namelen) |
5871 | 0 | { |
5872 | 0 | tor_assert(namelen <= SIZE_T_CEILING - sizeof(port_cfg_t) - 1); |
5873 | 0 | port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t) + namelen + 1); |
5874 | | |
5875 | | /* entry_cfg flags */ |
5876 | 0 | cfg->entry_cfg.ipv4_traffic = 1; |
5877 | 0 | cfg->entry_cfg.ipv6_traffic = 1; |
5878 | 0 | cfg->entry_cfg.prefer_ipv6 = 0; |
5879 | 0 | cfg->entry_cfg.dns_request = 1; |
5880 | 0 | cfg->entry_cfg.onion_traffic = 1; |
5881 | 0 | cfg->entry_cfg.prefer_ipv6_virtaddr = 1; |
5882 | 0 | cfg->entry_cfg.session_group = SESSION_GROUP_UNSET; |
5883 | 0 | cfg->entry_cfg.isolation_flags = ISO_DEFAULT; |
5884 | | |
5885 | | /* Other flags default to 0 due to tor_malloc_zero */ |
5886 | 0 | return cfg; |
5887 | 0 | } |
5888 | | |
5889 | | /** Free all storage held in <b>port</b> */ |
5890 | | void |
5891 | | port_cfg_free_(port_cfg_t *port) |
5892 | 0 | { |
5893 | 0 | tor_free(port); |
5894 | 0 | } |
5895 | | |
5896 | | /** Warn for every port in <b>ports</b> of type <b>listener_type</b> that is |
5897 | | * on a publicly routable address. */ |
5898 | | static void |
5899 | | warn_nonlocal_client_ports(const smartlist_t *ports, |
5900 | | const char *portname, |
5901 | | const int listener_type) |
5902 | 0 | { |
5903 | 0 | SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) { |
5904 | 0 | if (port->type != listener_type) |
5905 | 0 | continue; |
5906 | 0 | if (port->is_unix_addr) { |
5907 | | /* Unix sockets aren't accessible over a network. */ |
5908 | 0 | } else if (!tor_addr_is_internal(&port->addr, 1)) { |
5909 | 0 | log_warn(LD_CONFIG, "You specified a public address '%s' for %sPort. " |
5910 | 0 | "Other people on the Internet might find your computer and " |
5911 | 0 | "use it as an open proxy. Please don't allow this unless you " |
5912 | 0 | "have a good reason.", |
5913 | 0 | fmt_addrport(&port->addr, port->port), portname); |
5914 | 0 | } else if (!tor_addr_is_loopback(&port->addr)) { |
5915 | 0 | log_notice(LD_CONFIG, "You configured a non-loopback address '%s' " |
5916 | 0 | "for %sPort. This allows everybody on your local network to " |
5917 | 0 | "use your machine as a proxy. Make sure this is what you " |
5918 | 0 | "wanted.", |
5919 | 0 | fmt_addrport(&port->addr, port->port), portname); |
5920 | 0 | } |
5921 | 0 | } SMARTLIST_FOREACH_END(port); |
5922 | 0 | } |
5923 | | |
5924 | | /** Given a list of port_cfg_t in <b>ports</b>, warn if any controller port |
5925 | | * there is listening on any non-loopback address. If <b>forbid_nonlocal</b> |
5926 | | * is true, then emit a stronger warning and remove the port from the list. |
5927 | | */ |
5928 | | static void |
5929 | | warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid_nonlocal) |
5930 | 0 | { |
5931 | 0 | int warned = 0; |
5932 | 0 | SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) { |
5933 | 0 | if (port->type != CONN_TYPE_CONTROL_LISTENER) |
5934 | 0 | continue; |
5935 | 0 | if (port->is_unix_addr) |
5936 | 0 | continue; |
5937 | 0 | if (!tor_addr_is_loopback(&port->addr)) { |
5938 | 0 | if (forbid_nonlocal) { |
5939 | 0 | if (!warned) |
5940 | 0 | log_warn(LD_CONFIG, |
5941 | 0 | "You have a ControlPort set to accept " |
5942 | 0 | "unauthenticated connections from a non-local address. " |
5943 | 0 | "This means that programs not running on your computer " |
5944 | 0 | "can reconfigure your Tor, without even having to guess a " |
5945 | 0 | "password. That's so bad that I'm closing your ControlPort " |
5946 | 0 | "for you. If you need to control your Tor remotely, try " |
5947 | 0 | "enabling authentication and using a tool like stunnel or " |
5948 | 0 | "ssh to encrypt remote access."); |
5949 | 0 | warned = 1; |
5950 | 0 | port_cfg_free(port); |
5951 | 0 | SMARTLIST_DEL_CURRENT(ports, port); |
5952 | 0 | } else { |
5953 | 0 | log_warn(LD_CONFIG, "You have a ControlPort set to accept " |
5954 | 0 | "connections from a non-local address. This means that " |
5955 | 0 | "programs not running on your computer can reconfigure your " |
5956 | 0 | "Tor. That's pretty bad, since the controller " |
5957 | 0 | "protocol isn't encrypted! Maybe you should just listen on " |
5958 | 0 | "127.0.0.1 and use a tool like stunnel or ssh to encrypt " |
5959 | 0 | "remote connections to your control port."); |
5960 | 0 | return; /* No point in checking the rest */ |
5961 | 0 | } |
5962 | 0 | } |
5963 | 0 | } SMARTLIST_FOREACH_END(port); |
5964 | 0 | } |
5965 | | |
5966 | | /** |
5967 | | * Take a string (<b>line</b>) that begins with either an address:port, a |
5968 | | * port, or an AF_UNIX address, optionally quoted, prefixed with |
5969 | | * "unix:". Parse that line, and on success, set <b>addrport_out</b> to a new |
5970 | | * string containing the beginning portion (without prefix). Iff there was a |
5971 | | * unix: prefix, set <b>is_unix_out</b> to true. On success, also set |
5972 | | * <b>rest_out</b> to point to the part of the line after the address portion. |
5973 | | * |
5974 | | * Return 0 on success, -1 on failure. |
5975 | | */ |
5976 | | int |
5977 | | port_cfg_line_extract_addrport(const char *line, |
5978 | | char **addrport_out, |
5979 | | int *is_unix_out, |
5980 | | const char **rest_out) |
5981 | 0 | { |
5982 | 0 | tor_assert(line); |
5983 | 0 | tor_assert(addrport_out); |
5984 | 0 | tor_assert(is_unix_out); |
5985 | 0 | tor_assert(rest_out); |
5986 | | |
5987 | 0 | line = eat_whitespace(line); |
5988 | |
|
5989 | 0 | if (!strcmpstart(line, unix_q_socket_prefix)) { |
5990 | | // It starts with unix:" |
5991 | 0 | size_t sz; |
5992 | 0 | *is_unix_out = 1; |
5993 | 0 | *addrport_out = NULL; |
5994 | 0 | line += strlen(unix_socket_prefix); /* No 'unix:', but keep the quote */ |
5995 | 0 | *rest_out = unescape_string(line, addrport_out, &sz); |
5996 | 0 | if (!*rest_out || (*addrport_out && sz != strlen(*addrport_out))) { |
5997 | 0 | tor_free(*addrport_out); |
5998 | 0 | return -1; |
5999 | 0 | } |
6000 | 0 | *rest_out = eat_whitespace(*rest_out); |
6001 | 0 | return 0; |
6002 | 0 | } else { |
6003 | | // Is there a unix: prefix? |
6004 | 0 | if (!strcmpstart(line, unix_socket_prefix)) { |
6005 | 0 | line += strlen(unix_socket_prefix); |
6006 | 0 | *is_unix_out = 1; |
6007 | 0 | } else { |
6008 | 0 | *is_unix_out = 0; |
6009 | 0 | } |
6010 | |
|
6011 | 0 | const char *end = find_whitespace(line); |
6012 | 0 | if (BUG(!end)) { |
6013 | 0 | end = strchr(line, '\0'); // LCOV_EXCL_LINE -- this can't be NULL |
6014 | 0 | } |
6015 | 0 | tor_assert(end && end >= line); |
6016 | 0 | *addrport_out = tor_strndup(line, end - line); |
6017 | 0 | *rest_out = eat_whitespace(end); |
6018 | 0 | return 0; |
6019 | 0 | } |
6020 | 0 | } |
6021 | | |
6022 | | static void |
6023 | | warn_client_dns_cache(const char *option, int disabling) |
6024 | 0 | { |
6025 | 0 | if (disabling) |
6026 | 0 | return; |
6027 | | |
6028 | 0 | warn_deprecated_option(option, |
6029 | 0 | "Client-side DNS caching enables a wide variety of route-" |
6030 | 0 | "capture attacks. If a single bad exit node lies to you about " |
6031 | 0 | "an IP address, caching that address would make you visit " |
6032 | 0 | "an address of the attacker's choice every time you connected " |
6033 | 0 | "to your destination."); |
6034 | 0 | } |
6035 | | |
6036 | | /** |
6037 | | * Parse port configuration for a single port type. |
6038 | | * |
6039 | | * Read entries of the "FooPort" type from the list <b>ports</b>. Syntax is |
6040 | | * that FooPort can have any number of entries of the format |
6041 | | * "[Address:][Port] IsolationOptions". |
6042 | | * |
6043 | | * In log messages, describe the port type as <b>portname</b>. |
6044 | | * |
6045 | | * If no address is specified, default to <b>defaultaddr</b>. If no |
6046 | | * FooPort is given, default to defaultport (if 0, there is no default). |
6047 | | * |
6048 | | * If CL_PORT_NO_STREAM_OPTIONS is set in <b>flags</b>, do not allow stream |
6049 | | * isolation options in the FooPort entries. |
6050 | | * |
6051 | | * If CL_PORT_WARN_NONLOCAL is set in <b>flags</b>, warn if any of the |
6052 | | * ports are not on a local address. If CL_PORT_FORBID_NONLOCAL is set, |
6053 | | * this is a control port with no password set: don't even allow it. |
6054 | | * |
6055 | | * If CL_PORT_SERVER_OPTIONS is set in <b>flags</b>, do not allow stream |
6056 | | * isolation options in the FooPort entries; instead allow the |
6057 | | * server-port option set. |
6058 | | * |
6059 | | * If CL_PORT_TAKES_HOSTNAMES is set in <b>flags</b>, allow the options |
6060 | | * {No,}IPv{4,6}Traffic. |
6061 | | * |
6062 | | * On success, if <b>out</b> is given, add a new port_cfg_t entry to |
6063 | | * <b>out</b> for every port that the client should listen on. Return 0 |
6064 | | * on success, -1 on failure. |
6065 | | */ |
6066 | | int |
6067 | | port_parse_config(smartlist_t *out, |
6068 | | const config_line_t *ports, |
6069 | | const char *portname, |
6070 | | int listener_type, |
6071 | | const char *defaultaddr, |
6072 | | int defaultport, |
6073 | | const unsigned flags) |
6074 | 0 | { |
6075 | 0 | smartlist_t *elts; |
6076 | 0 | int retval = -1; |
6077 | 0 | const unsigned is_control = (listener_type == CONN_TYPE_CONTROL_LISTENER); |
6078 | 0 | const unsigned is_ext_orport = (listener_type == CONN_TYPE_EXT_OR_LISTENER); |
6079 | 0 | const unsigned allow_no_stream_options = flags & CL_PORT_NO_STREAM_OPTIONS; |
6080 | 0 | const unsigned use_server_options = flags & CL_PORT_SERVER_OPTIONS; |
6081 | 0 | const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL; |
6082 | 0 | const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL; |
6083 | 0 | const unsigned default_to_group_writable = |
6084 | 0 | flags & CL_PORT_DFLT_GROUP_WRITABLE; |
6085 | 0 | const unsigned takes_hostnames = flags & CL_PORT_TAKES_HOSTNAMES; |
6086 | 0 | const unsigned is_unix_socket = flags & CL_PORT_IS_UNIXSOCKET; |
6087 | 0 | int got_zero_port=0, got_nonzero_port=0; |
6088 | 0 | char *unix_socket_path = NULL; |
6089 | 0 | port_cfg_t *cfg = NULL; |
6090 | 0 | bool addr_is_explicit = false; |
6091 | 0 | tor_addr_t default_addr = TOR_ADDR_NULL; |
6092 | | |
6093 | | /* Parse default address. This can fail for Unix socket so the default_addr |
6094 | | * will simply be made UNSPEC. */ |
6095 | 0 | if (defaultaddr) { |
6096 | 0 | tor_addr_parse(&default_addr, defaultaddr); |
6097 | 0 | } |
6098 | | |
6099 | | /* If there's no FooPort, then maybe make a default one. */ |
6100 | 0 | if (! ports) { |
6101 | 0 | if (defaultport && defaultaddr && out) { |
6102 | 0 | cfg = port_cfg_new(is_unix_socket ? strlen(defaultaddr) : 0); |
6103 | 0 | cfg->type = listener_type; |
6104 | 0 | if (is_unix_socket) { |
6105 | 0 | tor_addr_make_unspec(&cfg->addr); |
6106 | 0 | memcpy(cfg->unix_addr, defaultaddr, strlen(defaultaddr) + 1); |
6107 | 0 | cfg->is_unix_addr = 1; |
6108 | 0 | } else { |
6109 | 0 | cfg->port = defaultport; |
6110 | 0 | tor_addr_parse(&cfg->addr, defaultaddr); |
6111 | 0 | } |
6112 | 0 | smartlist_add(out, cfg); |
6113 | 0 | } |
6114 | 0 | return 0; |
6115 | 0 | } |
6116 | | |
6117 | | /* At last we can actually parse the FooPort lines. The syntax is: |
6118 | | * [Addr:](Port|auto) [Options].*/ |
6119 | 0 | elts = smartlist_new(); |
6120 | 0 | char *addrport = NULL; |
6121 | |
|
6122 | 0 | for (; ports; ports = ports->next) { |
6123 | 0 | tor_addr_t addr; |
6124 | 0 | tor_addr_make_unspec(&addr); |
6125 | 0 | int port, ok, |
6126 | 0 | has_used_unix_socket_only_option = 0, |
6127 | 0 | is_unix_tagged_addr = 0; |
6128 | 0 | uint16_t ptmp=0; |
6129 | 0 | const char *rest_of_line = NULL; |
6130 | |
|
6131 | 0 | if (port_cfg_line_extract_addrport(ports->value, |
6132 | 0 | &addrport, &is_unix_tagged_addr, &rest_of_line)<0) { |
6133 | 0 | log_warn(LD_CONFIG, "Invalid %sPort line with unparsable address", |
6134 | 0 | portname); |
6135 | 0 | goto err; |
6136 | 0 | } |
6137 | 0 | if (strlen(addrport) == 0) { |
6138 | 0 | log_warn(LD_CONFIG, "Invalid %sPort line with no address", portname); |
6139 | 0 | goto err; |
6140 | 0 | } |
6141 | | |
6142 | | /* Split the remainder... */ |
6143 | 0 | smartlist_split_string(elts, rest_of_line, NULL, |
6144 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); |
6145 | | |
6146 | | /* Let's start to check if it's a Unix socket path. */ |
6147 | 0 | if (is_unix_tagged_addr) { |
6148 | | #ifndef HAVE_SYS_UN_H |
6149 | | log_warn(LD_CONFIG, "Unix sockets not supported on this system."); |
6150 | | goto err; |
6151 | | #endif |
6152 | 0 | unix_socket_path = addrport; |
6153 | 0 | addrport = NULL; |
6154 | 0 | } |
6155 | |
|
6156 | 0 | if (unix_socket_path && |
6157 | 0 | ! conn_listener_type_supports_af_unix(listener_type)) { |
6158 | 0 | log_warn(LD_CONFIG, "%sPort does not support unix sockets", portname); |
6159 | 0 | goto err; |
6160 | 0 | } |
6161 | | |
6162 | 0 | if (unix_socket_path) { |
6163 | 0 | port = 1; |
6164 | 0 | } else if (is_unix_socket) { |
6165 | 0 | if (BUG(!addrport)) |
6166 | 0 | goto err; // LCOV_EXCL_LINE unreachable, but coverity can't tell that |
6167 | 0 | unix_socket_path = tor_strdup(addrport); |
6168 | 0 | if (!strcmp(addrport, "0")) |
6169 | 0 | port = 0; |
6170 | 0 | else |
6171 | 0 | port = 1; |
6172 | 0 | } else if (!strcasecmp(addrport, "auto")) { |
6173 | 0 | port = CFG_AUTO_PORT; |
6174 | 0 | tor_addr_copy(&addr, &default_addr); |
6175 | 0 | } else if (!strcasecmpend(addrport, ":auto")) { |
6176 | 0 | char *addrtmp = tor_strndup(addrport, strlen(addrport)-5); |
6177 | 0 | port = CFG_AUTO_PORT; |
6178 | 0 | if (tor_addr_port_lookup(addrtmp, &addr, &ptmp)<0 || ptmp) { |
6179 | 0 | log_warn(LD_CONFIG, "Invalid address '%s' for %sPort", |
6180 | 0 | escaped(addrport), portname); |
6181 | 0 | tor_free(addrtmp); |
6182 | 0 | goto err; |
6183 | 0 | } |
6184 | 0 | tor_free(addrtmp); |
6185 | 0 | } else { |
6186 | | /* Try parsing integer port before address, because, who knows? |
6187 | | * "9050" might be a valid address. */ |
6188 | 0 | port = (int) tor_parse_long(addrport, 10, 0, 65535, &ok, NULL); |
6189 | 0 | if (ok) { |
6190 | 0 | tor_addr_copy(&addr, &default_addr); |
6191 | 0 | addr_is_explicit = false; |
6192 | 0 | } else if (tor_addr_port_lookup(addrport, &addr, &ptmp) == 0) { |
6193 | 0 | if (ptmp == 0) { |
6194 | 0 | log_warn(LD_CONFIG, "%sPort line has address but no port", portname); |
6195 | 0 | goto err; |
6196 | 0 | } |
6197 | 0 | port = ptmp; |
6198 | 0 | addr_is_explicit = true; |
6199 | 0 | } else { |
6200 | 0 | log_warn(LD_CONFIG, "Couldn't parse address %s for %sPort", |
6201 | 0 | escaped(addrport), portname); |
6202 | 0 | goto err; |
6203 | 0 | } |
6204 | 0 | } |
6205 | | |
6206 | | /* Default port_cfg_t object initialization */ |
6207 | 0 | cfg = port_cfg_new(unix_socket_path ? strlen(unix_socket_path) : 0); |
6208 | |
|
6209 | 0 | cfg->explicit_addr = addr_is_explicit; |
6210 | 0 | if (unix_socket_path && default_to_group_writable) |
6211 | 0 | cfg->is_group_writable = 1; |
6212 | | |
6213 | | /* Now parse the rest of the options, if any. */ |
6214 | 0 | if (use_server_options) { |
6215 | | /* This is a server port; parse advertising options */ |
6216 | 0 | SMARTLIST_FOREACH_BEGIN(elts, char *, elt) { |
6217 | 0 | if (!strcasecmp(elt, "NoAdvertise")) { |
6218 | 0 | cfg->server_cfg.no_advertise = 1; |
6219 | 0 | } else if (!strcasecmp(elt, "NoListen")) { |
6220 | 0 | cfg->server_cfg.no_listen = 1; |
6221 | | #if 0 |
6222 | | /* not implemented yet. */ |
6223 | | } else if (!strcasecmp(elt, "AllAddrs")) { |
6224 | | |
6225 | | all_addrs = 1; |
6226 | | #endif /* 0 */ |
6227 | 0 | } else if (!strcasecmp(elt, "IPv4Only")) { |
6228 | 0 | cfg->server_cfg.bind_ipv4_only = 1; |
6229 | 0 | } else if (!strcasecmp(elt, "IPv6Only")) { |
6230 | 0 | cfg->server_cfg.bind_ipv6_only = 1; |
6231 | 0 | } else { |
6232 | 0 | log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'", |
6233 | 0 | portname, escaped(elt)); |
6234 | 0 | } |
6235 | 0 | } SMARTLIST_FOREACH_END(elt); |
6236 | |
|
6237 | 0 | if (cfg->server_cfg.no_advertise && cfg->server_cfg.no_listen) { |
6238 | 0 | log_warn(LD_CONFIG, "Tried to set both NoListen and NoAdvertise " |
6239 | 0 | "on %sPort line '%s'", |
6240 | 0 | portname, escaped(ports->value)); |
6241 | 0 | goto err; |
6242 | 0 | } |
6243 | 0 | if (cfg->server_cfg.bind_ipv4_only && |
6244 | 0 | cfg->server_cfg.bind_ipv6_only) { |
6245 | 0 | log_warn(LD_CONFIG, "Tried to set both IPv4Only and IPv6Only " |
6246 | 0 | "on %sPort line '%s'", |
6247 | 0 | portname, escaped(ports->value)); |
6248 | 0 | goto err; |
6249 | 0 | } |
6250 | 0 | if (cfg->server_cfg.bind_ipv4_only && |
6251 | 0 | tor_addr_family(&addr) != AF_INET) { |
6252 | 0 | if (cfg->explicit_addr) { |
6253 | 0 | log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4", |
6254 | 0 | portname); |
6255 | 0 | goto err; |
6256 | 0 | } |
6257 | | /* This ORPort is IPv4Only but the default address is IPv6, ignore it |
6258 | | * since this will be configured with an IPv4 default address. */ |
6259 | 0 | goto ignore; |
6260 | 0 | } |
6261 | 0 | if (cfg->server_cfg.bind_ipv6_only && |
6262 | 0 | tor_addr_family(&addr) != AF_INET6) { |
6263 | 0 | if (cfg->explicit_addr) { |
6264 | 0 | log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6", |
6265 | 0 | portname); |
6266 | 0 | goto err; |
6267 | 0 | } |
6268 | | /* This ORPort is IPv6Only but the default address is IPv4, ignore it |
6269 | | * since this will be configured with an IPv6 default address. */ |
6270 | 0 | goto ignore; |
6271 | 0 | } |
6272 | 0 | } else { |
6273 | | /* This is a client port; parse isolation options */ |
6274 | 0 | SMARTLIST_FOREACH_BEGIN(elts, char *, elt) { |
6275 | 0 | int no = 0, isoflag = 0; |
6276 | 0 | const char *elt_orig = elt; |
6277 | |
|
6278 | 0 | if (!strcasecmpstart(elt, "SessionGroup=")) { |
6279 | 0 | int group = (int)tor_parse_long(elt+strlen("SessionGroup="), |
6280 | 0 | 10, 0, INT_MAX, &ok, NULL); |
6281 | 0 | if (!ok || allow_no_stream_options) { |
6282 | 0 | log_warn(LD_CONFIG, "Invalid %sPort option '%s'", |
6283 | 0 | portname, escaped(elt)); |
6284 | 0 | goto err; |
6285 | 0 | } |
6286 | 0 | if (cfg->entry_cfg.session_group >= 0) { |
6287 | 0 | log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort", |
6288 | 0 | portname); |
6289 | 0 | goto err; |
6290 | 0 | } |
6291 | 0 | cfg->entry_cfg.session_group = group; |
6292 | 0 | continue; |
6293 | 0 | } |
6294 | | |
6295 | 0 | if (!strcasecmpstart(elt, "No")) { |
6296 | 0 | no = 1; |
6297 | 0 | elt += 2; |
6298 | 0 | } |
6299 | |
|
6300 | 0 | if (!strcasecmp(elt, "GroupWritable")) { |
6301 | 0 | cfg->is_group_writable = !no; |
6302 | 0 | has_used_unix_socket_only_option = 1; |
6303 | 0 | continue; |
6304 | 0 | } else if (!strcasecmp(elt, "WorldWritable")) { |
6305 | 0 | cfg->is_world_writable = !no; |
6306 | 0 | has_used_unix_socket_only_option = 1; |
6307 | 0 | continue; |
6308 | 0 | } else if (!strcasecmp(elt, "RelaxDirModeCheck")) { |
6309 | 0 | cfg->relax_dirmode_check = !no; |
6310 | 0 | has_used_unix_socket_only_option = 1; |
6311 | 0 | continue; |
6312 | 0 | } |
6313 | | |
6314 | 0 | if (allow_no_stream_options) { |
6315 | 0 | log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'", |
6316 | 0 | portname, escaped(elt)); |
6317 | 0 | continue; |
6318 | 0 | } |
6319 | | |
6320 | 0 | if (takes_hostnames) { |
6321 | 0 | if (!strcasecmp(elt, "IPv4Traffic")) { |
6322 | 0 | cfg->entry_cfg.ipv4_traffic = ! no; |
6323 | 0 | continue; |
6324 | 0 | } else if (!strcasecmp(elt, "IPv6Traffic")) { |
6325 | 0 | cfg->entry_cfg.ipv6_traffic = ! no; |
6326 | 0 | continue; |
6327 | 0 | } else if (!strcasecmp(elt, "PreferIPv6")) { |
6328 | 0 | cfg->entry_cfg.prefer_ipv6 = ! no; |
6329 | 0 | continue; |
6330 | 0 | } else if (!strcasecmp(elt, "DNSRequest")) { |
6331 | 0 | cfg->entry_cfg.dns_request = ! no; |
6332 | 0 | continue; |
6333 | 0 | } else if (!strcasecmp(elt, "OnionTraffic")) { |
6334 | 0 | cfg->entry_cfg.onion_traffic = ! no; |
6335 | 0 | continue; |
6336 | 0 | } else if (!strcasecmp(elt, "OnionTrafficOnly")) { |
6337 | | /* Only connect to .onion addresses. Equivalent to |
6338 | | * NoDNSRequest, NoIPv4Traffic, NoIPv6Traffic. The option |
6339 | | * NoOnionTrafficOnly is not supported, it's too confusing. */ |
6340 | 0 | if (no) { |
6341 | 0 | log_warn(LD_CONFIG, "Unsupported %sPort option 'No%s'. Use " |
6342 | 0 | "DNSRequest, IPv4Traffic, and/or IPv6Traffic instead.", |
6343 | 0 | portname, escaped(elt)); |
6344 | 0 | } else { |
6345 | 0 | cfg->entry_cfg.ipv4_traffic = 0; |
6346 | 0 | cfg->entry_cfg.ipv6_traffic = 0; |
6347 | 0 | cfg->entry_cfg.dns_request = 0; |
6348 | 0 | } |
6349 | 0 | continue; |
6350 | 0 | } |
6351 | 0 | } |
6352 | 0 | if (!strcasecmp(elt, "CacheIPv4DNS")) { |
6353 | 0 | warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha |
6354 | 0 | cfg->entry_cfg.cache_ipv4_answers = ! no; |
6355 | 0 | continue; |
6356 | 0 | } else if (!strcasecmp(elt, "CacheIPv6DNS")) { |
6357 | 0 | warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha |
6358 | 0 | cfg->entry_cfg.cache_ipv6_answers = ! no; |
6359 | 0 | continue; |
6360 | 0 | } else if (!strcasecmp(elt, "CacheDNS")) { |
6361 | 0 | warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha |
6362 | 0 | cfg->entry_cfg.cache_ipv4_answers = ! no; |
6363 | 0 | cfg->entry_cfg.cache_ipv6_answers = ! no; |
6364 | 0 | continue; |
6365 | 0 | } else if (!strcasecmp(elt, "UseIPv4Cache")) { |
6366 | 0 | warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha |
6367 | 0 | cfg->entry_cfg.use_cached_ipv4_answers = ! no; |
6368 | 0 | continue; |
6369 | 0 | } else if (!strcasecmp(elt, "UseIPv6Cache")) { |
6370 | 0 | warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha |
6371 | 0 | cfg->entry_cfg.use_cached_ipv6_answers = ! no; |
6372 | 0 | continue; |
6373 | 0 | } else if (!strcasecmp(elt, "UseDNSCache")) { |
6374 | 0 | warn_client_dns_cache(elt, no); // since 0.2.9.2-alpha |
6375 | 0 | cfg->entry_cfg.use_cached_ipv4_answers = ! no; |
6376 | 0 | cfg->entry_cfg.use_cached_ipv6_answers = ! no; |
6377 | 0 | continue; |
6378 | 0 | } else if (!strcasecmp(elt, "PreferIPv6Automap")) { |
6379 | 0 | cfg->entry_cfg.prefer_ipv6_virtaddr = ! no; |
6380 | 0 | continue; |
6381 | 0 | } else if (!strcasecmp(elt, "PreferSOCKSNoAuth")) { |
6382 | 0 | cfg->entry_cfg.socks_prefer_no_auth = ! no; |
6383 | 0 | continue; |
6384 | 0 | } else if (!strcasecmp(elt, "KeepAliveIsolateSOCKSAuth")) { |
6385 | 0 | cfg->entry_cfg.socks_iso_keep_alive = ! no; |
6386 | 0 | continue; |
6387 | 0 | } else if (!strcasecmp(elt, "ExtendedErrors")) { |
6388 | 0 | cfg->entry_cfg.extended_socks5_codes = ! no; |
6389 | 0 | continue; |
6390 | 0 | } |
6391 | | |
6392 | 0 | if (!strcasecmpend(elt, "s")) |
6393 | 0 | elt[strlen(elt)-1] = '\0'; /* kill plurals. */ |
6394 | |
|
6395 | 0 | if (!strcasecmp(elt, "IsolateDestPort")) { |
6396 | 0 | isoflag = ISO_DESTPORT; |
6397 | 0 | } else if (!strcasecmp(elt, "IsolateDestAddr")) { |
6398 | 0 | isoflag = ISO_DESTADDR; |
6399 | 0 | } else if (!strcasecmp(elt, "IsolateSOCKSAuth")) { |
6400 | 0 | isoflag = ISO_SOCKSAUTH; |
6401 | 0 | } else if (!strcasecmp(elt, "IsolateClientProtocol")) { |
6402 | 0 | isoflag = ISO_CLIENTPROTO; |
6403 | 0 | } else if (!strcasecmp(elt, "IsolateClientAddr")) { |
6404 | 0 | isoflag = ISO_CLIENTADDR; |
6405 | 0 | } else { |
6406 | 0 | log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'", |
6407 | 0 | portname, escaped(elt_orig)); |
6408 | 0 | } |
6409 | |
|
6410 | 0 | if (no) { |
6411 | 0 | cfg->entry_cfg.isolation_flags &= ~isoflag; |
6412 | 0 | } else { |
6413 | 0 | cfg->entry_cfg.isolation_flags |= isoflag; |
6414 | 0 | } |
6415 | 0 | } SMARTLIST_FOREACH_END(elt); |
6416 | 0 | } |
6417 | | |
6418 | 0 | if (port) |
6419 | 0 | got_nonzero_port = 1; |
6420 | 0 | else |
6421 | 0 | got_zero_port = 1; |
6422 | |
|
6423 | 0 | if (cfg->entry_cfg.dns_request == 0 && |
6424 | 0 | listener_type == CONN_TYPE_AP_DNS_LISTENER) { |
6425 | 0 | log_warn(LD_CONFIG, "You have a %sPort entry with DNS disabled; that " |
6426 | 0 | "won't work.", portname); |
6427 | 0 | goto err; |
6428 | 0 | } |
6429 | 0 | if (cfg->entry_cfg.ipv4_traffic == 0 && |
6430 | 0 | cfg->entry_cfg.ipv6_traffic == 0 && |
6431 | 0 | cfg->entry_cfg.onion_traffic == 0 && |
6432 | 0 | listener_type != CONN_TYPE_AP_DNS_LISTENER) { |
6433 | 0 | log_warn(LD_CONFIG, "You have a %sPort entry with all of IPv4 and " |
6434 | 0 | "IPv6 and .onion disabled; that won't work.", portname); |
6435 | 0 | goto err; |
6436 | 0 | } |
6437 | 0 | if (cfg->entry_cfg.dns_request == 1 && |
6438 | 0 | cfg->entry_cfg.ipv4_traffic == 0 && |
6439 | 0 | cfg->entry_cfg.ipv6_traffic == 0 && |
6440 | 0 | listener_type != CONN_TYPE_AP_DNS_LISTENER) { |
6441 | 0 | log_warn(LD_CONFIG, "You have a %sPort entry with DNSRequest enabled, " |
6442 | 0 | "but IPv4 and IPv6 disabled; DNS-based sites won't work.", |
6443 | 0 | portname); |
6444 | 0 | goto err; |
6445 | 0 | } |
6446 | 0 | if (has_used_unix_socket_only_option && !unix_socket_path) { |
6447 | 0 | log_warn(LD_CONFIG, "You have a %sPort entry with GroupWritable, " |
6448 | 0 | "WorldWritable, or RelaxDirModeCheck, but it is not a " |
6449 | 0 | "unix socket.", portname); |
6450 | 0 | goto err; |
6451 | 0 | } |
6452 | 0 | if (!(cfg->entry_cfg.isolation_flags & ISO_SOCKSAUTH) && |
6453 | 0 | cfg->entry_cfg.socks_iso_keep_alive) { |
6454 | 0 | log_warn(LD_CONFIG, "You have a %sPort entry with both " |
6455 | 0 | "NoIsolateSOCKSAuth and KeepAliveIsolateSOCKSAuth set.", |
6456 | 0 | portname); |
6457 | 0 | goto err; |
6458 | 0 | } |
6459 | 0 | if (unix_socket_path && |
6460 | 0 | (cfg->entry_cfg.isolation_flags & ISO_CLIENTADDR)) { |
6461 | | /* `IsolateClientAddr` is nonsensical in the context of AF_LOCAL. |
6462 | | * just silently remove the isolation flag. |
6463 | | */ |
6464 | 0 | cfg->entry_cfg.isolation_flags &= ~ISO_CLIENTADDR; |
6465 | 0 | } |
6466 | 0 | if (out && port) { |
6467 | 0 | size_t namelen = unix_socket_path ? strlen(unix_socket_path) : 0; |
6468 | 0 | if (unix_socket_path) { |
6469 | 0 | tor_addr_make_unspec(&cfg->addr); |
6470 | 0 | memcpy(cfg->unix_addr, unix_socket_path, namelen + 1); |
6471 | 0 | cfg->is_unix_addr = 1; |
6472 | 0 | tor_free(unix_socket_path); |
6473 | 0 | } else { |
6474 | 0 | tor_addr_copy(&cfg->addr, &addr); |
6475 | 0 | cfg->port = port; |
6476 | 0 | } |
6477 | 0 | cfg->type = listener_type; |
6478 | 0 | if (! (cfg->entry_cfg.isolation_flags & ISO_SOCKSAUTH)) |
6479 | 0 | cfg->entry_cfg.socks_prefer_no_auth = 1; |
6480 | 0 | smartlist_add(out, cfg); |
6481 | | /* out owns cfg now, don't re-use or free it */ |
6482 | 0 | cfg = NULL; |
6483 | 0 | } |
6484 | |
|
6485 | 0 | ignore: |
6486 | 0 | tor_free(cfg); |
6487 | 0 | SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); |
6488 | 0 | smartlist_clear(elts); |
6489 | 0 | tor_free(addrport); |
6490 | 0 | tor_free(unix_socket_path); |
6491 | 0 | } |
6492 | | |
6493 | 0 | if (warn_nonlocal && out) { |
6494 | 0 | if (is_control) |
6495 | 0 | warn_nonlocal_controller_ports(out, forbid_nonlocal); |
6496 | 0 | else if (is_ext_orport) |
6497 | 0 | port_warn_nonlocal_ext_orports(out, portname); |
6498 | 0 | else |
6499 | 0 | warn_nonlocal_client_ports(out, portname, listener_type); |
6500 | 0 | } |
6501 | |
|
6502 | 0 | if (got_zero_port && got_nonzero_port) { |
6503 | 0 | log_warn(LD_CONFIG, "You specified a nonzero %sPort along with '%sPort 0' " |
6504 | 0 | "in the same configuration. Did you mean to disable %sPort or " |
6505 | 0 | "not?", portname, portname, portname); |
6506 | 0 | goto err; |
6507 | 0 | } |
6508 | | |
6509 | 0 | retval = 0; |
6510 | 0 | err: |
6511 | | /* There are two ways we can error out: |
6512 | | * 1. part way through the loop: cfg needs to be freed; |
6513 | | * 2. ending the loop normally: cfg is always NULL. |
6514 | | * In this case, cfg has either been: |
6515 | | * - added to out, then set to NULL, or |
6516 | | * - freed and set to NULL (because out is NULL, or port is 0). |
6517 | | */ |
6518 | 0 | tor_free(cfg); |
6519 | | |
6520 | | /* Free the other variables from the loop. |
6521 | | * elts is always non-NULL here, but it may or may not be empty. */ |
6522 | 0 | SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); |
6523 | 0 | smartlist_free(elts); |
6524 | 0 | tor_free(unix_socket_path); |
6525 | 0 | tor_free(addrport); |
6526 | |
|
6527 | 0 | return retval; |
6528 | 0 | } |
6529 | | |
6530 | | /** Return the number of ports which are actually going to listen with type |
6531 | | * <b>listenertype</b>. Do not count no_listen ports. Only count unix |
6532 | | * sockets if count_sockets is true. */ |
6533 | | int |
6534 | | port_count_real_listeners(const smartlist_t *ports, int listenertype, |
6535 | | int count_sockets) |
6536 | 0 | { |
6537 | 0 | int n = 0; |
6538 | 0 | SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) { |
6539 | 0 | if (port->server_cfg.no_listen) |
6540 | 0 | continue; |
6541 | 0 | if (!count_sockets && port->is_unix_addr) |
6542 | 0 | continue; |
6543 | 0 | if (port->type != listenertype) |
6544 | 0 | continue; |
6545 | 0 | ++n; |
6546 | 0 | } SMARTLIST_FOREACH_END(port); |
6547 | 0 | return n; |
6548 | 0 | } |
6549 | | |
6550 | | /** Parse all ports from <b>options</b>. On success, set *<b>n_ports_out</b> |
6551 | | * to the number of ports that are listed, update the *Port_set values in |
6552 | | * <b>options</b>, and return 0. On failure, set *<b>msg</b> to a |
6553 | | * description of the problem and return -1. |
6554 | | * |
6555 | | * If <b>validate_only</b> is false, set configured_client_ports to the |
6556 | | * new list of ports parsed from <b>options</b>. |
6557 | | **/ |
6558 | | STATIC int |
6559 | | parse_ports(or_options_t *options, int validate_only, |
6560 | | char **msg, int *n_ports_out, |
6561 | | int *world_writable_control_socket) |
6562 | 0 | { |
6563 | 0 | smartlist_t *ports; |
6564 | 0 | int retval = -1; |
6565 | |
|
6566 | 0 | ports = smartlist_new(); |
6567 | |
|
6568 | 0 | *n_ports_out = 0; |
6569 | |
|
6570 | 0 | const unsigned gw_flag = options->UnixSocksGroupWritable ? |
6571 | 0 | CL_PORT_DFLT_GROUP_WRITABLE : 0; |
6572 | 0 | if (port_parse_config(ports, |
6573 | 0 | options->SocksPort_lines, |
6574 | 0 | "Socks", CONN_TYPE_AP_LISTENER, |
6575 | 0 | "127.0.0.1", 9050, |
6576 | 0 | ((validate_only ? 0 : CL_PORT_WARN_NONLOCAL) |
6577 | 0 | | CL_PORT_TAKES_HOSTNAMES | gw_flag)) < 0) { |
6578 | 0 | *msg = tor_strdup("Invalid SocksPort configuration"); |
6579 | 0 | goto err; |
6580 | 0 | } |
6581 | 0 | if (port_parse_config(ports, |
6582 | 0 | options->DNSPort_lines, |
6583 | 0 | "DNS", CONN_TYPE_AP_DNS_LISTENER, |
6584 | 0 | "127.0.0.1", 0, |
6585 | 0 | CL_PORT_WARN_NONLOCAL|CL_PORT_TAKES_HOSTNAMES) < 0) { |
6586 | 0 | *msg = tor_strdup("Invalid DNSPort configuration"); |
6587 | 0 | goto err; |
6588 | 0 | } |
6589 | 0 | if (port_parse_config(ports, |
6590 | 0 | options->TransPort_lines, |
6591 | 0 | "Trans", CONN_TYPE_AP_TRANS_LISTENER, |
6592 | 0 | "127.0.0.1", 0, |
6593 | 0 | CL_PORT_WARN_NONLOCAL) < 0) { |
6594 | 0 | *msg = tor_strdup("Invalid TransPort configuration"); |
6595 | 0 | goto err; |
6596 | 0 | } |
6597 | 0 | if (port_parse_config(ports, |
6598 | 0 | options->NATDPort_lines, |
6599 | 0 | "NATD", CONN_TYPE_AP_NATD_LISTENER, |
6600 | 0 | "127.0.0.1", 0, |
6601 | 0 | CL_PORT_WARN_NONLOCAL) < 0) { |
6602 | 0 | *msg = tor_strdup("Invalid NatdPort configuration"); |
6603 | 0 | goto err; |
6604 | 0 | } |
6605 | 0 | if (port_parse_config(ports, |
6606 | 0 | options->HTTPTunnelPort_lines, |
6607 | 0 | "HTTP Tunnel", CONN_TYPE_AP_HTTP_CONNECT_LISTENER, |
6608 | 0 | "127.0.0.1", 0, |
6609 | 0 | ((validate_only ? 0 : CL_PORT_WARN_NONLOCAL) |
6610 | 0 | | CL_PORT_TAKES_HOSTNAMES | gw_flag)) < 0) { |
6611 | 0 | *msg = tor_strdup("Invalid HTTPTunnelPort configuration"); |
6612 | 0 | goto err; |
6613 | 0 | } |
6614 | 0 | if (metrics_parse_ports(options, ports, msg) < 0) { |
6615 | 0 | goto err; |
6616 | 0 | } |
6617 | | |
6618 | 0 | { |
6619 | 0 | unsigned control_port_flags = CL_PORT_NO_STREAM_OPTIONS | |
6620 | 0 | CL_PORT_WARN_NONLOCAL; |
6621 | 0 | const int any_passwords = (options->HashedControlPassword || |
6622 | 0 | options->HashedControlSessionPassword || |
6623 | 0 | options->CookieAuthentication); |
6624 | 0 | if (! any_passwords) |
6625 | 0 | control_port_flags |= CL_PORT_FORBID_NONLOCAL; |
6626 | 0 | if (options->ControlSocketsGroupWritable) |
6627 | 0 | control_port_flags |= CL_PORT_DFLT_GROUP_WRITABLE; |
6628 | |
|
6629 | 0 | if (port_parse_config(ports, |
6630 | 0 | options->ControlPort_lines, |
6631 | 0 | "Control", CONN_TYPE_CONTROL_LISTENER, |
6632 | 0 | "127.0.0.1", 0, |
6633 | 0 | control_port_flags) < 0) { |
6634 | 0 | *msg = tor_strdup("Invalid ControlPort configuration"); |
6635 | 0 | goto err; |
6636 | 0 | } |
6637 | | |
6638 | 0 | if (port_parse_config(ports, options->ControlSocket, |
6639 | 0 | "ControlSocket", |
6640 | 0 | CONN_TYPE_CONTROL_LISTENER, NULL, 0, |
6641 | 0 | control_port_flags | CL_PORT_IS_UNIXSOCKET) < 0) { |
6642 | 0 | *msg = tor_strdup("Invalid ControlSocket configuration"); |
6643 | 0 | goto err; |
6644 | 0 | } |
6645 | 0 | } |
6646 | | |
6647 | 0 | if (port_parse_ports_relay(options, msg, ports, &have_low_ports) < 0) |
6648 | 0 | goto err; |
6649 | | |
6650 | 0 | *n_ports_out = smartlist_len(ports); |
6651 | |
|
6652 | 0 | retval = 0; |
6653 | | |
6654 | | /* Update the *Port_set options. The !! here is to force a boolean out of |
6655 | | an integer. */ |
6656 | 0 | port_update_port_set_relay(options, ports); |
6657 | 0 | options->SocksPort_set = |
6658 | 0 | !! port_count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1); |
6659 | 0 | options->TransPort_set = |
6660 | 0 | !! port_count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1); |
6661 | 0 | options->NATDPort_set = |
6662 | 0 | !! port_count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1); |
6663 | 0 | options->HTTPTunnelPort_set = |
6664 | 0 | !! port_count_real_listeners(ports, CONN_TYPE_AP_HTTP_CONNECT_LISTENER, 1); |
6665 | | /* Use options->ControlSocket to test if a control socket is set */ |
6666 | 0 | options->ControlPort_set = |
6667 | 0 | !! port_count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0); |
6668 | 0 | options->DNSPort_set = |
6669 | 0 | !! port_count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER, 1); |
6670 | |
|
6671 | 0 | if (world_writable_control_socket) { |
6672 | 0 | SMARTLIST_FOREACH(ports, port_cfg_t *, p, |
6673 | 0 | if (p->type == CONN_TYPE_CONTROL_LISTENER && |
6674 | 0 | p->is_unix_addr && |
6675 | 0 | p->is_world_writable) { |
6676 | 0 | *world_writable_control_socket = 1; |
6677 | 0 | break; |
6678 | 0 | }); |
6679 | 0 | } |
6680 | |
|
6681 | 0 | if (!validate_only) { |
6682 | 0 | if (configured_ports) { |
6683 | 0 | SMARTLIST_FOREACH(configured_ports, |
6684 | 0 | port_cfg_t *, p, port_cfg_free(p)); |
6685 | 0 | smartlist_free(configured_ports); |
6686 | 0 | } |
6687 | 0 | configured_ports = ports; |
6688 | 0 | ports = NULL; /* prevent free below. */ |
6689 | 0 | } |
6690 | |
|
6691 | 0 | err: |
6692 | 0 | if (ports) { |
6693 | 0 | SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p)); |
6694 | 0 | smartlist_free(ports); |
6695 | 0 | } |
6696 | 0 | return retval; |
6697 | 0 | } |
6698 | | |
6699 | | /* Does port bind to IPv4? */ |
6700 | | int |
6701 | | port_binds_ipv4(const port_cfg_t *port) |
6702 | 0 | { |
6703 | 0 | return tor_addr_family(&port->addr) == AF_INET || |
6704 | 0 | (tor_addr_family(&port->addr) == AF_UNSPEC |
6705 | 0 | && !port->server_cfg.bind_ipv6_only); |
6706 | 0 | } |
6707 | | |
6708 | | /* Does port bind to IPv6? */ |
6709 | | int |
6710 | | port_binds_ipv6(const port_cfg_t *port) |
6711 | 0 | { |
6712 | 0 | return tor_addr_family(&port->addr) == AF_INET6 || |
6713 | 0 | (tor_addr_family(&port->addr) == AF_UNSPEC |
6714 | 0 | && !port->server_cfg.bind_ipv4_only); |
6715 | 0 | } |
6716 | | |
6717 | | /** Return a list of port_cfg_t for client ports parsed from the |
6718 | | * options. */ |
6719 | | MOCK_IMPL(const smartlist_t *, |
6720 | | get_configured_ports,(void)) |
6721 | 0 | { |
6722 | 0 | if (!configured_ports) |
6723 | 0 | configured_ports = smartlist_new(); |
6724 | 0 | return configured_ports; |
6725 | 0 | } |
6726 | | |
6727 | | /** Return an address:port string representation of the address |
6728 | | * where the first <b>listener_type</b> listener waits for |
6729 | | * connections. Return NULL if we couldn't find a listener. The |
6730 | | * string is allocated on the heap and it's the responsibility of the |
6731 | | * caller to free it after use. |
6732 | | * |
6733 | | * This function is meant to be used by the pluggable transport proxy |
6734 | | * spawning code, please make sure that it fits your purposes before |
6735 | | * using it. */ |
6736 | | char * |
6737 | | get_first_listener_addrport_string(int listener_type) |
6738 | 0 | { |
6739 | 0 | static const char *ipv4_localhost = "127.0.0.1"; |
6740 | 0 | static const char *ipv6_localhost = "[::1]"; |
6741 | 0 | const char *address; |
6742 | 0 | uint16_t port; |
6743 | 0 | char *string = NULL; |
6744 | |
|
6745 | 0 | if (!configured_ports) |
6746 | 0 | return NULL; |
6747 | | |
6748 | 0 | SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) { |
6749 | 0 | if (cfg->server_cfg.no_listen) |
6750 | 0 | continue; |
6751 | | |
6752 | 0 | if (cfg->type == listener_type && |
6753 | 0 | tor_addr_family(&cfg->addr) != AF_UNSPEC) { |
6754 | | |
6755 | | /* We found the first listener of the type we are interested in! */ |
6756 | | |
6757 | | /* If a listener is listening on INADDR_ANY, assume that it's |
6758 | | also listening on 127.0.0.1, and point the transport proxy |
6759 | | there: */ |
6760 | 0 | if (tor_addr_is_null(&cfg->addr)) |
6761 | 0 | address = tor_addr_is_v4(&cfg->addr) ? ipv4_localhost : ipv6_localhost; |
6762 | 0 | else |
6763 | 0 | address = fmt_and_decorate_addr(&cfg->addr); |
6764 | | |
6765 | | /* If a listener is configured with port 'auto', we are forced |
6766 | | to iterate all listener connections and find out in which |
6767 | | port it ended up listening: */ |
6768 | 0 | if (cfg->port == CFG_AUTO_PORT) { |
6769 | 0 | port = router_get_active_listener_port_by_type_af(listener_type, |
6770 | 0 | tor_addr_family(&cfg->addr)); |
6771 | 0 | if (!port) |
6772 | 0 | return NULL; |
6773 | 0 | } else { |
6774 | 0 | port = cfg->port; |
6775 | 0 | } |
6776 | | |
6777 | 0 | tor_asprintf(&string, "%s:%u", address, port); |
6778 | |
|
6779 | 0 | return string; |
6780 | 0 | } |
6781 | |
|
6782 | 0 | } SMARTLIST_FOREACH_END(cfg); |
6783 | | |
6784 | 0 | return NULL; |
6785 | 0 | } |
6786 | | |
6787 | | /** Find and return the first configured advertised `port_cfg_t` of type @a |
6788 | | * listener_type in @a address_family. */ |
6789 | | static const port_cfg_t * |
6790 | | portconf_get_first_advertised(int listener_type, int address_family) |
6791 | 0 | { |
6792 | 0 | const port_cfg_t *first_port = NULL; |
6793 | 0 | const port_cfg_t *first_port_explicit_addr = NULL; |
6794 | |
|
6795 | 0 | if (address_family == AF_UNSPEC) |
6796 | 0 | return NULL; |
6797 | | |
6798 | 0 | const smartlist_t *conf_ports = get_configured_ports(); |
6799 | 0 | SMARTLIST_FOREACH_BEGIN(conf_ports, const port_cfg_t *, cfg) { |
6800 | 0 | if (cfg->type == listener_type && !cfg->server_cfg.no_advertise) { |
6801 | 0 | if ((address_family == AF_INET && port_binds_ipv4(cfg)) || |
6802 | 0 | (address_family == AF_INET6 && port_binds_ipv6(cfg))) { |
6803 | 0 | if (cfg->explicit_addr && !first_port_explicit_addr) { |
6804 | 0 | first_port_explicit_addr = cfg; |
6805 | 0 | } else if (!first_port) { |
6806 | 0 | first_port = cfg; |
6807 | 0 | } |
6808 | 0 | } |
6809 | 0 | } |
6810 | 0 | } SMARTLIST_FOREACH_END(cfg); |
6811 | | |
6812 | | /* Prefer the port with the explicit address if any. */ |
6813 | 0 | return (first_port_explicit_addr) ? first_port_explicit_addr : first_port; |
6814 | 0 | } |
6815 | | |
6816 | | /** Return the first advertised port of type <b>listener_type</b> in |
6817 | | * <b>address_family</b>. Returns 0 when no port is found, and when passed |
6818 | | * AF_UNSPEC. */ |
6819 | | int |
6820 | | portconf_get_first_advertised_port(int listener_type, int address_family) |
6821 | 0 | { |
6822 | 0 | const port_cfg_t *cfg; |
6823 | 0 | cfg = portconf_get_first_advertised(listener_type, address_family); |
6824 | |
|
6825 | 0 | return cfg ? cfg->port : 0; |
6826 | 0 | } |
6827 | | |
6828 | | /** Return the first advertised address of type <b>listener_type</b> in |
6829 | | * <b>address_family</b>. Returns NULL if there is no advertised address, |
6830 | | * and when passed AF_UNSPEC. */ |
6831 | | const tor_addr_t * |
6832 | | portconf_get_first_advertised_addr(int listener_type, int address_family) |
6833 | 0 | { |
6834 | 0 | const port_cfg_t *cfg; |
6835 | 0 | cfg = portconf_get_first_advertised(listener_type, address_family); |
6836 | |
|
6837 | 0 | return cfg ? &cfg->addr : NULL; |
6838 | 0 | } |
6839 | | |
6840 | | /** Return 1 if a port exists of type <b>listener_type</b> on <b>addr</b> and |
6841 | | * <b>port</b>. If <b>check_wildcard</b> is true, INADDR[6]_ANY and AF_UNSPEC |
6842 | | * addresses match any address of the appropriate family; and port -1 matches |
6843 | | * any port. |
6844 | | * To match auto ports, pass CFG_PORT_AUTO. (Does not match on the actual |
6845 | | * automatically chosen listener ports.) */ |
6846 | | int |
6847 | | port_exists_by_type_addr_port(int listener_type, const tor_addr_t *addr, |
6848 | | int port, int check_wildcard) |
6849 | 0 | { |
6850 | 0 | if (!configured_ports || !addr) |
6851 | 0 | return 0; |
6852 | 0 | SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) { |
6853 | 0 | if (cfg->type == listener_type) { |
6854 | 0 | if (cfg->port == port || (check_wildcard && port == -1)) { |
6855 | | /* Exact match */ |
6856 | 0 | if (tor_addr_eq(&cfg->addr, addr)) { |
6857 | 0 | return 1; |
6858 | 0 | } |
6859 | | /* Skip wildcard matches if we're not doing them */ |
6860 | 0 | if (!check_wildcard) { |
6861 | 0 | continue; |
6862 | 0 | } |
6863 | | /* Wildcard matches IPv4 */ |
6864 | 0 | const int cfg_v4 = port_binds_ipv4(cfg); |
6865 | 0 | const int cfg_any_v4 = tor_addr_is_null(&cfg->addr) && cfg_v4; |
6866 | 0 | const int addr_v4 = tor_addr_family(addr) == AF_INET || |
6867 | 0 | tor_addr_family(addr) == AF_UNSPEC; |
6868 | 0 | const int addr_any_v4 = tor_addr_is_null(&cfg->addr) && addr_v4; |
6869 | 0 | if ((cfg_any_v4 && addr_v4) || (cfg_v4 && addr_any_v4)) { |
6870 | 0 | return 1; |
6871 | 0 | } |
6872 | | /* Wildcard matches IPv6 */ |
6873 | 0 | const int cfg_v6 = port_binds_ipv6(cfg); |
6874 | 0 | const int cfg_any_v6 = tor_addr_is_null(&cfg->addr) && cfg_v6; |
6875 | 0 | const int addr_v6 = tor_addr_family(addr) == AF_INET6 || |
6876 | 0 | tor_addr_family(addr) == AF_UNSPEC; |
6877 | 0 | const int addr_any_v6 = tor_addr_is_null(&cfg->addr) && addr_v6; |
6878 | 0 | if ((cfg_any_v6 && addr_v6) || (cfg_v6 && addr_any_v6)) { |
6879 | 0 | return 1; |
6880 | 0 | } |
6881 | 0 | } |
6882 | 0 | } |
6883 | 0 | } SMARTLIST_FOREACH_END(cfg); |
6884 | 0 | return 0; |
6885 | 0 | } |
6886 | | |
6887 | | /* Like port_exists_by_type_addr_port, but accepts a host-order IPv4 address |
6888 | | * instead. */ |
6889 | | int |
6890 | | port_exists_by_type_addr32h_port(int listener_type, uint32_t addr_ipv4h, |
6891 | | int port, int check_wildcard) |
6892 | 0 | { |
6893 | 0 | tor_addr_t ipv4; |
6894 | 0 | tor_addr_from_ipv4h(&ipv4, addr_ipv4h); |
6895 | 0 | return port_exists_by_type_addr_port(listener_type, &ipv4, port, |
6896 | 0 | check_wildcard); |
6897 | 0 | } |
6898 | | |
6899 | | /** Allocate and return a good value for the DataDirectory based on |
6900 | | * <b>val</b>, which may be NULL. Return NULL on failure. */ |
6901 | | static char * |
6902 | | get_data_directory(const char *val) |
6903 | 0 | { |
6904 | | #ifdef _WIN32 |
6905 | | if (val) { |
6906 | | return tor_strdup(val); |
6907 | | } else { |
6908 | | return tor_strdup(get_windows_conf_root()); |
6909 | | } |
6910 | | #elif defined(__ANDROID__) |
6911 | | /* Android apps can only use paths that are configured at runtime. |
6912 | | * /data/local/tmp is guaranteed to exist, but is only usable by the |
6913 | | * 'shell' and 'root' users, so this fallback is for debugging only. */ |
6914 | | if (val) { |
6915 | | return tor_strdup(val); |
6916 | | } else { |
6917 | | return tor_strdup("/data/local/tmp"); |
6918 | | } |
6919 | | #else /* !defined(_WIN32) */ |
6920 | 0 | const char *d = val; |
6921 | 0 | if (!d) |
6922 | 0 | d = "~/.tor"; |
6923 | |
|
6924 | 0 | if (!strcmpstart(d, "~/")) { |
6925 | 0 | char *fn = expand_filename(d); |
6926 | 0 | if (!fn) { |
6927 | 0 | log_warn(LD_CONFIG,"Failed to expand filename \"%s\".", d); |
6928 | 0 | return NULL; |
6929 | 0 | } |
6930 | 0 | if (!val && !strcmp(fn,"/.tor")) { |
6931 | | /* If our homedir is /, we probably don't want to use it. */ |
6932 | | /* Default to LOCALSTATEDIR/tor which is probably closer to what we |
6933 | | * want. */ |
6934 | 0 | log_warn(LD_CONFIG, |
6935 | 0 | "Default DataDirectory is \"~/.tor\". This expands to " |
6936 | 0 | "\"%s\", which is probably not what you want. Using " |
6937 | 0 | "\"%s"PATH_SEPARATOR"tor\" instead", fn, LOCALSTATEDIR); |
6938 | 0 | tor_free(fn); |
6939 | 0 | fn = tor_strdup(LOCALSTATEDIR PATH_SEPARATOR "tor"); |
6940 | 0 | } |
6941 | 0 | return fn; |
6942 | 0 | } |
6943 | 0 | return tor_strdup(d); |
6944 | 0 | #endif /* defined(_WIN32) */ |
6945 | 0 | } |
6946 | | |
6947 | | /** Check and normalize the values of options->{Key,Data,Cache}Directory; |
6948 | | * return 0 if it is sane, -1 otherwise. */ |
6949 | | static int |
6950 | | validate_data_directories(or_options_t *options) |
6951 | 0 | { |
6952 | 0 | tor_free(options->DataDirectory); |
6953 | 0 | options->DataDirectory = get_data_directory(options->DataDirectory_option); |
6954 | 0 | if (!options->DataDirectory) |
6955 | 0 | return -1; |
6956 | 0 | if (strlen(options->DataDirectory) > (512-128)) { |
6957 | 0 | log_warn(LD_CONFIG, "DataDirectory is too long."); |
6958 | 0 | return -1; |
6959 | 0 | } |
6960 | | |
6961 | 0 | tor_free(options->KeyDirectory); |
6962 | 0 | if (options->KeyDirectory_option) { |
6963 | 0 | options->KeyDirectory = get_data_directory(options->KeyDirectory_option); |
6964 | 0 | if (!options->KeyDirectory) |
6965 | 0 | return -1; |
6966 | 0 | } else { |
6967 | | /* Default to the data directory's keys subdir */ |
6968 | 0 | tor_asprintf(&options->KeyDirectory, "%s"PATH_SEPARATOR"keys", |
6969 | 0 | options->DataDirectory); |
6970 | 0 | } |
6971 | | |
6972 | 0 | tor_free(options->CacheDirectory); |
6973 | 0 | if (options->CacheDirectory_option) { |
6974 | 0 | options->CacheDirectory = get_data_directory( |
6975 | 0 | options->CacheDirectory_option); |
6976 | 0 | if (!options->CacheDirectory) |
6977 | 0 | return -1; |
6978 | 0 | } else { |
6979 | | /* Default to the data directory. */ |
6980 | 0 | options->CacheDirectory = tor_strdup(options->DataDirectory); |
6981 | 0 | } |
6982 | | |
6983 | 0 | return 0; |
6984 | 0 | } |
6985 | | |
6986 | | /** This string must remain the same forevermore. It is how we |
6987 | | * recognize that the torrc file doesn't need to be backed up. */ |
6988 | 0 | #define GENERATED_FILE_PREFIX "# This file was generated by Tor; " \ |
6989 | 0 | "if you edit it, comments will not be preserved" |
6990 | | /** This string can change; it tries to give the reader an idea |
6991 | | * that editing this file by hand is not a good plan. */ |
6992 | 0 | #define GENERATED_FILE_COMMENT "# The old torrc file was renamed " \ |
6993 | 0 | "to torrc.orig.1, and Tor will ignore it" |
6994 | | |
6995 | | /** Save a configuration file for the configuration in <b>options</b> |
6996 | | * into the file <b>fname</b>. If the file already exists, and |
6997 | | * doesn't begin with GENERATED_FILE_PREFIX, rename it. Otherwise |
6998 | | * replace it. Return 0 on success, -1 on failure. */ |
6999 | | static int |
7000 | | write_configuration_file(const char *fname, const or_options_t *options) |
7001 | 0 | { |
7002 | 0 | char *old_val=NULL, *new_val=NULL, *new_conf=NULL; |
7003 | 0 | int rename_old = 0, r; |
7004 | |
|
7005 | 0 | if (!fname) |
7006 | 0 | return -1; |
7007 | | |
7008 | 0 | switch (file_status(fname)) { |
7009 | | /* create backups of old config files, even if they're empty */ |
7010 | 0 | case FN_FILE: |
7011 | 0 | case FN_EMPTY: |
7012 | 0 | old_val = read_file_to_str(fname, 0, NULL); |
7013 | 0 | if (!old_val || strcmpstart(old_val, GENERATED_FILE_PREFIX)) { |
7014 | 0 | rename_old = 1; |
7015 | 0 | } |
7016 | 0 | tor_free(old_val); |
7017 | 0 | break; |
7018 | 0 | case FN_NOENT: |
7019 | 0 | break; |
7020 | 0 | case FN_ERROR: |
7021 | 0 | case FN_DIR: |
7022 | 0 | default: |
7023 | 0 | log_warn(LD_CONFIG, |
7024 | 0 | "Config file \"%s\" is not a file? Failing.", fname); |
7025 | 0 | return -1; |
7026 | 0 | } |
7027 | | |
7028 | 0 | if (!(new_conf = options_dump(options, OPTIONS_DUMP_MINIMAL))) { |
7029 | 0 | log_warn(LD_BUG, "Couldn't get configuration string"); |
7030 | 0 | goto err; |
7031 | 0 | } |
7032 | | |
7033 | 0 | tor_asprintf(&new_val, "%s\n%s\n\n%s", |
7034 | 0 | GENERATED_FILE_PREFIX, GENERATED_FILE_COMMENT, new_conf); |
7035 | |
|
7036 | 0 | if (rename_old) { |
7037 | 0 | char *fn_tmp = NULL; |
7038 | 0 | tor_asprintf(&fn_tmp, CONFIG_BACKUP_PATTERN, fname); |
7039 | 0 | file_status_t fn_tmp_status = file_status(fn_tmp); |
7040 | 0 | if (fn_tmp_status == FN_DIR || fn_tmp_status == FN_ERROR) { |
7041 | 0 | log_warn(LD_CONFIG, |
7042 | 0 | "Config backup file \"%s\" is not a file? Failing.", fn_tmp); |
7043 | 0 | tor_free(fn_tmp); |
7044 | 0 | goto err; |
7045 | 0 | } |
7046 | | |
7047 | 0 | log_notice(LD_CONFIG, "Renaming old configuration file to \"%s\"", fn_tmp); |
7048 | 0 | if (replace_file(fname, fn_tmp) < 0) { |
7049 | 0 | log_warn(LD_FS, |
7050 | 0 | "Couldn't rename configuration file \"%s\" to \"%s\": %s", |
7051 | 0 | fname, fn_tmp, strerror(errno)); |
7052 | 0 | tor_free(fn_tmp); |
7053 | 0 | goto err; |
7054 | 0 | } |
7055 | 0 | tor_free(fn_tmp); |
7056 | 0 | } |
7057 | | |
7058 | 0 | if (write_str_to_file(fname, new_val, 0) < 0) |
7059 | 0 | goto err; |
7060 | | |
7061 | 0 | r = 0; |
7062 | 0 | goto done; |
7063 | 0 | err: |
7064 | 0 | r = -1; |
7065 | 0 | done: |
7066 | 0 | tor_free(new_val); |
7067 | 0 | tor_free(new_conf); |
7068 | 0 | return r; |
7069 | 0 | } |
7070 | | |
7071 | | /** |
7072 | | * Save the current configuration file value to disk. Return 0 on |
7073 | | * success, -1 on failure. |
7074 | | **/ |
7075 | | int |
7076 | | options_save_current(void) |
7077 | 0 | { |
7078 | | /* This fails if we can't write to our configuration file. |
7079 | | * |
7080 | | * If we try falling back to datadirectory or something, we have a better |
7081 | | * chance of saving the configuration, but a better chance of doing |
7082 | | * something the user never expected. */ |
7083 | 0 | return write_configuration_file(get_torrc_fname(0), get_options()); |
7084 | 0 | } |
7085 | | |
7086 | | /** Return the number of cpus configured in <b>options</b>. If we are |
7087 | | * told to auto-detect the number of cpus, return the auto-detected number. */ |
7088 | | int |
7089 | | get_num_cpus(const or_options_t *options) |
7090 | 0 | { |
7091 | 0 | if (options->NumCPUs == 0) { |
7092 | 0 | int n = compute_num_cpus(); |
7093 | 0 | return (n >= 1) ? n : 1; |
7094 | 0 | } else { |
7095 | 0 | return options->NumCPUs; |
7096 | 0 | } |
7097 | 0 | } |
7098 | | |
7099 | | /** |
7100 | | * Initialize the libevent library. |
7101 | | */ |
7102 | | static void |
7103 | | init_libevent(const or_options_t *options) |
7104 | 0 | { |
7105 | 0 | tor_libevent_cfg_t cfg; |
7106 | |
|
7107 | 0 | tor_assert(options); |
7108 | | |
7109 | 0 | configure_libevent_logging(); |
7110 | | /* If the kernel complains that some method (say, epoll) doesn't |
7111 | | * exist, we don't care about it, since libevent will cope. |
7112 | | */ |
7113 | 0 | suppress_libevent_log_msg("Function not implemented"); |
7114 | |
|
7115 | 0 | memset(&cfg, 0, sizeof(cfg)); |
7116 | 0 | cfg.num_cpus = get_num_cpus(options); |
7117 | 0 | cfg.msec_per_tick = options->TokenBucketRefillInterval; |
7118 | |
|
7119 | 0 | tor_libevent_initialize(&cfg); |
7120 | |
|
7121 | 0 | suppress_libevent_log_msg(NULL); |
7122 | 0 | } |
7123 | | |
7124 | | /** Return a newly allocated string holding a filename relative to the |
7125 | | * directory in <b>options</b> specified by <b>roottype</b>. |
7126 | | * If <b>sub1</b> is present, it is the first path component after |
7127 | | * the data directory. If <b>sub2</b> is also present, it is the second path |
7128 | | * component after the data directory. If <b>suffix</b> is present, it |
7129 | | * is appended to the filename. |
7130 | | * |
7131 | | * Note: Consider using macros in config.h that wrap this function; |
7132 | | * you should probably never need to call it as-is. |
7133 | | */ |
7134 | | MOCK_IMPL(char *, |
7135 | | options_get_dir_fname2_suffix,(const or_options_t *options, |
7136 | | directory_root_t roottype, |
7137 | | const char *sub1, const char *sub2, |
7138 | | const char *suffix)) |
7139 | 0 | { |
7140 | 0 | tor_assert(options); |
7141 | | |
7142 | 0 | const char *rootdir = NULL; |
7143 | 0 | switch (roottype) { |
7144 | 0 | case DIRROOT_DATADIR: |
7145 | 0 | rootdir = options->DataDirectory; |
7146 | 0 | break; |
7147 | 0 | case DIRROOT_CACHEDIR: |
7148 | 0 | rootdir = options->CacheDirectory; |
7149 | 0 | break; |
7150 | 0 | case DIRROOT_KEYDIR: |
7151 | 0 | rootdir = options->KeyDirectory; |
7152 | 0 | break; |
7153 | 0 | default: |
7154 | 0 | tor_assert_unreached(); |
7155 | 0 | break; |
7156 | 0 | } |
7157 | 0 | tor_assert(rootdir); |
7158 | | |
7159 | 0 | if (!suffix) |
7160 | 0 | suffix = ""; |
7161 | |
|
7162 | 0 | char *fname = NULL; |
7163 | |
|
7164 | 0 | if (sub1 == NULL) { |
7165 | 0 | tor_asprintf(&fname, "%s%s", rootdir, suffix); |
7166 | 0 | tor_assert(!sub2); /* If sub2 is present, sub1 must be present. */ |
7167 | 0 | } else if (sub2 == NULL) { |
7168 | 0 | tor_asprintf(&fname, "%s"PATH_SEPARATOR"%s%s", rootdir, sub1, suffix); |
7169 | 0 | } else { |
7170 | 0 | tor_asprintf(&fname, "%s"PATH_SEPARATOR"%s"PATH_SEPARATOR"%s%s", |
7171 | 0 | rootdir, sub1, sub2, suffix); |
7172 | 0 | } |
7173 | | |
7174 | 0 | return fname; |
7175 | 0 | } |
7176 | | |
7177 | | /** Check whether the data directory has a private subdirectory |
7178 | | * <b>subdir</b>. If not, try to create it. Return 0 on success, |
7179 | | * -1 otherwise. */ |
7180 | | int |
7181 | | check_or_create_data_subdir(const char *subdir) |
7182 | 0 | { |
7183 | 0 | char *statsdir = get_datadir_fname(subdir); |
7184 | 0 | int return_val = 0; |
7185 | |
|
7186 | 0 | if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) { |
7187 | 0 | log_warn(LD_HIST, "Unable to create %s/ directory!", subdir); |
7188 | 0 | return_val = -1; |
7189 | 0 | } |
7190 | 0 | tor_free(statsdir); |
7191 | 0 | return return_val; |
7192 | 0 | } |
7193 | | |
7194 | | /** Create a file named <b>fname</b> with contents <b>str</b> in the |
7195 | | * subdirectory <b>subdir</b> of the data directory. <b>descr</b> |
7196 | | * should be a short description of the file's content and will be |
7197 | | * used for the warning message, if it's present and the write process |
7198 | | * fails. Return 0 on success, -1 otherwise.*/ |
7199 | | int |
7200 | | write_to_data_subdir(const char* subdir, const char* fname, |
7201 | | const char* str, const char* descr) |
7202 | 0 | { |
7203 | 0 | char *filename = get_datadir_fname2(subdir, fname); |
7204 | 0 | int return_val = 0; |
7205 | |
|
7206 | 0 | if (write_str_to_file(filename, str, 0) < 0) { |
7207 | 0 | log_warn(LD_HIST, "Unable to write %s to disk!", descr ? descr : fname); |
7208 | 0 | return_val = -1; |
7209 | 0 | } |
7210 | 0 | tor_free(filename); |
7211 | 0 | return return_val; |
7212 | 0 | } |
7213 | | |
7214 | | /** Helper to implement GETINFO functions about configuration variables (not |
7215 | | * their values). Given a "config/names" question, set *<b>answer</b> to a |
7216 | | * new string describing the supported configuration variables and their |
7217 | | * types. */ |
7218 | | int |
7219 | | getinfo_helper_config(control_connection_t *conn, |
7220 | | const char *question, char **answer, |
7221 | | const char **errmsg) |
7222 | 0 | { |
7223 | 0 | (void) conn; |
7224 | 0 | (void) errmsg; |
7225 | 0 | if (!strcmp(question, "config/names")) { |
7226 | 0 | smartlist_t *sl = smartlist_new(); |
7227 | 0 | smartlist_t *vars = config_mgr_list_vars(get_options_mgr()); |
7228 | 0 | SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) { |
7229 | | /* don't tell controller about invisible options */ |
7230 | 0 | if (! config_var_is_listable(var)) |
7231 | 0 | continue; |
7232 | 0 | const char *type = struct_var_get_typename(&var->member); |
7233 | 0 | if (!type) |
7234 | 0 | continue; |
7235 | 0 | smartlist_add_asprintf(sl, "%s %s\n",var->member.name,type); |
7236 | 0 | } SMARTLIST_FOREACH_END(var); |
7237 | 0 | *answer = smartlist_join_strings(sl, "", 0, NULL); |
7238 | 0 | SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); |
7239 | 0 | smartlist_free(sl); |
7240 | 0 | smartlist_free(vars); |
7241 | 0 | } else if (!strcmp(question, "config/defaults")) { |
7242 | 0 | smartlist_t *sl = smartlist_new(); |
7243 | 0 | int dirauth_lines_seen = 0, fallback_lines_seen = 0; |
7244 | | /* Possibly this should check whether the variables are listable, |
7245 | | * but currently it does not. See ticket 31654. */ |
7246 | 0 | smartlist_t *vars = config_mgr_list_vars(get_options_mgr()); |
7247 | 0 | SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) { |
7248 | 0 | if (var->initvalue != NULL) { |
7249 | 0 | if (strcmp(var->member.name, "DirAuthority") == 0) { |
7250 | | /* |
7251 | | * Count dirauth lines we have a default for; we'll use the |
7252 | | * count later to decide whether to add the defaults manually |
7253 | | */ |
7254 | 0 | ++dirauth_lines_seen; |
7255 | 0 | } |
7256 | 0 | if (strcmp(var->member.name, "FallbackDir") == 0) { |
7257 | | /* |
7258 | | * Similarly count fallback lines, so that we can decide later |
7259 | | * to add the defaults manually. |
7260 | | */ |
7261 | 0 | ++fallback_lines_seen; |
7262 | 0 | } |
7263 | 0 | char *val = esc_for_log(var->initvalue); |
7264 | 0 | smartlist_add_asprintf(sl, "%s %s\n",var->member.name,val); |
7265 | 0 | tor_free(val); |
7266 | 0 | } |
7267 | 0 | } SMARTLIST_FOREACH_END(var); |
7268 | 0 | smartlist_free(vars); |
7269 | |
|
7270 | 0 | if (dirauth_lines_seen == 0) { |
7271 | | /* |
7272 | | * We didn't see any directory authorities with default values, |
7273 | | * so add the list of default authorities manually. |
7274 | | */ |
7275 | | |
7276 | | /* |
7277 | | * default_authorities is defined earlier in this file and |
7278 | | * is a const char ** NULL-terminated array of dirauth config |
7279 | | * lines. |
7280 | | */ |
7281 | 0 | for (const char **i = default_authorities; *i != NULL; ++i) { |
7282 | 0 | char *val = esc_for_log(*i); |
7283 | 0 | smartlist_add_asprintf(sl, "DirAuthority %s\n", val); |
7284 | 0 | tor_free(val); |
7285 | 0 | } |
7286 | 0 | } |
7287 | |
|
7288 | 0 | if (fallback_lines_seen == 0 && |
7289 | 0 | get_options()->UseDefaultFallbackDirs == 1) { |
7290 | | /* |
7291 | | * We didn't see any explicitly configured fallback mirrors, |
7292 | | * so add the defaults to the list manually. |
7293 | | * |
7294 | | * default_fallbacks is included earlier in this file and |
7295 | | * is a const char ** NULL-terminated array of fallback config lines. |
7296 | | */ |
7297 | 0 | const char **i; |
7298 | |
|
7299 | 0 | for (i = default_fallbacks; *i != NULL; ++i) { |
7300 | 0 | char *val = esc_for_log(*i); |
7301 | 0 | smartlist_add_asprintf(sl, "FallbackDir %s\n", val); |
7302 | 0 | tor_free(val); |
7303 | 0 | } |
7304 | 0 | } |
7305 | |
|
7306 | 0 | *answer = smartlist_join_strings(sl, "", 0, NULL); |
7307 | 0 | SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); |
7308 | 0 | smartlist_free(sl); |
7309 | 0 | } |
7310 | 0 | return 0; |
7311 | 0 | } |
7312 | | |
7313 | | /* Check whether an address has already been set against the options |
7314 | | * depending on address family and destination type. Any existing |
7315 | | * value will lead to a fail, even if it is the same value. If not |
7316 | | * set and not only validating, copy it into this location too. |
7317 | | * Returns 0 on success or -1 if this address is already set. |
7318 | | */ |
7319 | | static int |
7320 | | verify_and_store_outbound_address(sa_family_t family, tor_addr_t *addr, |
7321 | | outbound_addr_t type, or_options_t *options, int validate_only) |
7322 | 0 | { |
7323 | 0 | if (type>=OUTBOUND_ADDR_MAX || (family!=AF_INET && family!=AF_INET6)) { |
7324 | 0 | return -1; |
7325 | 0 | } |
7326 | 0 | int fam_index=0; |
7327 | 0 | if (family==AF_INET6) { |
7328 | 0 | fam_index=1; |
7329 | 0 | } |
7330 | 0 | tor_addr_t *dest=&options->OutboundBindAddresses[type][fam_index]; |
7331 | 0 | if (!tor_addr_is_null(dest)) { |
7332 | 0 | return -1; |
7333 | 0 | } |
7334 | 0 | if (!validate_only) { |
7335 | 0 | tor_addr_copy(dest, addr); |
7336 | 0 | } |
7337 | 0 | return 0; |
7338 | 0 | } |
7339 | | |
7340 | | /* Parse a list of address lines for a specific destination type. |
7341 | | * Will store them into the options if not validate_only. If a |
7342 | | * problem occurs, a suitable error message is store in msg. |
7343 | | * Returns 0 on success or -1 if any address is already set. |
7344 | | */ |
7345 | | static int |
7346 | | parse_outbound_address_lines(const config_line_t *lines, outbound_addr_t type, |
7347 | | or_options_t *options, int validate_only, char **msg) |
7348 | 0 | { |
7349 | 0 | tor_addr_t addr; |
7350 | 0 | sa_family_t family; |
7351 | 0 | while (lines) { |
7352 | 0 | family = tor_addr_parse(&addr, lines->value); |
7353 | 0 | if (verify_and_store_outbound_address(family, &addr, type, |
7354 | 0 | options, validate_only)) { |
7355 | 0 | if (msg) |
7356 | 0 | tor_asprintf(msg, "Multiple%s%s outbound bind addresses " |
7357 | 0 | "configured: %s", |
7358 | 0 | family==AF_INET?" IPv4":(family==AF_INET6?" IPv6":""), |
7359 | 0 | type==OUTBOUND_ADDR_OR?" OR": |
7360 | 0 | (type==OUTBOUND_ADDR_EXIT?" exit": |
7361 | 0 | (type==OUTBOUND_ADDR_PT?" PT":"")), lines->value); |
7362 | 0 | return -1; |
7363 | 0 | } |
7364 | 0 | lines = lines->next; |
7365 | 0 | } |
7366 | 0 | return 0; |
7367 | 0 | } |
7368 | | |
7369 | | /** Parse outbound bind address option lines. If <b>validate_only</b> |
7370 | | * is not 0 update OutboundBindAddresses in <b>options</b>. |
7371 | | * Only one address can be set for any of these values. |
7372 | | * On failure, set <b>msg</b> (if provided) to a newly allocated string |
7373 | | * containing a description of the problem and return -1. |
7374 | | */ |
7375 | | static int |
7376 | | parse_outbound_addresses(or_options_t *options, int validate_only, char **msg) |
7377 | 0 | { |
7378 | 0 | if (!validate_only) { |
7379 | 0 | memset(&options->OutboundBindAddresses, 0, |
7380 | 0 | sizeof(options->OutboundBindAddresses)); |
7381 | 0 | } |
7382 | |
|
7383 | 0 | if (parse_outbound_address_lines(options->OutboundBindAddress, |
7384 | 0 | OUTBOUND_ADDR_ANY, options, |
7385 | 0 | validate_only, msg) < 0) { |
7386 | 0 | goto err; |
7387 | 0 | } |
7388 | | |
7389 | 0 | if (parse_outbound_address_lines(options->OutboundBindAddressOR, |
7390 | 0 | OUTBOUND_ADDR_OR, options, validate_only, |
7391 | 0 | msg) < 0) { |
7392 | 0 | goto err; |
7393 | 0 | } |
7394 | | |
7395 | 0 | if (parse_outbound_address_lines(options->OutboundBindAddressExit, |
7396 | 0 | OUTBOUND_ADDR_EXIT, options, validate_only, |
7397 | 0 | msg) < 0) { |
7398 | 0 | goto err; |
7399 | 0 | } |
7400 | | |
7401 | 0 | if (parse_outbound_address_lines(options->OutboundBindAddressPT, |
7402 | 0 | OUTBOUND_ADDR_PT, options, validate_only, |
7403 | 0 | msg) < 0) { |
7404 | 0 | goto err; |
7405 | 0 | } |
7406 | | |
7407 | 0 | return 0; |
7408 | 0 | err: |
7409 | 0 | return -1; |
7410 | 0 | } |
7411 | | |
7412 | | /** Load one of the geoip files, <a>family</a> determining which |
7413 | | * one. <a>default_fname</a> is used if on Windows and |
7414 | | * <a>fname</a> equals "<default>". */ |
7415 | | static void |
7416 | | config_load_geoip_file_(sa_family_t family, |
7417 | | const char *fname, |
7418 | | const char *default_fname) |
7419 | 0 | { |
7420 | 0 | const or_options_t *options = get_options(); |
7421 | 0 | const char *msg = ""; |
7422 | 0 | int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO; |
7423 | 0 | int r; |
7424 | |
|
7425 | | #ifdef _WIN32 |
7426 | | char *free_fname = NULL; /* Used to hold any temporary-allocated value */ |
7427 | | /* XXXX Don't use this "<default>" junk; make our filename options |
7428 | | * understand prefixes somehow. -NM */ |
7429 | | if (!strcmp(fname, "<default>")) { |
7430 | | const char *conf_root = get_windows_conf_root(); |
7431 | | tor_asprintf(&free_fname, "%s\\%s", conf_root, default_fname); |
7432 | | fname = free_fname; |
7433 | | } |
7434 | | r = geoip_load_file(family, fname, severity); |
7435 | | tor_free(free_fname); |
7436 | | #else /* !defined(_WIN32) */ |
7437 | 0 | (void)default_fname; |
7438 | 0 | r = geoip_load_file(family, fname, severity); |
7439 | 0 | #endif /* defined(_WIN32) */ |
7440 | |
|
7441 | 0 | if (r < 0 && severity == LOG_WARN) { |
7442 | 0 | log_warn(LD_GENERAL, "%s", msg); |
7443 | 0 | } |
7444 | 0 | } |
7445 | | |
7446 | | /** Load geoip files for IPv4 and IPv6 if <a>options</a> and |
7447 | | * <a>old_options</a> indicate we should. */ |
7448 | | static void |
7449 | | config_maybe_load_geoip_files_(const or_options_t *options, |
7450 | | const or_options_t *old_options) |
7451 | 0 | { |
7452 | | /* XXXX Reload GeoIPFile on SIGHUP. -NM */ |
7453 | |
|
7454 | 0 | if (options->GeoIPFile && |
7455 | 0 | ((!old_options || !opt_streq(old_options->GeoIPFile, |
7456 | 0 | options->GeoIPFile)) |
7457 | 0 | || !geoip_is_loaded(AF_INET))) { |
7458 | 0 | config_load_geoip_file_(AF_INET, options->GeoIPFile, "geoip"); |
7459 | | /* Okay, now we need to maybe change our mind about what is in |
7460 | | * which country. We do this for IPv4 only since that's what we |
7461 | | * store in node->country. */ |
7462 | 0 | refresh_all_country_info(); |
7463 | 0 | } |
7464 | 0 | if (options->GeoIPv6File && |
7465 | 0 | ((!old_options || !opt_streq(old_options->GeoIPv6File, |
7466 | 0 | options->GeoIPv6File)) |
7467 | 0 | || !geoip_is_loaded(AF_INET6))) { |
7468 | 0 | config_load_geoip_file_(AF_INET6, options->GeoIPv6File, "geoip6"); |
7469 | 0 | } |
7470 | 0 | } |
7471 | | |
7472 | | /** Initialize cookie authentication (used so far by the ControlPort |
7473 | | * and Extended ORPort). |
7474 | | * |
7475 | | * Allocate memory and create a cookie (of length <b>cookie_len</b>) |
7476 | | * in <b>cookie_out</b>. |
7477 | | * Then write it down to <b>fname</b> and prepend it with <b>header</b>. |
7478 | | * |
7479 | | * If <b>group_readable</b> is set, set <b>fname</b> to be readable |
7480 | | * by the default GID. |
7481 | | * |
7482 | | * If the whole procedure was successful, set |
7483 | | * <b>cookie_is_set_out</b> to True. */ |
7484 | | int |
7485 | | init_cookie_authentication(const char *fname, const char *header, |
7486 | | int cookie_len, int group_readable, |
7487 | | uint8_t **cookie_out, int *cookie_is_set_out) |
7488 | 0 | { |
7489 | 0 | char cookie_file_str_len = strlen(header) + cookie_len; |
7490 | 0 | char *cookie_file_str = tor_malloc(cookie_file_str_len); |
7491 | 0 | int retval = -1; |
7492 | | |
7493 | | /* We don't want to generate a new cookie every time we call |
7494 | | * options_act(). One should be enough. */ |
7495 | 0 | if (*cookie_is_set_out) { |
7496 | 0 | retval = 0; /* we are all set */ |
7497 | 0 | goto done; |
7498 | 0 | } |
7499 | | |
7500 | | /* If we've already set the cookie, free it before re-setting |
7501 | | it. This can happen if we previously generated a cookie, but |
7502 | | couldn't write it to a disk. */ |
7503 | 0 | if (*cookie_out) |
7504 | 0 | tor_free(*cookie_out); |
7505 | | |
7506 | | /* Generate the cookie */ |
7507 | 0 | *cookie_out = tor_malloc(cookie_len); |
7508 | 0 | crypto_rand((char *)*cookie_out, cookie_len); |
7509 | | |
7510 | | /* Create the string that should be written on the file. */ |
7511 | 0 | memcpy(cookie_file_str, header, strlen(header)); |
7512 | 0 | memcpy(cookie_file_str+strlen(header), *cookie_out, cookie_len); |
7513 | 0 | if (write_bytes_to_file(fname, cookie_file_str, cookie_file_str_len, 1)) { |
7514 | 0 | log_warn(LD_FS,"Error writing auth cookie to %s.", escaped(fname)); |
7515 | 0 | goto done; |
7516 | 0 | } |
7517 | | |
7518 | 0 | #ifndef _WIN32 |
7519 | 0 | if (group_readable) { |
7520 | 0 | if (chmod(fname, 0640)) { |
7521 | 0 | log_warn(LD_FS,"Unable to make %s group-readable.", escaped(fname)); |
7522 | 0 | } |
7523 | 0 | } |
7524 | | #else /* defined(_WIN32) */ |
7525 | | (void) group_readable; |
7526 | | #endif /* !defined(_WIN32) */ |
7527 | | |
7528 | | /* Success! */ |
7529 | 0 | log_info(LD_GENERAL, "Generated auth cookie file in '%s'.", escaped(fname)); |
7530 | 0 | *cookie_is_set_out = 1; |
7531 | 0 | retval = 0; |
7532 | |
|
7533 | 0 | done: |
7534 | 0 | memwipe(cookie_file_str, 0, cookie_file_str_len); |
7535 | 0 | tor_free(cookie_file_str); |
7536 | 0 | return retval; |
7537 | 0 | } |
7538 | | |
7539 | | /** |
7540 | | * Return true if any option is set in <b>options</b> to make us behave |
7541 | | * as a client. |
7542 | | */ |
7543 | | int |
7544 | | options_any_client_port_set(const or_options_t *options) |
7545 | 0 | { |
7546 | 0 | return (options->SocksPort_set || |
7547 | 0 | options->TransPort_set || |
7548 | 0 | options->NATDPort_set || |
7549 | 0 | options->DNSPort_set || |
7550 | 0 | options->HTTPTunnelPort_set); |
7551 | 0 | } |