1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2  * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
4 
5 /**
6  * \file control_bootstrap.c
7  * \brief Provide bootstrap progress events for the control port.
8  */
9 #include "core/or/or.h"
10 
11 #include "app/config/config.h"
12 #include "core/mainloop/connection.h"
13 #include "core/or/connection_or.h"
14 #include "core/or/connection_st.h"
15 #include "core/or/or_connection_st.h"
16 #include "core/or/reasons.h"
17 #include "feature/control/control_events.h"
18 #include "feature/hibernate/hibernate.h"
19 #include "lib/malloc/malloc.h"
20 
21 /** A sufficiently large size to record the last bootstrap phase string. */
22 #define BOOTSTRAP_MSG_LEN 1024
23 
24 /** What was the last bootstrap phase message we sent? We keep track
25  * of this so we can respond to getinfo status/bootstrap-phase queries. */
26 static char last_sent_bootstrap_message[BOOTSTRAP_MSG_LEN];
27 
28 /** Table to convert bootstrap statuses to strings.  */
29 static const struct {
30   bootstrap_status_t status;
31   const char *tag;
32   const char *summary;
33 } boot_to_str_tab[] = {
34   { BOOTSTRAP_STATUS_UNDEF, "undef", "Undefined" },
35   { BOOTSTRAP_STATUS_STARTING, "starting", "Starting" },
36 
37   /* Initial connection to any relay */
38 
39   { BOOTSTRAP_STATUS_CONN_PT, "conn_pt", "Connecting to pluggable transport" },
40   { BOOTSTRAP_STATUS_CONN_DONE_PT, "conn_done_pt",
41     "Connected to pluggable transport" },
42   { BOOTSTRAP_STATUS_CONN_PROXY, "conn_proxy", "Connecting to proxy" },
43   { BOOTSTRAP_STATUS_CONN_DONE_PROXY, "conn_done_proxy",
44     "Connected to proxy" },
45   { BOOTSTRAP_STATUS_CONN, "conn", "Connecting to a relay" },
46   { BOOTSTRAP_STATUS_CONN_DONE, "conn_done", "Connected to a relay" },
47   { BOOTSTRAP_STATUS_HANDSHAKE, "handshake",
48     "Handshaking with a relay" },
49   { BOOTSTRAP_STATUS_HANDSHAKE_DONE, "handshake_done",
50     "Handshake with a relay done" },
51 
52   /* Loading directory info */
53 
54   { BOOTSTRAP_STATUS_ONEHOP_CREATE, "onehop_create",
55     "Establishing an encrypted directory connection" },
56   { BOOTSTRAP_STATUS_REQUESTING_STATUS, "requesting_status",
57     "Asking for networkstatus consensus" },
58   { BOOTSTRAP_STATUS_LOADING_STATUS, "loading_status",
59     "Loading networkstatus consensus" },
60   { BOOTSTRAP_STATUS_LOADING_KEYS, "loading_keys",
61     "Loading authority key certs" },
62   { BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, "requesting_descriptors",
63     "Asking for relay descriptors" },
64   { BOOTSTRAP_STATUS_LOADING_DESCRIPTORS, "loading_descriptors",
65     "Loading relay descriptors" },
66   { BOOTSTRAP_STATUS_ENOUGH_DIRINFO, "enough_dirinfo",
67     "Loaded enough directory info to build circuits" },
68 
69   /* Connecting to a relay for AP circuits */
70 
71   { BOOTSTRAP_STATUS_AP_CONN_PT, "ap_conn_pt",
72     "Connecting to pluggable transport to build circuits" },
73   { BOOTSTRAP_STATUS_AP_CONN_DONE_PT, "ap_conn_done_pt",
74     "Connected to pluggable transport to build circuits" },
75   { BOOTSTRAP_STATUS_AP_CONN_PROXY, "ap_conn_proxy",
76     "Connecting to proxy to build circuits" },
77   { BOOTSTRAP_STATUS_AP_CONN_DONE_PROXY, "ap_conn_done_proxy",
78     "Connected to proxy to build circuits" },
79   { BOOTSTRAP_STATUS_AP_CONN, "ap_conn",
80     "Connecting to a relay to build circuits" },
81   { BOOTSTRAP_STATUS_AP_CONN_DONE, "ap_conn_done",
82     "Connected to a relay to build circuits" },
83   { BOOTSTRAP_STATUS_AP_HANDSHAKE, "ap_handshake",
84     "Finishing handshake with a relay to build circuits" },
85   { BOOTSTRAP_STATUS_AP_HANDSHAKE_DONE, "ap_handshake_done",
86     "Handshake finished with a relay to build circuits" },
87 
88   /* Creating AP circuits */
89 
90   { BOOTSTRAP_STATUS_CIRCUIT_CREATE, "circuit_create",
91     "Establishing a Tor circuit" },
92   { BOOTSTRAP_STATUS_DONE, "done", "Done" },
93 };
94 #define N_BOOT_TO_STR (sizeof(boot_to_str_tab)/sizeof(boot_to_str_tab[0]))
95 
96 /** Convert the name of a bootstrapping phase <b>s</b> into strings
97  * <b>tag</b> and <b>summary</b> suitable for display by the controller. */
98 static int
bootstrap_status_to_string(bootstrap_status_t s,const char ** tag,const char ** summary)99 bootstrap_status_to_string(bootstrap_status_t s, const char **tag,
100                            const char **summary)
101 {
102   for (size_t i = 0; i < N_BOOT_TO_STR; i++) {
103     if (s == boot_to_str_tab[i].status) {
104       *tag = boot_to_str_tab[i].tag;
105       *summary = boot_to_str_tab[i].summary;
106       return 0;
107     }
108   }
109 
110   *tag = *summary = "unknown";
111   return -1;
112 }
113 
114 /** What percentage through the bootstrap process are we? We remember
115  * this so we can avoid sending redundant bootstrap status events, and
116  * so we can guess context for the bootstrap messages which are
117  * ambiguous. It starts at 'undef', but gets set to 'starting' while
118  * Tor initializes. */
119 static int bootstrap_percent = BOOTSTRAP_STATUS_UNDEF;
120 
121 /** Like bootstrap_percent, but only takes on the enumerated values in
122  * bootstrap_status_t.
123  */
124 static int bootstrap_phase = BOOTSTRAP_STATUS_UNDEF;
125 
126 /** As bootstrap_percent, but holds the bootstrapping level at which we last
127  * logged a NOTICE-level message. We use this, plus BOOTSTRAP_PCT_INCREMENT,
128  * to avoid flooding the log with a new message every time we get a few more
129  * microdescriptors */
130 static int notice_bootstrap_percent = 0;
131 
132 /** How many problems have we had getting to the next bootstrapping phase?
133  * These include failure to establish a connection to a Tor relay,
134  * failures to finish the TLS handshake, failures to validate the
135  * consensus document, etc. */
136 static int bootstrap_problems = 0;
137 
138 /** We only tell the controller once we've hit a threshold of problems
139  * for the current phase. */
140 #define BOOTSTRAP_PROBLEM_THRESHOLD 10
141 
142 /** When our bootstrapping progress level changes, but our bootstrapping
143  * status has not advanced, we only log at NOTICE when we have made at least
144  * this much progress.
145  */
146 #define BOOTSTRAP_PCT_INCREMENT 5
147 
148 /** Do the actual logging and notifications for
149  * control_event_bootstrap().  Doesn't change any state beyond that.
150  */
151 static void
control_event_bootstrap_core(int loglevel,bootstrap_status_t status,int progress)152 control_event_bootstrap_core(int loglevel, bootstrap_status_t status,
153                              int progress)
154 {
155   char buf[BOOTSTRAP_MSG_LEN];
156   const char *tag, *summary;
157 
158   bootstrap_status_to_string(status, &tag, &summary);
159   /* Locally reset status if there's incremental progress */
160   if (progress)
161     status = progress;
162 
163   tor_log(loglevel, LD_CONTROL,
164           "Bootstrapped %d%% (%s): %s", status, tag, summary);
165   tor_snprintf(buf, sizeof(buf),
166                "BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\"",
167                status, tag, summary);
168   tor_snprintf(last_sent_bootstrap_message,
169                sizeof(last_sent_bootstrap_message),
170                "NOTICE %s", buf);
171   control_event_client_status(LOG_NOTICE, "%s", buf);
172 }
173 
174 int
control_get_bootstrap_percent(void)175 control_get_bootstrap_percent(void)
176 {
177   return bootstrap_percent;
178 }
179 
180 /** Called when Tor has made progress at bootstrapping its directory
181  * information and initial circuits.
182  *
183  * <b>status</b> is the new status, that is, what task we will be doing
184  * next. <b>progress</b> is zero if we just started this task, else it
185  * represents progress on the task.
186  */
187 void
control_event_bootstrap(bootstrap_status_t status,int progress)188 control_event_bootstrap(bootstrap_status_t status, int progress)
189 {
190   int loglevel = LOG_NOTICE;
191 
192   if (bootstrap_percent == BOOTSTRAP_STATUS_DONE)
193     return; /* already bootstrapped; nothing to be done here. */
194 
195   if (status <= bootstrap_percent) {
196     /* If there's no new progress, return early. */
197     if (!progress || progress <= bootstrap_percent)
198       return;
199     /* Log at INFO if not enough progress happened. */
200     if (progress < notice_bootstrap_percent + BOOTSTRAP_PCT_INCREMENT)
201       loglevel = LOG_INFO;
202   }
203 
204   control_event_bootstrap_core(loglevel, status, progress);
205 
206   if (status > bootstrap_percent) {
207     bootstrap_phase = status; /* new milestone reached */
208     bootstrap_percent = status;
209   }
210   if (progress > bootstrap_percent) {
211     /* incremental progress within a milestone */
212     bootstrap_percent = progress;
213     bootstrap_problems = 0; /* Progress! Reset our problem counter. */
214   }
215   if (loglevel == LOG_NOTICE &&
216       bootstrap_percent > notice_bootstrap_percent) {
217     /* Remember that we gave a notice at this level. */
218     notice_bootstrap_percent = bootstrap_percent;
219   }
220 }
221 
222 /** Flag whether we've opened an OR_CONN yet  */
223 static int bootstrap_first_orconn = 0;
224 
225 /** Like bootstrap_phase, but for (possibly deferred) directory progress */
226 static int bootstrap_dir_phase = BOOTSTRAP_STATUS_UNDEF;
227 
228 /** Like bootstrap_problems, but for (possibly deferred) directory progress  */
229 static int bootstrap_dir_progress = BOOTSTRAP_STATUS_UNDEF;
230 
231 /** Defer directory info bootstrap events until we have successfully
232  * completed our first connection to a router.  */
233 void
control_event_boot_dir(bootstrap_status_t status,int progress)234 control_event_boot_dir(bootstrap_status_t status, int progress)
235 {
236   if (status > bootstrap_dir_progress) {
237     bootstrap_dir_progress = status;
238     bootstrap_dir_phase = status;
239   }
240   if (progress && progress >= bootstrap_dir_progress) {
241     bootstrap_dir_progress = progress;
242   }
243 
244   /* Don't report unless we have successfully opened at least one OR_CONN */
245   if (!bootstrap_first_orconn)
246     return;
247 
248   control_event_bootstrap(status, progress);
249 }
250 
251 /** Set a flag to allow reporting of directory bootstrap progress.
252  * (Code that reports completion of an OR_CONN calls this.)  Also,
253  * report directory progress so far. */
254 void
control_event_boot_first_orconn(void)255 control_event_boot_first_orconn(void)
256 {
257   bootstrap_first_orconn = 1;
258   control_event_bootstrap(bootstrap_dir_phase, bootstrap_dir_progress);
259 }
260 
261 /** Called when Tor has failed to make bootstrapping progress in a way
262  * that indicates a problem. <b>warn</b> gives a human-readable hint
263  * as to why, and <b>reason</b> provides a controller-facing short
264  * tag.  <b>conn</b> is the connection that caused this problem and
265  * can be NULL if a connection cannot be easily identified.
266  */
267 void
control_event_bootstrap_problem(const char * warn,const char * reason,const connection_t * conn,int dowarn)268 control_event_bootstrap_problem(const char *warn, const char *reason,
269                                 const connection_t *conn, int dowarn)
270 {
271   int status = bootstrap_percent;
272   const char *tag = "", *summary = "";
273   char buf[BOOTSTRAP_MSG_LEN];
274   const char *recommendation = "ignore";
275   int severity;
276   char *or_id = NULL, *hostaddr = NULL;
277   const or_connection_t *or_conn = NULL;
278 
279   /* bootstrap_percent must not be in "undefined" state here. */
280   tor_assert(status >= 0);
281 
282   if (bootstrap_percent == 100)
283     return; /* already bootstrapped; nothing to be done here. */
284 
285   bootstrap_problems++;
286 
287   if (bootstrap_problems >= BOOTSTRAP_PROBLEM_THRESHOLD)
288     dowarn = 1;
289 
290   /* Don't warn about our bootstrapping status if we are hibernating or
291    * shutting down. */
292   if (we_are_hibernating())
293     dowarn = 0;
294 
295   tor_assert(bootstrap_status_to_string(bootstrap_phase, &tag, &summary) == 0);
296 
297   severity = dowarn ? LOG_WARN : LOG_INFO;
298 
299   if (dowarn)
300     recommendation = "warn";
301 
302   if (conn && conn->type == CONN_TYPE_OR) {
303     /* XXX TO_OR_CONN can't deal with const */
304     or_conn = CONST_TO_OR_CONN(conn);
305     or_id = tor_strdup(hex_str(or_conn->identity_digest, DIGEST_LEN));
306   } else {
307     or_id = tor_strdup("?");
308   }
309 
310   if (conn)
311     tor_asprintf(&hostaddr, "%s:%d", conn->address, (int)conn->port);
312   else
313     hostaddr = tor_strdup("?");
314 
315   log_fn(severity,
316          LD_CONTROL, "Problem bootstrapping. Stuck at %d%% (%s): %s. (%s; %s; "
317          "count %d; recommendation %s; host %s at %s)",
318          status, tag, summary, warn, reason,
319          bootstrap_problems, recommendation,
320          or_id, hostaddr);
321 
322   connection_or_report_broken_states(severity, LD_HANDSHAKE);
323 
324   tor_snprintf(buf, sizeof(buf),
325       "BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\" WARNING=\"%s\" REASON=%s "
326       "COUNT=%d RECOMMENDATION=%s HOSTID=\"%s\" HOSTADDR=\"%s\"",
327       bootstrap_percent, tag, summary, warn, reason, bootstrap_problems,
328       recommendation,
329       or_id, hostaddr);
330 
331   tor_snprintf(last_sent_bootstrap_message,
332                sizeof(last_sent_bootstrap_message),
333                "WARN %s", buf);
334   control_event_client_status(LOG_WARN, "%s", buf);
335 
336   tor_free(hostaddr);
337   tor_free(or_id);
338 }
339 
340 /** Called when Tor has failed to make bootstrapping progress in a way
341  * that indicates a problem. <b>warn</b> gives a hint as to why, and
342  * <b>reason</b> provides an "or_conn_end_reason" tag.  <b>or_conn</b>
343  * is the connection that caused this problem.
344  */
345 MOCK_IMPL(void,
346 control_event_bootstrap_prob_or, (const char *warn, int reason,
347                                   or_connection_t *or_conn))
348 {
349   int dowarn = 0;
350 
351   if (! or_conn->potentially_used_for_bootstrapping) {
352     /* We never decided that this channel was a good match for one of our
353      * origin_circuit_t objects.  That means that we probably launched it
354      * for somebody else, most likely in response to an EXTEND cell.
355      *
356      * Since EXTEND cells can contain arbitrarily broken descriptions of
357      * relays, a failure on this connection here won't necessarily indicate a
358      * bootstrapping problem.
359      */
360     return;
361   }
362 
363   if (or_conn->have_noted_bootstrap_problem)
364     return;
365 
366   or_conn->have_noted_bootstrap_problem = 1;
367 
368   if (reason == END_OR_CONN_REASON_NO_ROUTE)
369     dowarn = 1;
370 
371   /* If we are using bridges and all our OR connections are now
372      closed, it means that we totally failed to connect to our
373      bridges. Throw a warning. */
374   if (get_options()->UseBridges && !any_other_active_or_conns(or_conn))
375     dowarn = 1;
376 
377   control_event_bootstrap_problem(warn,
378                                   orconn_end_reason_to_control_string(reason),
379                                   TO_CONN(or_conn), dowarn);
380 }
381 
382 /** Return a copy of the last sent bootstrap message. */
383 char *
control_event_boot_last_msg(void)384 control_event_boot_last_msg(void)
385 {
386   return tor_strdup(last_sent_bootstrap_message);
387 }
388 
389 /** Reset bootstrap tracking state. */
390 void
control_event_bootstrap_reset(void)391 control_event_bootstrap_reset(void)
392 {
393   bootstrap_percent = BOOTSTRAP_STATUS_UNDEF;
394   bootstrap_phase = BOOTSTRAP_STATUS_UNDEF;
395   notice_bootstrap_percent = 0;
396   bootstrap_problems = 0;
397   bootstrap_first_orconn = 0;
398   bootstrap_dir_progress = BOOTSTRAP_STATUS_UNDEF;
399   bootstrap_dir_phase = BOOTSTRAP_STATUS_UNDEF;
400   memset(last_sent_bootstrap_message, 0, sizeof(last_sent_bootstrap_message));
401 }
402