/src/tor/src/app/main/main.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 main.c |
9 | | * \brief Invocation module. Initializes subsystems and runs the main loop. |
10 | | **/ |
11 | | |
12 | | #include "core/or/or.h" |
13 | | |
14 | | #include "app/config/config.h" |
15 | | #include "app/config/statefile.h" |
16 | | #include "app/config/quiet_level.h" |
17 | | #include "app/main/main.h" |
18 | | #include "app/main/ntmain.h" |
19 | | #include "app/main/risky_options.h" |
20 | | #include "app/main/shutdown.h" |
21 | | #include "app/main/subsysmgr.h" |
22 | | #include "core/mainloop/connection.h" |
23 | | #include "core/mainloop/cpuworker.h" |
24 | | #include "core/mainloop/mainloop.h" |
25 | | #include "core/mainloop/mainloop_pubsub.h" |
26 | | #include "core/mainloop/netstatus.h" |
27 | | #include "core/or/channel.h" |
28 | | #include "core/or/channelpadding.h" |
29 | | #include "core/or/circuitpadding.h" |
30 | | #include "core/or/congestion_control_common.h" |
31 | | #include "core/or/congestion_control_flow.h" |
32 | | #include "core/or/circuitlist.h" |
33 | | #include "core/or/command.h" |
34 | | #include "core/or/connection_or.h" |
35 | | #include "core/or/relay.h" |
36 | | #include "core/or/status.h" |
37 | | #include "feature/api/tor_api.h" |
38 | | #include "feature/api/tor_api_internal.h" |
39 | | #include "feature/client/addressmap.h" |
40 | | #include "feature/control/control.h" |
41 | | #include "feature/control/control_auth.h" |
42 | | #include "feature/control/control_events.h" |
43 | | #include "feature/dirauth/keypin.h" |
44 | | #include "feature/dirauth/process_descs.h" |
45 | | #include "feature/dircache/consdiffmgr.h" |
46 | | #include "feature/dirparse/routerparse.h" |
47 | | #include "feature/hibernate/hibernate.h" |
48 | | #include "feature/hs/hs_dos.h" |
49 | | #include "feature/hs/hs_service.h" |
50 | | #include "feature/nodelist/authcert.h" |
51 | | #include "feature/nodelist/networkstatus.h" |
52 | | #include "feature/nodelist/routerlist.h" |
53 | | #include "feature/relay/dns.h" |
54 | | #include "feature/relay/ext_orport.h" |
55 | | #include "feature/relay/routerkeys.h" |
56 | | #include "feature/relay/routermode.h" |
57 | | #include "feature/stats/predict_ports.h" |
58 | | #include "feature/stats/bwhist.h" |
59 | | #include "feature/stats/rephist.h" |
60 | | #include "lib/compress/compress.h" |
61 | | #include "lib/buf/buffers.h" |
62 | | #include "lib/crypt_ops/crypto_format.h" |
63 | | #include "lib/crypt_ops/crypto_rand.h" |
64 | | #include "lib/crypt_ops/crypto_s2k.h" |
65 | | #include "lib/net/resolve.h" |
66 | | #include "lib/trace/trace.h" |
67 | | |
68 | | #include "lib/process/waitpid.h" |
69 | | #include "lib/pubsub/pubsub_build.h" |
70 | | |
71 | | #include "lib/meminfo/meminfo.h" |
72 | | #include "lib/osinfo/uname.h" |
73 | | #include "lib/osinfo/libc.h" |
74 | | #include "lib/sandbox/sandbox.h" |
75 | | #include "lib/fs/lockfile.h" |
76 | | #include "lib/tls/tortls.h" |
77 | | #include "lib/evloop/compat_libevent.h" |
78 | | #include "lib/encoding/confline.h" |
79 | | #include "lib/evloop/timers.h" |
80 | | #include "lib/crypt_ops/crypto_init.h" |
81 | | #include "lib/version/torversion.h" |
82 | | |
83 | | #include <event2/event.h> |
84 | | |
85 | | #include "feature/dirauth/authmode.h" |
86 | | #include "feature/dirauth/shared_random.h" |
87 | | |
88 | | #include "core/or/or_connection_st.h" |
89 | | #include "core/or/port_cfg_st.h" |
90 | | |
91 | | #ifdef HAVE_UNISTD_H |
92 | | #include <unistd.h> |
93 | | #endif |
94 | | |
95 | | #ifdef HAVE_SYSTEMD |
96 | | # if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) |
97 | | /* Systemd's use of gcc's __INCLUDE_LEVEL__ extension macro appears to confuse |
98 | | * Coverity. Here's a kludge to unconfuse it. |
99 | | */ |
100 | | # define __INCLUDE_LEVEL__ 2 |
101 | | #endif /* defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) */ |
102 | | #include <systemd/sd-daemon.h> |
103 | | #endif /* defined(HAVE_SYSTEMD) */ |
104 | | |
105 | | /********* PROTOTYPES **********/ |
106 | | |
107 | | static void dumpmemusage(int severity); |
108 | | static void dumpstats(int severity); /* log stats */ |
109 | | static void process_signal(int sig); |
110 | | |
111 | | /** Called when we get a SIGHUP: reload configuration files and keys, |
112 | | * retry all connections, and so on. */ |
113 | | static int |
114 | | do_hup(void) |
115 | 0 | { |
116 | 0 | const or_options_t *options = get_options(); |
117 | |
|
118 | 0 | log_notice(LD_GENERAL,"Received reload signal (hup). Reloading config and " |
119 | 0 | "resetting internal state."); |
120 | 0 | if (accounting_is_enabled(options)) |
121 | 0 | accounting_record_bandwidth_usage(time(NULL), get_or_state()); |
122 | |
|
123 | 0 | router_reset_warnings(); |
124 | 0 | routerlist_reset_warnings(); |
125 | | /* first, reload config variables, in case they've changed */ |
126 | 0 | if (options->ReloadTorrcOnSIGHUP) { |
127 | | /* no need to provide argc/v, they've been cached in init_from_config */ |
128 | 0 | int init_rv = options_init_from_torrc(0, NULL); |
129 | 0 | if (init_rv < 0) { |
130 | 0 | log_err(LD_CONFIG,"Reading config failed--see warnings above. " |
131 | 0 | "For usage, try -h."); |
132 | 0 | return -1; |
133 | 0 | } else if (BUG(init_rv > 0)) { |
134 | | // LCOV_EXCL_START |
135 | | /* This should be impossible: the only "return 1" cases in |
136 | | * options_init_from_torrc are ones caused by command-line arguments; |
137 | | * but they can't change while Tor is running. */ |
138 | 0 | return -1; |
139 | | // LCOV_EXCL_STOP |
140 | 0 | } |
141 | 0 | options = get_options(); /* they have changed now */ |
142 | | /* Logs are only truncated the first time they are opened, but were |
143 | | probably intended to be cleaned up on signal. */ |
144 | 0 | if (options->TruncateLogFile) |
145 | 0 | truncate_logs(); |
146 | 0 | } else { |
147 | 0 | char *msg = NULL; |
148 | 0 | log_notice(LD_GENERAL, "Not reloading config file: the controller told " |
149 | 0 | "us not to."); |
150 | | /* Make stuff get rescanned, reloaded, etc. */ |
151 | 0 | if (set_options((or_options_t*)options, &msg) < 0) { |
152 | 0 | if (!msg) |
153 | 0 | msg = tor_strdup("Unknown error"); |
154 | 0 | log_warn(LD_GENERAL, "Unable to re-set previous options: %s", msg); |
155 | 0 | tor_free(msg); |
156 | 0 | } |
157 | 0 | } |
158 | 0 | if (authdir_mode(options)) { |
159 | | /* reload the approved-routers file */ |
160 | 0 | if (dirserv_load_fingerprint_file() < 0) { |
161 | | /* warnings are logged from dirserv_load_fingerprint_file() directly */ |
162 | 0 | log_info(LD_GENERAL, "Error reloading fingerprints. " |
163 | 0 | "Continuing with old list."); |
164 | 0 | } |
165 | 0 | } |
166 | | |
167 | | /* Rotate away from the old dirty circuits. This has to be done |
168 | | * after we've read the new options, but before we start using |
169 | | * circuits for directory fetches. */ |
170 | 0 | circuit_mark_all_dirty_circs_as_unusable(); |
171 | | |
172 | | /* retry appropriate downloads */ |
173 | 0 | router_reset_status_download_failures(); |
174 | 0 | router_reset_descriptor_download_failures(); |
175 | 0 | if (!net_is_disabled()) |
176 | 0 | update_networkstatus_downloads(time(NULL)); |
177 | | |
178 | | /* We'll retry routerstatus downloads in about 10 seconds; no need to |
179 | | * force a retry there. */ |
180 | |
|
181 | 0 | if (server_mode(options)) { |
182 | | /* Maybe we've been given a new ed25519 key or certificate? |
183 | | */ |
184 | 0 | time_t now = approx_time(); |
185 | 0 | int new_signing_key = load_ed_keys(options, now); |
186 | 0 | if (new_signing_key < 0 || |
187 | 0 | generate_ed_link_cert(options, now, new_signing_key > 0)) { |
188 | 0 | log_warn(LD_OR, "Problem reloading Ed25519 keys; still using old keys."); |
189 | 0 | } |
190 | | |
191 | | /* Update cpuworker and dnsworker processes, so they get up-to-date |
192 | | * configuration options. */ |
193 | 0 | cpuworkers_rotate_keyinfo(); |
194 | 0 | dns_reset(); |
195 | 0 | } |
196 | 0 | return 0; |
197 | 0 | } |
198 | | |
199 | | /** Libevent callback: invoked when we get a signal. |
200 | | */ |
201 | | static void |
202 | | signal_callback(evutil_socket_t fd, short events, void *arg) |
203 | 0 | { |
204 | 0 | const int *sigptr = arg; |
205 | 0 | const int sig = *sigptr; |
206 | 0 | (void)fd; |
207 | 0 | (void)events; |
208 | |
|
209 | 0 | update_current_time(time(NULL)); |
210 | 0 | process_signal(sig); |
211 | 0 | } |
212 | | |
213 | | /** Do the work of acting on a signal received in <b>sig</b> */ |
214 | | static void |
215 | | process_signal(int sig) |
216 | 0 | { |
217 | 0 | switch (sig) |
218 | 0 | { |
219 | 0 | case SIGTERM: |
220 | 0 | log_notice(LD_GENERAL,"Catching signal TERM, exiting cleanly."); |
221 | 0 | tor_shutdown_event_loop_and_exit(0); |
222 | 0 | break; |
223 | 0 | case SIGINT: |
224 | 0 | if (!server_mode(get_options())) { /* do it now */ |
225 | 0 | log_notice(LD_GENERAL,"Interrupt: exiting cleanly."); |
226 | 0 | tor_shutdown_event_loop_and_exit(0); |
227 | 0 | return; |
228 | 0 | } |
229 | | #ifdef HAVE_SYSTEMD |
230 | | sd_notify(0, "STOPPING=1"); |
231 | | #endif |
232 | 0 | hibernate_begin_shutdown(); |
233 | 0 | break; |
234 | 0 | #ifdef SIGPIPE |
235 | 0 | case SIGPIPE: |
236 | 0 | log_debug(LD_GENERAL,"Caught SIGPIPE. Ignoring."); |
237 | 0 | break; |
238 | 0 | #endif |
239 | 0 | case SIGUSR1: |
240 | | /* prefer to log it at INFO, but make sure we always see it */ |
241 | 0 | dumpstats(get_min_log_level()<LOG_INFO ? get_min_log_level() : LOG_INFO); |
242 | 0 | control_event_signal(sig); |
243 | 0 | break; |
244 | 0 | case SIGUSR2: |
245 | 0 | switch_logs_debug(); |
246 | 0 | log_debug(LD_GENERAL,"Caught USR2, going to loglevel debug. " |
247 | 0 | "Send HUP to change back."); |
248 | 0 | control_event_signal(sig); |
249 | 0 | break; |
250 | 0 | case SIGHUP: |
251 | | #ifdef HAVE_SYSTEMD |
252 | | sd_notify(0, "RELOADING=1"); |
253 | | #endif |
254 | 0 | if (do_hup() < 0) { |
255 | 0 | log_warn(LD_CONFIG,"Restart failed (config error?). Exiting."); |
256 | 0 | tor_shutdown_event_loop_and_exit(1); |
257 | 0 | return; |
258 | 0 | } |
259 | | #ifdef HAVE_SYSTEMD |
260 | | sd_notify(0, "READY=1"); |
261 | | #endif |
262 | 0 | control_event_signal(sig); |
263 | 0 | break; |
264 | 0 | #ifdef SIGCHLD |
265 | 0 | case SIGCHLD: |
266 | 0 | notify_pending_waitpid_callbacks(); |
267 | 0 | break; |
268 | 0 | #endif |
269 | 0 | case SIGNEWNYM: { |
270 | 0 | do_signewnym(time(NULL)); |
271 | 0 | break; |
272 | 0 | } |
273 | 0 | case SIGCLEARDNSCACHE: |
274 | 0 | addressmap_clear_transient(); |
275 | 0 | control_event_signal(sig); |
276 | 0 | break; |
277 | 0 | case SIGHEARTBEAT: |
278 | 0 | log_heartbeat(time(NULL)); |
279 | 0 | control_event_signal(sig); |
280 | 0 | break; |
281 | 0 | case SIGACTIVE: |
282 | | /* "SIGACTIVE" counts as ersatz user activity. */ |
283 | 0 | note_user_activity(approx_time()); |
284 | 0 | control_event_signal(sig); |
285 | 0 | break; |
286 | 0 | case SIGDORMANT: |
287 | | /* "SIGDORMANT" means to ignore past user activity */ |
288 | 0 | log_notice(LD_GENERAL, "Going dormant because of controller request."); |
289 | 0 | reset_user_activity(0); |
290 | 0 | set_network_participation(false); |
291 | 0 | schedule_rescan_periodic_events(); |
292 | 0 | control_event_signal(sig); |
293 | 0 | break; |
294 | 0 | } |
295 | 0 | } |
296 | | |
297 | | #ifdef _WIN32 |
298 | | /** Activate SIGINT on receiving a control signal in console. */ |
299 | | static BOOL WINAPI |
300 | | process_win32_console_ctrl(DWORD ctrl_type) |
301 | | { |
302 | | /* Ignore type of the ctrl signal */ |
303 | | (void) ctrl_type; |
304 | | |
305 | | activate_signal(SIGINT); |
306 | | return TRUE; |
307 | | } |
308 | | #endif /* defined(_WIN32) */ |
309 | | |
310 | | /** |
311 | | * Write current memory usage information to the log. |
312 | | */ |
313 | | static void |
314 | | dumpmemusage(int severity) |
315 | 0 | { |
316 | 0 | connection_dump_buffer_mem_stats(severity); |
317 | 0 | tor_log(severity, LD_GENERAL, "In rephist: %"PRIu64" used by %d Tors.", |
318 | 0 | (rephist_total_alloc), rephist_total_num); |
319 | 0 | dump_routerlist_mem_usage(severity); |
320 | 0 | dump_cell_pool_usage(severity); |
321 | 0 | dump_dns_mem_usage(severity); |
322 | 0 | } |
323 | | |
324 | | /** Write all statistics to the log, with log level <b>severity</b>. Called |
325 | | * in response to a SIGUSR1. */ |
326 | | static void |
327 | | dumpstats(int severity) |
328 | 0 | { |
329 | 0 | time_t now = time(NULL); |
330 | 0 | time_t elapsed; |
331 | 0 | size_t rbuf_cap, wbuf_cap, rbuf_len, wbuf_len; |
332 | |
|
333 | 0 | tor_log(severity, LD_GENERAL, "Dumping stats:"); |
334 | |
|
335 | 0 | SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { |
336 | 0 | int i = conn_sl_idx; |
337 | 0 | tor_log(severity, LD_GENERAL, |
338 | 0 | "Conn %d (socket %d) is a %s, created %d secs ago", |
339 | 0 | i, (int)conn->s, |
340 | 0 | connection_describe(conn), |
341 | 0 | (int)(now - conn->timestamp_created)); |
342 | 0 | if (!connection_is_listener(conn)) { |
343 | 0 | tor_log(severity,LD_GENERAL, |
344 | 0 | "Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)", |
345 | 0 | i, |
346 | 0 | (int)connection_get_inbuf_len(conn), |
347 | 0 | (int)buf_allocation(conn->inbuf), |
348 | 0 | (int)(now - conn->timestamp_last_read_allowed)); |
349 | 0 | tor_log(severity,LD_GENERAL, |
350 | 0 | "Conn %d: %d bytes waiting on outbuf " |
351 | 0 | "(len %d, last written %d secs ago)",i, |
352 | 0 | (int)connection_get_outbuf_len(conn), |
353 | 0 | (int)buf_allocation(conn->outbuf), |
354 | 0 | (int)(now - conn->timestamp_last_write_allowed)); |
355 | 0 | if (conn->type == CONN_TYPE_OR) { |
356 | 0 | or_connection_t *or_conn = TO_OR_CONN(conn); |
357 | 0 | if (or_conn->tls) { |
358 | 0 | if (tor_tls_get_buffer_sizes(or_conn->tls, &rbuf_cap, &rbuf_len, |
359 | 0 | &wbuf_cap, &wbuf_len) == 0) { |
360 | 0 | tor_log(severity, LD_GENERAL, |
361 | 0 | "Conn %d: %d/%d bytes used on OpenSSL read buffer; " |
362 | 0 | "%d/%d bytes used on write buffer.", |
363 | 0 | i, (int)rbuf_len, (int)rbuf_cap, (int)wbuf_len, (int)wbuf_cap); |
364 | 0 | } |
365 | 0 | } |
366 | 0 | } |
367 | 0 | } |
368 | 0 | circuit_dump_by_conn(conn, severity); /* dump info about all the circuits |
369 | | * using this conn */ |
370 | 0 | } SMARTLIST_FOREACH_END(conn); |
371 | |
|
372 | 0 | channel_dumpstats(severity); |
373 | 0 | channel_listener_dumpstats(severity); |
374 | |
|
375 | 0 | tor_log(severity, LD_NET, |
376 | 0 | "Cells processed: %"PRIu64" padding\n" |
377 | 0 | " %"PRIu64" create\n" |
378 | 0 | " %"PRIu64" created\n" |
379 | 0 | " %"PRIu64" relay\n" |
380 | 0 | " (%"PRIu64" relayed)\n" |
381 | 0 | " (%"PRIu64" delivered)\n" |
382 | 0 | " %"PRIu64" destroy", |
383 | 0 | (stats_n_padding_cells_processed), |
384 | 0 | (stats_n_create_cells_processed), |
385 | 0 | (stats_n_created_cells_processed), |
386 | 0 | (stats_n_relay_cells_processed), |
387 | 0 | (stats_n_relay_cells_relayed), |
388 | 0 | (stats_n_relay_cells_delivered), |
389 | 0 | (stats_n_destroy_cells_processed)); |
390 | 0 | if (stats_n_data_cells_packaged) |
391 | 0 | tor_log(severity,LD_NET,"Average packaged cell fullness: %2.3f%%", |
392 | 0 | 100*(((double)stats_n_data_bytes_packaged) / |
393 | 0 | ((double)stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE)) ); |
394 | 0 | if (stats_n_data_cells_received) |
395 | 0 | tor_log(severity,LD_NET,"Average delivered cell fullness: %2.3f%%", |
396 | 0 | 100*(((double)stats_n_data_bytes_received) / |
397 | 0 | ((double)stats_n_data_cells_received*RELAY_PAYLOAD_SIZE)) ); |
398 | |
|
399 | 0 | cpuworker_log_onionskin_overhead(severity, ONION_HANDSHAKE_TYPE_TAP, "TAP"); |
400 | 0 | cpuworker_log_onionskin_overhead(severity, ONION_HANDSHAKE_TYPE_NTOR,"ntor"); |
401 | |
|
402 | 0 | if (now - time_of_process_start >= 0) |
403 | 0 | elapsed = now - time_of_process_start; |
404 | 0 | else |
405 | 0 | elapsed = 0; |
406 | |
|
407 | 0 | if (elapsed) { |
408 | 0 | tor_log(severity, LD_NET, |
409 | 0 | "Average bandwidth: %"PRIu64"/%d = %d bytes/sec reading", |
410 | 0 | (get_bytes_read()), |
411 | 0 | (int)elapsed, |
412 | 0 | (int) (get_bytes_read()/elapsed)); |
413 | 0 | tor_log(severity, LD_NET, |
414 | 0 | "Average bandwidth: %"PRIu64"/%d = %d bytes/sec writing", |
415 | 0 | (get_bytes_written()), |
416 | 0 | (int)elapsed, |
417 | 0 | (int) (get_bytes_written()/elapsed)); |
418 | 0 | } |
419 | |
|
420 | 0 | tor_log(severity, LD_NET, "--------------- Dumping memory information:"); |
421 | 0 | dumpmemusage(severity); |
422 | |
|
423 | 0 | rep_hist_dump_stats(now,severity); |
424 | 0 | hs_service_dump_stats(severity); |
425 | 0 | } |
426 | | |
427 | | #ifdef _WIN32 |
428 | | #define UNIX_ONLY 0 |
429 | | #else |
430 | | #define UNIX_ONLY 1 |
431 | | #endif |
432 | | |
433 | | static struct { |
434 | | /** A numeric code for this signal. Must match the signal value if |
435 | | * try_to_register is true. */ |
436 | | int signal_value; |
437 | | /** True if we should try to register this signal with libevent and catch |
438 | | * corresponding posix signals. False otherwise. */ |
439 | | int try_to_register; |
440 | | /** Pointer to hold the event object constructed for this signal. */ |
441 | | struct event *signal_event; |
442 | | } signal_handlers[] = { |
443 | | #ifdef SIGINT |
444 | | { SIGINT, UNIX_ONLY, NULL }, /* do a controlled slow shutdown */ |
445 | | #endif |
446 | | #ifdef SIGTERM |
447 | | { SIGTERM, UNIX_ONLY, NULL }, /* to terminate now */ |
448 | | #endif |
449 | | #ifdef SIGPIPE |
450 | | { SIGPIPE, UNIX_ONLY, NULL }, /* otherwise SIGPIPE kills us */ |
451 | | #endif |
452 | | #ifdef SIGUSR1 |
453 | | { SIGUSR1, UNIX_ONLY, NULL }, /* dump stats */ |
454 | | #endif |
455 | | #ifdef SIGUSR2 |
456 | | { SIGUSR2, UNIX_ONLY, NULL }, /* go to loglevel debug */ |
457 | | #endif |
458 | | #ifdef SIGHUP |
459 | | { SIGHUP, UNIX_ONLY, NULL }, /* to reload config, retry conns, etc */ |
460 | | #endif |
461 | | #ifdef SIGXFSZ |
462 | | { SIGXFSZ, UNIX_ONLY, NULL }, /* handle file-too-big resource exhaustion */ |
463 | | #endif |
464 | | #ifdef SIGCHLD |
465 | | { SIGCHLD, UNIX_ONLY, NULL }, /* handle dns/cpu workers that exit */ |
466 | | #endif |
467 | | /* These are controller-only */ |
468 | | { SIGNEWNYM, 0, NULL }, |
469 | | { SIGCLEARDNSCACHE, 0, NULL }, |
470 | | { SIGHEARTBEAT, 0, NULL }, |
471 | | { SIGACTIVE, 0, NULL }, |
472 | | { SIGDORMANT, 0, NULL }, |
473 | | { -1, -1, NULL } |
474 | | }; |
475 | | |
476 | | /** Set up the signal handler events for this process, and register them |
477 | | * with libevent if appropriate. */ |
478 | | void |
479 | | handle_signals(void) |
480 | 0 | { |
481 | 0 | int i; |
482 | 0 | const int enabled = !get_options()->DisableSignalHandlers; |
483 | |
|
484 | 0 | for (i = 0; signal_handlers[i].signal_value >= 0; ++i) { |
485 | | /* Signal handlers are only registered with libevent if they need to catch |
486 | | * real POSIX signals. We construct these signal handler events in either |
487 | | * case, though, so that controllers can activate them with the SIGNAL |
488 | | * command. |
489 | | */ |
490 | 0 | if (enabled && signal_handlers[i].try_to_register) { |
491 | 0 | signal_handlers[i].signal_event = |
492 | 0 | tor_evsignal_new(tor_libevent_get_base(), |
493 | 0 | signal_handlers[i].signal_value, |
494 | 0 | signal_callback, |
495 | 0 | &signal_handlers[i].signal_value); |
496 | 0 | if (event_add(signal_handlers[i].signal_event, NULL)) |
497 | 0 | log_warn(LD_BUG, "Error from libevent when adding " |
498 | 0 | "event for signal %d", |
499 | 0 | signal_handlers[i].signal_value); |
500 | 0 | } else { |
501 | 0 | signal_handlers[i].signal_event = |
502 | 0 | tor_event_new(tor_libevent_get_base(), -1, |
503 | 0 | EV_SIGNAL, signal_callback, |
504 | 0 | &signal_handlers[i].signal_value); |
505 | 0 | } |
506 | 0 | } |
507 | |
|
508 | | #ifdef _WIN32 |
509 | | /* Windows lacks traditional POSIX signals but WinAPI provides a function |
510 | | * to handle control signals like Ctrl+C in the console, we can use this to |
511 | | * simulate the SIGINT signal */ |
512 | | if (enabled) SetConsoleCtrlHandler(process_win32_console_ctrl, TRUE); |
513 | | #endif /* defined(_WIN32) */ |
514 | 0 | } |
515 | | |
516 | | /* Cause the signal handler for signal_num to be called in the event loop. */ |
517 | | void |
518 | | activate_signal(int signal_num) |
519 | 0 | { |
520 | 0 | int i; |
521 | 0 | for (i = 0; signal_handlers[i].signal_value >= 0; ++i) { |
522 | 0 | if (signal_handlers[i].signal_value == signal_num) { |
523 | 0 | event_active(signal_handlers[i].signal_event, EV_SIGNAL, 1); |
524 | 0 | return; |
525 | 0 | } |
526 | 0 | } |
527 | 0 | } |
528 | | |
529 | | /** Main entry point for the Tor command-line client. Return 0 on "success", |
530 | | * negative on "failure", and positive on "success and exit". |
531 | | */ |
532 | | int |
533 | | tor_init(int argc, char *argv[]) |
534 | 0 | { |
535 | 0 | char progname[256]; |
536 | 0 | quiet_level_t quiet = QUIET_NONE; |
537 | 0 | bool running_tor = false; |
538 | |
|
539 | 0 | time_of_process_start = time(NULL); |
540 | 0 | tor_init_connection_lists(); |
541 | | /* Have the log set up with our application name. */ |
542 | 0 | tor_snprintf(progname, sizeof(progname), "Tor %s", get_version()); |
543 | 0 | log_set_application_name(progname); |
544 | | |
545 | | /* Initialize the history structures. */ |
546 | 0 | rep_hist_init(); |
547 | 0 | bwhist_init(); |
548 | | /* Initialize the service cache. */ |
549 | 0 | addressmap_init(); /* Init the client dns cache. Do it always, since it's |
550 | | * cheap. */ |
551 | | |
552 | | /* Initialize the HS subsystem. */ |
553 | 0 | hs_init(); |
554 | |
|
555 | 0 | { |
556 | | /* We check for the "quiet"/"hush" settings first, since they decide |
557 | | whether we log anything at all to stdout. */ |
558 | 0 | parsed_cmdline_t *cmdline; |
559 | 0 | cmdline = config_parse_commandline(argc, argv, 1); |
560 | 0 | if (cmdline) { |
561 | 0 | quiet = cmdline->quiet_level; |
562 | 0 | running_tor = (cmdline->command == CMD_RUN_TOR); |
563 | 0 | } |
564 | 0 | parsed_cmdline_free(cmdline); |
565 | 0 | } |
566 | | |
567 | | /* give it somewhere to log to initially */ |
568 | 0 | add_default_log_for_quiet_level(quiet); |
569 | 0 | quiet_level = quiet; |
570 | |
|
571 | 0 | { |
572 | 0 | const char *version = get_version(); |
573 | |
|
574 | 0 | log_notice(LD_GENERAL, "Tor %s running on %s with Libevent %s, " |
575 | 0 | "%s %s, Zlib %s, Liblzma %s, Libzstd %s and %s %s as libc.", |
576 | 0 | version, |
577 | 0 | get_uname(), |
578 | 0 | tor_libevent_get_version_str(), |
579 | 0 | crypto_get_library_name(), |
580 | 0 | crypto_get_library_version_string(), |
581 | 0 | tor_compress_supports_method(ZLIB_METHOD) ? |
582 | 0 | tor_compress_version_str(ZLIB_METHOD) : "N/A", |
583 | 0 | tor_compress_supports_method(LZMA_METHOD) ? |
584 | 0 | tor_compress_version_str(LZMA_METHOD) : "N/A", |
585 | 0 | tor_compress_supports_method(ZSTD_METHOD) ? |
586 | 0 | tor_compress_version_str(ZSTD_METHOD) : "N/A", |
587 | 0 | tor_libc_get_name() ? |
588 | 0 | tor_libc_get_name() : "Unknown", |
589 | 0 | tor_libc_get_version_str()); |
590 | |
|
591 | 0 | log_notice(LD_GENERAL, "Tor can't help you if you use it wrong! " |
592 | 0 | "Learn how to be safe at " |
593 | 0 | "https://support.torproject.org/faq/staying-anonymous/"); |
594 | |
|
595 | 0 | if (strstr(version, "alpha") || strstr(version, "beta")) |
596 | 0 | log_notice(LD_GENERAL, "This version is not a stable Tor release. " |
597 | 0 | "Expect more bugs than usual."); |
598 | |
|
599 | 0 | if (strlen(risky_option_list) && running_tor) { |
600 | 0 | log_warn(LD_GENERAL, "This build of Tor has been compiled with one " |
601 | 0 | "or more options that might make it less reliable or secure! " |
602 | 0 | "They are:%s", risky_option_list); |
603 | 0 | } |
604 | |
|
605 | 0 | tor_compress_log_init_warnings(); |
606 | 0 | } |
607 | | |
608 | | /* Warn _if_ the tracing subsystem is built in. */ |
609 | 0 | tracing_log_warning(); |
610 | |
|
611 | 0 | int init_rv = options_init_from_torrc(argc,argv); |
612 | 0 | if (init_rv < 0) { |
613 | 0 | log_err(LD_CONFIG,"Reading config failed--see warnings above."); |
614 | 0 | return -1; |
615 | 0 | } else if (init_rv > 0) { |
616 | | // We succeeded, and should exit anyway -- probably the user just said |
617 | | // "--version" or something like that. |
618 | 0 | return 1; |
619 | 0 | } |
620 | | |
621 | | /* Initialize channelpadding and circpad parameters to defaults |
622 | | * until we get a consensus */ |
623 | 0 | channelpadding_new_consensus_params(NULL); |
624 | 0 | circpad_new_consensus_params(NULL); |
625 | 0 | congestion_control_new_consensus_params(NULL); |
626 | 0 | flow_control_new_consensus_params(NULL); |
627 | | |
628 | | /* Initialize circuit padding to defaults+torrc until we get a consensus */ |
629 | 0 | circpad_machines_init(); |
630 | | |
631 | | /* Initialize hidden service DoS subsystem. We need to do this once the |
632 | | * configuration object has been set because it can be accessed. */ |
633 | 0 | hs_dos_init(); |
634 | | |
635 | | /* Initialize predicted ports list after loading options */ |
636 | 0 | predicted_ports_init(); |
637 | |
|
638 | 0 | #ifndef _WIN32 |
639 | 0 | if (geteuid()==0) |
640 | 0 | log_warn(LD_GENERAL,"You are running Tor as root. You don't need to, " |
641 | 0 | "and you probably shouldn't."); |
642 | 0 | #endif |
643 | | |
644 | | /* Scan/clean unparseable descriptors; after reading config */ |
645 | 0 | routerparse_init(); |
646 | |
|
647 | 0 | return 0; |
648 | 0 | } |
649 | | |
650 | | /** A lockfile structure, used to prevent two Tors from messing with the |
651 | | * data directory at once. If this variable is non-NULL, we're holding |
652 | | * the lockfile. */ |
653 | | static tor_lockfile_t *lockfile = NULL; |
654 | | |
655 | | /** Try to grab the lock file described in <b>options</b>, if we do not |
656 | | * already have it. If <b>err_if_locked</b> is true, warn if somebody else is |
657 | | * holding the lock, and exit if we can't get it after waiting. Otherwise, |
658 | | * return -1 if we can't get the lockfile. Return 0 on success. |
659 | | */ |
660 | | int |
661 | | try_locking(const or_options_t *options, int err_if_locked) |
662 | 0 | { |
663 | 0 | if (lockfile) |
664 | 0 | return 0; |
665 | 0 | else { |
666 | 0 | char *fname = options_get_datadir_fname(options, "lock"); |
667 | 0 | int already_locked = 0; |
668 | 0 | tor_lockfile_t *lf = tor_lockfile_lock(fname, 0, &already_locked); |
669 | 0 | tor_free(fname); |
670 | 0 | if (!lf) { |
671 | 0 | if (err_if_locked && already_locked) { |
672 | 0 | int r; |
673 | 0 | log_warn(LD_GENERAL, "It looks like another Tor process is running " |
674 | 0 | "with the same data directory. Waiting 5 seconds to see " |
675 | 0 | "if it goes away."); |
676 | 0 | #ifndef _WIN32 |
677 | 0 | sleep(5); |
678 | | #else |
679 | | Sleep(5000); |
680 | | #endif |
681 | 0 | r = try_locking(options, 0); |
682 | 0 | if (r<0) { |
683 | 0 | log_err(LD_GENERAL, "No, it's still there. Exiting."); |
684 | 0 | return -1; |
685 | 0 | } |
686 | 0 | return r; |
687 | 0 | } |
688 | 0 | return -1; |
689 | 0 | } |
690 | 0 | lockfile = lf; |
691 | 0 | return 0; |
692 | 0 | } |
693 | 0 | } |
694 | | |
695 | | /** Return true iff we've successfully acquired the lock file. */ |
696 | | int |
697 | | have_lockfile(void) |
698 | 0 | { |
699 | 0 | return lockfile != NULL; |
700 | 0 | } |
701 | | |
702 | | /** If we have successfully acquired the lock file, release it. */ |
703 | | void |
704 | | release_lockfile(void) |
705 | 0 | { |
706 | 0 | if (lockfile) { |
707 | 0 | tor_lockfile_unlock(lockfile); |
708 | 0 | lockfile = NULL; |
709 | 0 | } |
710 | 0 | } |
711 | | |
712 | | /** |
713 | | * Remove the specified file, and log a warning if the operation fails for |
714 | | * any reason other than the file not existing. Ignores NULL filenames. |
715 | | */ |
716 | | void |
717 | | tor_remove_file(const char *filename) |
718 | 0 | { |
719 | 0 | if (filename && tor_unlink(filename) != 0 && errno != ENOENT) { |
720 | 0 | log_warn(LD_FS, "Couldn't unlink %s: %s", |
721 | 0 | filename, strerror(errno)); |
722 | 0 | } |
723 | 0 | } |
724 | | |
725 | | /** Read/create keys as needed, and echo our fingerprint to stdout. */ |
726 | | static int |
727 | | do_list_fingerprint(void) |
728 | 0 | { |
729 | 0 | const or_options_t *options = get_options(); |
730 | 0 | const char *arg = options->command_arg; |
731 | 0 | char rsa[FINGERPRINT_LEN + 1]; |
732 | 0 | crypto_pk_t *k; |
733 | 0 | const ed25519_public_key_t *edkey; |
734 | 0 | const char *nickname = options->Nickname; |
735 | 0 | sandbox_disable_getaddrinfo_cache(); |
736 | |
|
737 | 0 | bool show_rsa = !strcmp(arg, "") || !strcmp(arg, "rsa"); |
738 | 0 | bool show_ed25519 = !strcmp(arg, "ed25519"); |
739 | 0 | if (!show_rsa && !show_ed25519) { |
740 | 0 | log_err(LD_GENERAL, |
741 | 0 | "If you give a key type, you must specify 'rsa' or 'ed25519'. Exiting."); |
742 | 0 | return -1; |
743 | 0 | } |
744 | | |
745 | 0 | if (!server_mode(options)) { |
746 | 0 | log_err(LD_GENERAL, |
747 | 0 | "Clients don't have long-term identity keys. Exiting."); |
748 | 0 | return -1; |
749 | 0 | } |
750 | 0 | tor_assert(nickname); |
751 | 0 | if (init_keys() < 0) { |
752 | 0 | log_err(LD_GENERAL, "Error initializing keys; exiting."); |
753 | 0 | return -1; |
754 | 0 | } |
755 | 0 | if (!(k = get_server_identity_key())) { |
756 | 0 | log_err(LD_GENERAL, "Error: missing RSA identity key."); |
757 | 0 | return -1; |
758 | 0 | } |
759 | 0 | if (crypto_pk_get_fingerprint(k, rsa, 1) < 0) { |
760 | 0 | log_err(LD_BUG, "Error computing RSA fingerprint"); |
761 | 0 | return -1; |
762 | 0 | } |
763 | 0 | if (!(edkey = get_master_identity_key())) { |
764 | 0 | log_err(LD_GENERAL,"Error: missing ed25519 identity key."); |
765 | 0 | return -1; |
766 | 0 | } |
767 | 0 | if (show_rsa) { |
768 | 0 | printf("%s %s\n", nickname, rsa); |
769 | 0 | } |
770 | 0 | if (show_ed25519) { |
771 | 0 | char ed25519[ED25519_BASE64_LEN + 1]; |
772 | 0 | digest256_to_base64(ed25519, (const char *) edkey->pubkey); |
773 | 0 | printf("%s %s\n", nickname, ed25519); |
774 | 0 | } |
775 | 0 | return 0; |
776 | 0 | } |
777 | | |
778 | | /** Entry point for password hashing: take the desired password from |
779 | | * the command line, and print its salted hash to stdout. **/ |
780 | | static void |
781 | | do_hash_password(void) |
782 | 0 | { |
783 | |
|
784 | 0 | char output[256]; |
785 | 0 | char key[S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN]; |
786 | |
|
787 | 0 | crypto_rand(key, S2K_RFC2440_SPECIFIER_LEN-1); |
788 | 0 | key[S2K_RFC2440_SPECIFIER_LEN-1] = (uint8_t)96; /* Hash 64 K of data. */ |
789 | 0 | secret_to_key_rfc2440(key+S2K_RFC2440_SPECIFIER_LEN, DIGEST_LEN, |
790 | 0 | get_options()->command_arg, strlen(get_options()->command_arg), |
791 | 0 | key); |
792 | 0 | base16_encode(output, sizeof(output), key, sizeof(key)); |
793 | 0 | printf("16:%s\n",output); |
794 | 0 | } |
795 | | |
796 | | /** Entry point for configuration dumping: write the configuration to |
797 | | * stdout. */ |
798 | | static int |
799 | | do_dump_config(void) |
800 | 0 | { |
801 | 0 | const or_options_t *options = get_options(); |
802 | 0 | const char *arg = options->command_arg; |
803 | 0 | int how; |
804 | 0 | char *opts; |
805 | |
|
806 | 0 | if (!strcmp(arg, "short")) { |
807 | 0 | how = OPTIONS_DUMP_MINIMAL; |
808 | 0 | } else if (!strcmp(arg, "non-builtin")) { |
809 | | // Deprecated since 0.4.5.1-alpha. |
810 | 0 | fprintf(stderr, "'non-builtin' is deprecated; use 'short' instead.\n"); |
811 | 0 | how = OPTIONS_DUMP_MINIMAL; |
812 | 0 | } else if (!strcmp(arg, "full")) { |
813 | 0 | how = OPTIONS_DUMP_ALL; |
814 | 0 | } else { |
815 | 0 | fprintf(stderr, "No valid argument to --dump-config found!\n"); |
816 | 0 | fprintf(stderr, "Please select 'short' or 'full'.\n"); |
817 | |
|
818 | 0 | return -1; |
819 | 0 | } |
820 | | |
821 | 0 | opts = options_dump(options, how); |
822 | 0 | printf("%s", opts); |
823 | 0 | tor_free(opts); |
824 | |
|
825 | 0 | return 0; |
826 | 0 | } |
827 | | |
828 | | static void |
829 | | init_addrinfo(void) |
830 | 0 | { |
831 | 0 | if (! server_mode(get_options()) || get_options()->Address) { |
832 | | /* We don't need to seed our own hostname, because we won't be calling |
833 | | * resolve_my_address on it. |
834 | | */ |
835 | 0 | return; |
836 | 0 | } |
837 | 0 | char hname[256]; |
838 | | |
839 | | // host name to sandbox |
840 | 0 | gethostname(hname, sizeof(hname)); |
841 | 0 | tor_add_addrinfo(hname); |
842 | 0 | } |
843 | | |
844 | | static sandbox_cfg_t* |
845 | | sandbox_init_filter(void) |
846 | 0 | { |
847 | 0 | const or_options_t *options = get_options(); |
848 | 0 | sandbox_cfg_t *cfg = sandbox_cfg_new(); |
849 | |
|
850 | 0 | sandbox_cfg_allow_openat_filename(&cfg, |
851 | 0 | get_cachedir_fname("cached-status")); |
852 | |
|
853 | 0 | #define OPEN(name) \ |
854 | 0 | sandbox_cfg_allow_open_filename(&cfg, tor_strdup(name)) |
855 | |
|
856 | 0 | #define OPENDIR(dir) \ |
857 | 0 | sandbox_cfg_allow_opendir_dirname(&cfg, tor_strdup(dir)) |
858 | |
|
859 | 0 | #define OPEN_DATADIR(name) \ |
860 | 0 | sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname(name)) |
861 | |
|
862 | 0 | #define OPEN_DATADIR2(name, name2) \ |
863 | 0 | sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname2((name), (name2))) |
864 | |
|
865 | 0 | #define OPEN_DATADIR_SUFFIX(name, suffix) do { \ |
866 | 0 | OPEN_DATADIR(name); \ |
867 | 0 | OPEN_DATADIR(name suffix); \ |
868 | 0 | } while (0) |
869 | |
|
870 | 0 | #define OPEN_DATADIR2_SUFFIX(name, name2, suffix) do { \ |
871 | 0 | OPEN_DATADIR2(name, name2); \ |
872 | 0 | OPEN_DATADIR2(name, name2 suffix); \ |
873 | 0 | } while (0) |
874 | | |
875 | | // KeyDirectory is a directory, but it is only opened in check_private_dir |
876 | | // which calls open instead of opendir |
877 | 0 | #define OPEN_KEY_DIRECTORY() \ |
878 | 0 | OPEN(options->KeyDirectory) |
879 | 0 | #define OPEN_CACHEDIR(name) \ |
880 | 0 | sandbox_cfg_allow_open_filename(&cfg, get_cachedir_fname(name)) |
881 | 0 | #define OPEN_CACHEDIR_SUFFIX(name, suffix) do { \ |
882 | 0 | OPEN_CACHEDIR(name); \ |
883 | 0 | OPEN_CACHEDIR(name suffix); \ |
884 | 0 | } while (0) |
885 | 0 | #define OPEN_KEYDIR(name) \ |
886 | 0 | sandbox_cfg_allow_open_filename(&cfg, get_keydir_fname(name)) |
887 | 0 | #define OPEN_KEYDIR_SUFFIX(name, suffix) do { \ |
888 | 0 | OPEN_KEYDIR(name); \ |
889 | 0 | OPEN_KEYDIR(name suffix); \ |
890 | 0 | } while (0) |
891 | | |
892 | | // DataDirectory is a directory, but it is only opened in check_private_dir |
893 | | // which calls open instead of opendir |
894 | 0 | OPEN(options->DataDirectory); |
895 | 0 | OPEN_KEY_DIRECTORY(); |
896 | |
|
897 | 0 | OPEN_CACHEDIR_SUFFIX("cached-certs", ".tmp"); |
898 | 0 | OPEN_CACHEDIR_SUFFIX("cached-consensus", ".tmp"); |
899 | 0 | OPEN_CACHEDIR_SUFFIX("unverified-consensus", ".tmp"); |
900 | 0 | OPEN_CACHEDIR_SUFFIX("unverified-microdesc-consensus", ".tmp"); |
901 | 0 | OPEN_CACHEDIR_SUFFIX("cached-microdesc-consensus", ".tmp"); |
902 | 0 | OPEN_CACHEDIR_SUFFIX("cached-microdescs", ".tmp"); |
903 | 0 | OPEN_CACHEDIR_SUFFIX("cached-microdescs.new", ".tmp"); |
904 | 0 | OPEN_CACHEDIR_SUFFIX("cached-descriptors", ".tmp"); |
905 | 0 | OPEN_CACHEDIR_SUFFIX("cached-descriptors.new", ".tmp"); |
906 | 0 | OPEN_CACHEDIR("cached-descriptors.tmp.tmp"); |
907 | 0 | OPEN_CACHEDIR_SUFFIX("cached-extrainfo", ".tmp"); |
908 | 0 | OPEN_CACHEDIR_SUFFIX("cached-extrainfo.new", ".tmp"); |
909 | 0 | OPEN_CACHEDIR("cached-extrainfo.tmp.tmp"); |
910 | |
|
911 | 0 | OPEN_DATADIR_SUFFIX("state", ".tmp"); |
912 | 0 | OPEN_DATADIR_SUFFIX("sr-state", ".tmp"); |
913 | 0 | OPEN_DATADIR_SUFFIX("unparseable-desc", ".tmp"); |
914 | 0 | OPEN_DATADIR_SUFFIX("v3-status-votes", ".tmp"); |
915 | 0 | OPEN_DATADIR("key-pinning-journal"); |
916 | 0 | OPEN("/dev/srandom"); |
917 | 0 | OPEN("/dev/urandom"); |
918 | 0 | OPEN("/dev/random"); |
919 | 0 | OPEN("/etc/hosts"); |
920 | 0 | OPEN("/proc/meminfo"); |
921 | |
|
922 | 0 | if (options->BridgeAuthoritativeDir) |
923 | 0 | OPEN_DATADIR_SUFFIX("networkstatus-bridges", ".tmp"); |
924 | |
|
925 | 0 | if (authdir_mode(options)) { |
926 | 0 | OPEN_DATADIR("approved-routers"); |
927 | 0 | OPEN_DATADIR_SUFFIX("my-consensus-microdesc", ".tmp"); |
928 | 0 | OPEN_DATADIR_SUFFIX("my-consensus-ns", ".tmp"); |
929 | 0 | } |
930 | |
|
931 | 0 | if (options->ServerDNSResolvConfFile) |
932 | 0 | sandbox_cfg_allow_open_filename(&cfg, |
933 | 0 | tor_strdup(options->ServerDNSResolvConfFile)); |
934 | 0 | else |
935 | 0 | sandbox_cfg_allow_open_filename(&cfg, tor_strdup("/etc/resolv.conf")); |
936 | |
|
937 | 0 | const char *torrc_defaults_fname = get_torrc_fname(1); |
938 | 0 | if (torrc_defaults_fname) { |
939 | 0 | sandbox_cfg_allow_open_filename(&cfg, tor_strdup(torrc_defaults_fname)); |
940 | 0 | } |
941 | 0 | const char *torrc_fname = get_torrc_fname(0); |
942 | 0 | if (torrc_fname) { |
943 | 0 | sandbox_cfg_allow_open_filename(&cfg, tor_strdup(torrc_fname)); |
944 | | // allow torrc backup and torrc.tmp to make SAVECONF work |
945 | 0 | char *torrc_bck = NULL; |
946 | 0 | tor_asprintf(&torrc_bck, CONFIG_BACKUP_PATTERN, torrc_fname); |
947 | 0 | sandbox_cfg_allow_rename(&cfg, tor_strdup(torrc_fname), torrc_bck); |
948 | 0 | char *torrc_tmp = NULL; |
949 | 0 | tor_asprintf(&torrc_tmp, "%s.tmp", torrc_fname); |
950 | 0 | sandbox_cfg_allow_rename(&cfg, torrc_tmp, tor_strdup(torrc_fname)); |
951 | 0 | sandbox_cfg_allow_open_filename(&cfg, tor_strdup(torrc_tmp)); |
952 | | // we need to stat the existing backup file |
953 | 0 | sandbox_cfg_allow_stat_filename(&cfg, tor_strdup(torrc_bck)); |
954 | 0 | } |
955 | |
|
956 | 0 | SMARTLIST_FOREACH(options->FilesOpenedByIncludes, char *, f, { |
957 | 0 | if (file_status(f) == FN_DIR) { |
958 | 0 | OPENDIR(f); |
959 | 0 | } else { |
960 | 0 | OPEN(f); |
961 | 0 | } |
962 | 0 | }); |
963 | |
|
964 | 0 | #define RENAME_SUFFIX(name, suffix) \ |
965 | 0 | sandbox_cfg_allow_rename(&cfg, \ |
966 | 0 | get_datadir_fname(name suffix), \ |
967 | 0 | get_datadir_fname(name)) |
968 | |
|
969 | 0 | #define RENAME_SUFFIX2(prefix, name, suffix) \ |
970 | 0 | sandbox_cfg_allow_rename(&cfg, \ |
971 | 0 | get_datadir_fname2(prefix, name suffix), \ |
972 | 0 | get_datadir_fname2(prefix, name)) |
973 | |
|
974 | 0 | #define RENAME_CACHEDIR_SUFFIX(name, suffix) \ |
975 | 0 | sandbox_cfg_allow_rename(&cfg, \ |
976 | 0 | get_cachedir_fname(name suffix), \ |
977 | 0 | get_cachedir_fname(name)) |
978 | |
|
979 | 0 | #define RENAME_KEYDIR_SUFFIX(name, suffix) \ |
980 | 0 | sandbox_cfg_allow_rename(&cfg, \ |
981 | 0 | get_keydir_fname(name suffix), \ |
982 | 0 | get_keydir_fname(name)) |
983 | |
|
984 | 0 | RENAME_CACHEDIR_SUFFIX("cached-certs", ".tmp"); |
985 | 0 | RENAME_CACHEDIR_SUFFIX("cached-consensus", ".tmp"); |
986 | 0 | RENAME_CACHEDIR_SUFFIX("unverified-consensus", ".tmp"); |
987 | 0 | RENAME_CACHEDIR_SUFFIX("unverified-microdesc-consensus", ".tmp"); |
988 | 0 | RENAME_CACHEDIR_SUFFIX("cached-microdesc-consensus", ".tmp"); |
989 | 0 | RENAME_CACHEDIR_SUFFIX("cached-microdescs", ".tmp"); |
990 | 0 | RENAME_CACHEDIR_SUFFIX("cached-microdescs", ".new"); |
991 | 0 | RENAME_CACHEDIR_SUFFIX("cached-microdescs.new", ".tmp"); |
992 | 0 | RENAME_CACHEDIR_SUFFIX("cached-descriptors", ".tmp"); |
993 | 0 | RENAME_CACHEDIR_SUFFIX("cached-descriptors", ".new"); |
994 | 0 | RENAME_CACHEDIR_SUFFIX("cached-descriptors.new", ".tmp"); |
995 | 0 | RENAME_CACHEDIR_SUFFIX("cached-extrainfo", ".tmp"); |
996 | 0 | RENAME_CACHEDIR_SUFFIX("cached-extrainfo", ".new"); |
997 | 0 | RENAME_CACHEDIR_SUFFIX("cached-extrainfo.new", ".tmp"); |
998 | |
|
999 | 0 | RENAME_SUFFIX("state", ".tmp"); |
1000 | 0 | RENAME_SUFFIX("sr-state", ".tmp"); |
1001 | 0 | RENAME_SUFFIX("unparseable-desc", ".tmp"); |
1002 | 0 | RENAME_SUFFIX("v3-status-votes", ".tmp"); |
1003 | |
|
1004 | 0 | if (options->BridgeAuthoritativeDir) |
1005 | 0 | RENAME_SUFFIX("networkstatus-bridges", ".tmp"); |
1006 | |
|
1007 | 0 | if (authdir_mode(options)) { |
1008 | 0 | RENAME_SUFFIX("my-consensus-microdesc", ".tmp"); |
1009 | 0 | RENAME_SUFFIX("my-consensus-ns", ".tmp"); |
1010 | 0 | } |
1011 | |
|
1012 | 0 | #define STAT_DATADIR(name) \ |
1013 | 0 | sandbox_cfg_allow_stat_filename(&cfg, get_datadir_fname(name)) |
1014 | |
|
1015 | 0 | #define STAT_CACHEDIR(name) \ |
1016 | 0 | sandbox_cfg_allow_stat_filename(&cfg, get_cachedir_fname(name)) |
1017 | |
|
1018 | 0 | #define STAT_DATADIR2(name, name2) \ |
1019 | 0 | sandbox_cfg_allow_stat_filename(&cfg, get_datadir_fname2((name), (name2))) |
1020 | |
|
1021 | 0 | #define STAT_KEY_DIRECTORY() \ |
1022 | 0 | sandbox_cfg_allow_stat_filename(&cfg, tor_strdup(options->KeyDirectory)) |
1023 | |
|
1024 | 0 | STAT_DATADIR(NULL); |
1025 | 0 | STAT_DATADIR("lock"); |
1026 | 0 | STAT_DATADIR("state"); |
1027 | 0 | STAT_DATADIR("router-stability"); |
1028 | |
|
1029 | 0 | STAT_CACHEDIR("cached-extrainfo.new"); |
1030 | |
|
1031 | 0 | { |
1032 | 0 | smartlist_t *files = smartlist_new(); |
1033 | 0 | tor_log_get_logfile_names(files); |
1034 | 0 | SMARTLIST_FOREACH(files, char *, file_name, { |
1035 | | /* steals reference */ |
1036 | 0 | sandbox_cfg_allow_open_filename(&cfg, file_name); |
1037 | 0 | }); |
1038 | 0 | smartlist_free(files); |
1039 | 0 | } |
1040 | |
|
1041 | 0 | { |
1042 | 0 | smartlist_t *files = smartlist_new(); |
1043 | 0 | smartlist_t *dirs = smartlist_new(); |
1044 | 0 | hs_service_lists_fnames_for_sandbox(files, dirs); |
1045 | 0 | SMARTLIST_FOREACH(files, char *, file_name, { |
1046 | 0 | char *tmp_name = NULL; |
1047 | 0 | tor_asprintf(&tmp_name, "%s.tmp", file_name); |
1048 | 0 | sandbox_cfg_allow_rename(&cfg, |
1049 | 0 | tor_strdup(tmp_name), tor_strdup(file_name)); |
1050 | | /* steals references */ |
1051 | 0 | sandbox_cfg_allow_open_filename(&cfg, file_name); |
1052 | 0 | sandbox_cfg_allow_open_filename(&cfg, tmp_name); |
1053 | 0 | }); |
1054 | 0 | SMARTLIST_FOREACH(dirs, char *, dir, { |
1055 | | /* steals reference */ |
1056 | 0 | sandbox_cfg_allow_stat_filename(&cfg, dir); |
1057 | 0 | }); |
1058 | 0 | smartlist_free(files); |
1059 | 0 | smartlist_free(dirs); |
1060 | 0 | } |
1061 | |
|
1062 | 0 | { |
1063 | 0 | char *fname; |
1064 | 0 | if ((fname = get_controller_cookie_file_name())) { |
1065 | 0 | sandbox_cfg_allow_open_filename(&cfg, fname); |
1066 | 0 | } |
1067 | 0 | if ((fname = get_ext_or_auth_cookie_file_name())) { |
1068 | 0 | sandbox_cfg_allow_open_filename(&cfg, fname); |
1069 | 0 | } |
1070 | 0 | } |
1071 | |
|
1072 | 0 | SMARTLIST_FOREACH_BEGIN(get_configured_ports(), port_cfg_t *, port) { |
1073 | 0 | if (!port->is_unix_addr) |
1074 | 0 | continue; |
1075 | | /* When we open an AF_UNIX address, we want permission to open the |
1076 | | * directory that holds it. */ |
1077 | 0 | char *dirname = tor_strdup(port->unix_addr); |
1078 | 0 | if (get_parent_directory(dirname) == 0) { |
1079 | 0 | OPENDIR(dirname); |
1080 | 0 | } |
1081 | 0 | tor_free(dirname); |
1082 | 0 | sandbox_cfg_allow_chmod_filename(&cfg, tor_strdup(port->unix_addr)); |
1083 | 0 | sandbox_cfg_allow_chown_filename(&cfg, tor_strdup(port->unix_addr)); |
1084 | 0 | } SMARTLIST_FOREACH_END(port); |
1085 | |
|
1086 | 0 | if (options->DirPortFrontPage) { |
1087 | 0 | sandbox_cfg_allow_open_filename(&cfg, |
1088 | 0 | tor_strdup(options->DirPortFrontPage)); |
1089 | 0 | } |
1090 | | |
1091 | | // orport |
1092 | 0 | if (server_mode(get_options())) { |
1093 | |
|
1094 | 0 | OPEN_KEYDIR_SUFFIX("secret_id_key", ".tmp"); |
1095 | 0 | OPEN_KEYDIR_SUFFIX("secret_onion_key", ".tmp"); |
1096 | 0 | OPEN_KEYDIR_SUFFIX("secret_onion_key_ntor", ".tmp"); |
1097 | 0 | OPEN_KEYDIR("secret_id_key.old"); |
1098 | 0 | OPEN_KEYDIR("secret_onion_key.old"); |
1099 | 0 | OPEN_KEYDIR("secret_onion_key_ntor.old"); |
1100 | |
|
1101 | 0 | OPEN_KEYDIR_SUFFIX("ed25519_master_id_secret_key", ".tmp"); |
1102 | 0 | OPEN_KEYDIR_SUFFIX("ed25519_master_id_secret_key_encrypted", ".tmp"); |
1103 | 0 | OPEN_KEYDIR_SUFFIX("ed25519_master_id_public_key", ".tmp"); |
1104 | 0 | OPEN_KEYDIR_SUFFIX("ed25519_signing_secret_key", ".tmp"); |
1105 | 0 | OPEN_KEYDIR_SUFFIX("ed25519_signing_secret_key_encrypted", ".tmp"); |
1106 | 0 | OPEN_KEYDIR_SUFFIX("ed25519_signing_public_key", ".tmp"); |
1107 | 0 | OPEN_KEYDIR_SUFFIX("ed25519_signing_cert", ".tmp"); |
1108 | |
|
1109 | 0 | OPEN_DATADIR2_SUFFIX("stats", "bridge-stats", ".tmp"); |
1110 | 0 | OPEN_DATADIR2_SUFFIX("stats", "dirreq-stats", ".tmp"); |
1111 | |
|
1112 | 0 | OPEN_DATADIR2_SUFFIX("stats", "entry-stats", ".tmp"); |
1113 | 0 | OPEN_DATADIR2_SUFFIX("stats", "exit-stats", ".tmp"); |
1114 | 0 | OPEN_DATADIR2_SUFFIX("stats", "buffer-stats", ".tmp"); |
1115 | 0 | OPEN_DATADIR2_SUFFIX("stats", "conn-stats", ".tmp"); |
1116 | 0 | OPEN_DATADIR2_SUFFIX("stats", "hidserv-stats", ".tmp"); |
1117 | 0 | OPEN_DATADIR2_SUFFIX("stats", "hidserv-v3-stats", ".tmp"); |
1118 | |
|
1119 | 0 | OPEN_DATADIR("approved-routers"); |
1120 | 0 | OPEN_DATADIR_SUFFIX("fingerprint", ".tmp"); |
1121 | 0 | OPEN_DATADIR_SUFFIX("fingerprint-ed25519", ".tmp"); |
1122 | 0 | OPEN_DATADIR_SUFFIX("hashed-fingerprint", ".tmp"); |
1123 | 0 | OPEN_DATADIR_SUFFIX("router-stability", ".tmp"); |
1124 | |
|
1125 | 0 | OPEN("/etc/resolv.conf"); |
1126 | |
|
1127 | 0 | RENAME_SUFFIX("fingerprint", ".tmp"); |
1128 | 0 | RENAME_SUFFIX("fingerprint-ed25519", ".tmp"); |
1129 | 0 | RENAME_KEYDIR_SUFFIX("secret_onion_key_ntor", ".tmp"); |
1130 | |
|
1131 | 0 | RENAME_KEYDIR_SUFFIX("secret_id_key", ".tmp"); |
1132 | 0 | RENAME_KEYDIR_SUFFIX("secret_id_key.old", ".tmp"); |
1133 | 0 | RENAME_KEYDIR_SUFFIX("secret_onion_key", ".tmp"); |
1134 | 0 | RENAME_KEYDIR_SUFFIX("secret_onion_key.old", ".tmp"); |
1135 | |
|
1136 | 0 | RENAME_SUFFIX2("stats", "bridge-stats", ".tmp"); |
1137 | 0 | RENAME_SUFFIX2("stats", "dirreq-stats", ".tmp"); |
1138 | 0 | RENAME_SUFFIX2("stats", "entry-stats", ".tmp"); |
1139 | 0 | RENAME_SUFFIX2("stats", "exit-stats", ".tmp"); |
1140 | 0 | RENAME_SUFFIX2("stats", "buffer-stats", ".tmp"); |
1141 | 0 | RENAME_SUFFIX2("stats", "conn-stats", ".tmp"); |
1142 | 0 | RENAME_SUFFIX2("stats", "hidserv-stats", ".tmp"); |
1143 | 0 | RENAME_SUFFIX2("stats", "hidserv-v3-stats", ".tmp"); |
1144 | 0 | RENAME_SUFFIX("hashed-fingerprint", ".tmp"); |
1145 | 0 | RENAME_SUFFIX("router-stability", ".tmp"); |
1146 | |
|
1147 | 0 | RENAME_KEYDIR_SUFFIX("ed25519_master_id_secret_key", ".tmp"); |
1148 | 0 | RENAME_KEYDIR_SUFFIX("ed25519_master_id_secret_key_encrypted", ".tmp"); |
1149 | 0 | RENAME_KEYDIR_SUFFIX("ed25519_master_id_public_key", ".tmp"); |
1150 | 0 | RENAME_KEYDIR_SUFFIX("ed25519_signing_secret_key", ".tmp"); |
1151 | 0 | RENAME_KEYDIR_SUFFIX("ed25519_signing_cert", ".tmp"); |
1152 | |
|
1153 | 0 | sandbox_cfg_allow_rename(&cfg, |
1154 | 0 | get_keydir_fname("secret_onion_key"), |
1155 | 0 | get_keydir_fname("secret_onion_key.old")); |
1156 | 0 | sandbox_cfg_allow_rename(&cfg, |
1157 | 0 | get_keydir_fname("secret_onion_key_ntor"), |
1158 | 0 | get_keydir_fname("secret_onion_key_ntor.old")); |
1159 | |
|
1160 | 0 | STAT_KEY_DIRECTORY(); |
1161 | 0 | OPEN_DATADIR("stats"); |
1162 | 0 | STAT_DATADIR("stats"); |
1163 | 0 | STAT_DATADIR2("stats", "dirreq-stats"); |
1164 | |
|
1165 | 0 | consdiffmgr_register_with_sandbox(&cfg); |
1166 | 0 | } |
1167 | |
|
1168 | 0 | init_addrinfo(); |
1169 | |
|
1170 | 0 | return cfg; |
1171 | 0 | } |
1172 | | |
1173 | | int |
1174 | | run_tor_main_loop(void) |
1175 | 0 | { |
1176 | 0 | handle_signals(); |
1177 | 0 | timers_initialize(); |
1178 | 0 | initialize_mainloop_events(); |
1179 | | |
1180 | | /* load the private keys, if we're supposed to have them, and set up the |
1181 | | * TLS context. */ |
1182 | 0 | if (! client_identity_key_is_set()) { |
1183 | 0 | if (init_keys() < 0) { |
1184 | 0 | log_err(LD_OR, "Error initializing keys; exiting"); |
1185 | 0 | return -1; |
1186 | 0 | } |
1187 | 0 | } |
1188 | | |
1189 | | /* Set up our buckets */ |
1190 | 0 | connection_bucket_init(); |
1191 | | |
1192 | | /* initialize the bootstrap status events to know we're starting up */ |
1193 | 0 | control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0); |
1194 | | |
1195 | | /* Initialize the keypinning log. */ |
1196 | 0 | if (authdir_mode_v3(get_options())) { |
1197 | 0 | char *fname = get_datadir_fname("key-pinning-journal"); |
1198 | 0 | int r = 0; |
1199 | 0 | if (keypin_load_journal(fname)<0) { |
1200 | 0 | log_err(LD_DIR, "Error loading key-pinning journal: %s",strerror(errno)); |
1201 | 0 | r = -1; |
1202 | 0 | } |
1203 | 0 | if (keypin_open_journal(fname)<0) { |
1204 | 0 | log_err(LD_DIR, "Error opening key-pinning journal: %s",strerror(errno)); |
1205 | 0 | r = -1; |
1206 | 0 | } |
1207 | 0 | tor_free(fname); |
1208 | 0 | if (r) |
1209 | 0 | return r; |
1210 | 0 | } |
1211 | 0 | { |
1212 | | /* This is the old name for key-pinning-journal. These got corrupted |
1213 | | * in a couple of cases by #16530, so we started over. See #16580 for |
1214 | | * the rationale and for other options we didn't take. We can remove |
1215 | | * this code once all the authorities that ran 0.2.7.1-alpha-dev are |
1216 | | * upgraded. |
1217 | | */ |
1218 | 0 | char *fname = get_datadir_fname("key-pinning-entries"); |
1219 | 0 | unlink(fname); |
1220 | 0 | tor_free(fname); |
1221 | 0 | } |
1222 | |
|
1223 | 0 | if (trusted_dirs_reload_certs()) { |
1224 | 0 | log_warn(LD_DIR, |
1225 | 0 | "Couldn't load all cached v3 certificates. Starting anyway."); |
1226 | 0 | } |
1227 | 0 | if (router_reload_consensus_networkstatus()) { |
1228 | 0 | return -1; |
1229 | 0 | } |
1230 | | /* load the routers file, or assign the defaults. */ |
1231 | 0 | if (router_reload_router_list()) { |
1232 | 0 | return -1; |
1233 | 0 | } |
1234 | | /* load the networkstatuses. (This launches a download for new routers as |
1235 | | * appropriate.) |
1236 | | */ |
1237 | 0 | const time_t now = time(NULL); |
1238 | 0 | directory_info_has_arrived(now, 1, 0); |
1239 | | |
1240 | | /* launch cpuworkers. Need to do this *after* we've read the onion key. */ |
1241 | | /* launch them always for all tors, now that clients can solve onion PoWs. */ |
1242 | 0 | cpuworker_init(); |
1243 | |
|
1244 | 0 | consdiffmgr_enable_background_compression(); |
1245 | | |
1246 | | /* Setup shared random protocol subsystem. */ |
1247 | 0 | if (authdir_mode_v3(get_options())) { |
1248 | 0 | if (sr_init(1) < 0) { |
1249 | 0 | return -1; |
1250 | 0 | } |
1251 | 0 | } |
1252 | | |
1253 | | /* initialize dns resolve map, spawn workers if needed */ |
1254 | 0 | if (dns_init() < 0) { |
1255 | 0 | if (get_options()->ServerDNSAllowBrokenConfig) |
1256 | 0 | log_warn(LD_GENERAL, "Couldn't set up any working nameservers. " |
1257 | 0 | "Network not up yet? Will try again soon."); |
1258 | 0 | else { |
1259 | 0 | log_err(LD_GENERAL,"Error initializing dns subsystem; exiting. To " |
1260 | 0 | "retry instead, set the ServerDNSAllowBrokenResolvConf option."); |
1261 | 0 | } |
1262 | 0 | } |
1263 | |
|
1264 | | #ifdef HAVE_SYSTEMD |
1265 | | { |
1266 | | const int r = sd_notify(0, "READY=1"); |
1267 | | if (r < 0) { |
1268 | | log_warn(LD_GENERAL, "Unable to send readiness to systemd: %s", |
1269 | | strerror(r)); |
1270 | | } else if (r > 0) { |
1271 | | log_notice(LD_GENERAL, "Signaled readiness to systemd"); |
1272 | | } else { |
1273 | | log_info(LD_GENERAL, "Systemd NOTIFY_SOCKET not present."); |
1274 | | } |
1275 | | } |
1276 | | #endif /* defined(HAVE_SYSTEMD) */ |
1277 | |
|
1278 | 0 | return do_main_loop(); |
1279 | 0 | } |
1280 | | |
1281 | | /** Install the publish/subscribe relationships for all the subsystems. */ |
1282 | | void |
1283 | | pubsub_install(void) |
1284 | 0 | { |
1285 | 0 | pubsub_builder_t *builder = pubsub_builder_new(); |
1286 | 0 | int r = subsystems_add_pubsub(builder); |
1287 | 0 | tor_assert(r == 0); |
1288 | 0 | r = tor_mainloop_connect_pubsub(builder); // consumes builder |
1289 | 0 | tor_assert(r == 0); |
1290 | 0 | } |
1291 | | |
1292 | | /** Connect the mainloop to its publish/subscribe message delivery events if |
1293 | | * appropriate, and configure the global channels appropriately. */ |
1294 | | void |
1295 | | pubsub_connect(void) |
1296 | 0 | { |
1297 | 0 | if (get_options()->command == CMD_RUN_TOR) { |
1298 | 0 | tor_mainloop_connect_pubsub_events(); |
1299 | | /* XXXX For each pubsub channel, its delivery strategy should be set at |
1300 | | * this XXXX point, using tor_mainloop_set_delivery_strategy(). |
1301 | | */ |
1302 | 0 | tor_mainloop_set_delivery_strategy("orconn", DELIV_IMMEDIATE); |
1303 | 0 | tor_mainloop_set_delivery_strategy("ocirc", DELIV_IMMEDIATE); |
1304 | 0 | } |
1305 | 0 | } |
1306 | | |
1307 | | /* Main entry point for the Tor process. Called from tor_main(), and by |
1308 | | * anybody embedding Tor. */ |
1309 | | int |
1310 | | tor_run_main(const tor_main_configuration_t *tor_cfg) |
1311 | 0 | { |
1312 | 0 | int result = 0; |
1313 | |
|
1314 | 0 | #ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED |
1315 | 0 | event_set_mem_functions(tor_malloc_, tor_realloc_, tor_free_); |
1316 | 0 | #endif |
1317 | |
|
1318 | 0 | subsystems_init(); |
1319 | |
|
1320 | 0 | init_protocol_warning_severity_level(); |
1321 | |
|
1322 | 0 | int argc = tor_cfg->argc + tor_cfg->argc_owned; |
1323 | 0 | char **argv = tor_calloc(argc, sizeof(char*)); |
1324 | 0 | memcpy(argv, tor_cfg->argv, tor_cfg->argc*sizeof(char*)); |
1325 | 0 | if (tor_cfg->argc_owned) |
1326 | 0 | memcpy(argv + tor_cfg->argc, tor_cfg->argv_owned, |
1327 | 0 | tor_cfg->argc_owned*sizeof(char*)); |
1328 | |
|
1329 | 0 | int done = 0; |
1330 | 0 | result = nt_service_parse_options(argc, argv, &done); |
1331 | 0 | if (POSSIBLE(done)) |
1332 | 0 | goto done; |
1333 | | |
1334 | 0 | pubsub_install(); |
1335 | |
|
1336 | 0 | { |
1337 | 0 | int init_rv = tor_init(argc, argv); |
1338 | 0 | if (init_rv) { |
1339 | 0 | tor_free_all(0); |
1340 | 0 | result = (init_rv < 0) ? -1 : 0; |
1341 | 0 | goto done; |
1342 | 0 | } |
1343 | 0 | } |
1344 | | |
1345 | 0 | pubsub_connect(); |
1346 | |
|
1347 | 0 | if (get_options()->Sandbox && get_options()->command == CMD_RUN_TOR) { |
1348 | | #ifdef ENABLE_FRAGILE_HARDENING |
1349 | | log_warn(LD_CONFIG, "Sandbox is enabled but this Tor was built using " |
1350 | | "fragile compiler hardening. The sandbox may be unable to filter " |
1351 | | "requests to open files and directories and its overall " |
1352 | | "effectiveness will be reduced."); |
1353 | | #endif |
1354 | |
|
1355 | 0 | sandbox_cfg_t* cfg = sandbox_init_filter(); |
1356 | |
|
1357 | 0 | if (sandbox_init(cfg)) { |
1358 | 0 | tor_free(argv); |
1359 | 0 | log_err(LD_BUG,"Failed to create syscall sandbox filter"); |
1360 | 0 | tor_free_all(0); |
1361 | 0 | return -1; |
1362 | 0 | } |
1363 | 0 | tor_make_getaddrinfo_cache_active(); |
1364 | | |
1365 | | // registering libevent rng |
1366 | 0 | #ifdef HAVE_EVUTIL_SECURE_RNG_SET_URANDOM_DEVICE_FILE |
1367 | 0 | evutil_secure_rng_set_urandom_device_file( |
1368 | 0 | (char*) sandbox_intern_string("/dev/urandom")); |
1369 | 0 | #endif |
1370 | 0 | } |
1371 | | |
1372 | 0 | switch (get_options()->command) { |
1373 | 0 | case CMD_RUN_TOR: |
1374 | 0 | nt_service_set_state(SERVICE_RUNNING); |
1375 | 0 | result = run_tor_main_loop(); |
1376 | 0 | break; |
1377 | 0 | case CMD_KEYGEN: |
1378 | 0 | result = load_ed_keys(get_options(), time(NULL)) < 0; |
1379 | 0 | break; |
1380 | 0 | case CMD_KEY_EXPIRATION: |
1381 | 0 | init_keys(); |
1382 | 0 | result = log_cert_expiration(); |
1383 | 0 | break; |
1384 | 0 | case CMD_LIST_FINGERPRINT: |
1385 | 0 | result = do_list_fingerprint(); |
1386 | 0 | break; |
1387 | 0 | case CMD_HASH_PASSWORD: |
1388 | 0 | do_hash_password(); |
1389 | 0 | result = 0; |
1390 | 0 | break; |
1391 | 0 | case CMD_VERIFY_CONFIG: |
1392 | 0 | if (quiet_level == QUIET_NONE) |
1393 | 0 | printf("Configuration was valid\n"); |
1394 | 0 | result = 0; |
1395 | 0 | break; |
1396 | 0 | case CMD_DUMP_CONFIG: |
1397 | 0 | result = do_dump_config(); |
1398 | 0 | break; |
1399 | 0 | case CMD_RUN_UNITTESTS: /* only set by test.c */ |
1400 | 0 | case CMD_IMMEDIATE: /* Handled in config.c */ |
1401 | 0 | default: |
1402 | 0 | log_warn(LD_BUG,"Illegal command number %d: internal error.", |
1403 | 0 | get_options()->command); |
1404 | 0 | result = -1; |
1405 | 0 | } |
1406 | 0 | tor_cleanup(); |
1407 | 0 | done: |
1408 | 0 | tor_free(argv); |
1409 | 0 | return result; |
1410 | 0 | } |