mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-25 23:21:38 +01:00
Merge remote-tracking branch 'catalyst-oniongit/skew'
This commit is contained in:
commit
72b802001c
7 changed files with 97 additions and 52 deletions
4
changes/bug23506
Normal file
4
changes/bug23506
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
o Major bugfixes (usability, control port):
|
||||||
|
- Report trusted clock skew indications as bootstrap errors, so
|
||||||
|
controllers can more easily alert users. Fixes bug 23506;
|
||||||
|
bugfix on 0.1.2.6-alpha.
|
|
@ -5221,7 +5221,7 @@ clock_skew_warning(const connection_t *conn, long apparent_skew, int trusted,
|
||||||
const char *source)
|
const char *source)
|
||||||
{
|
{
|
||||||
char dbuf[64];
|
char dbuf[64];
|
||||||
char *ext_source = NULL;
|
char *ext_source = NULL, *warn = NULL;
|
||||||
format_time_interval(dbuf, sizeof(dbuf), apparent_skew);
|
format_time_interval(dbuf, sizeof(dbuf), apparent_skew);
|
||||||
if (conn)
|
if (conn)
|
||||||
tor_asprintf(&ext_source, "%s:%s:%d", source, conn->address, conn->port);
|
tor_asprintf(&ext_source, "%s:%s:%d", source, conn->address, conn->port);
|
||||||
|
@ -5235,9 +5235,14 @@ clock_skew_warning(const connection_t *conn, long apparent_skew, int trusted,
|
||||||
apparent_skew > 0 ? "ahead" : "behind", dbuf,
|
apparent_skew > 0 ? "ahead" : "behind", dbuf,
|
||||||
apparent_skew > 0 ? "behind" : "ahead",
|
apparent_skew > 0 ? "behind" : "ahead",
|
||||||
(!conn || trusted) ? "" : ", or they are sending us the wrong time");
|
(!conn || trusted) ? "" : ", or they are sending us the wrong time");
|
||||||
if (trusted)
|
if (trusted) {
|
||||||
control_event_general_status(LOG_WARN, "CLOCK_SKEW SKEW=%ld SOURCE=%s",
|
control_event_general_status(LOG_WARN, "CLOCK_SKEW SKEW=%ld SOURCE=%s",
|
||||||
apparent_skew, ext_source);
|
apparent_skew, ext_source);
|
||||||
|
tor_asprintf(&warn, "Clock skew %ld in %s from %s", apparent_skew,
|
||||||
|
received, source);
|
||||||
|
control_event_bootstrap_problem(warn, "CLOCK_SKEW", conn, 1);
|
||||||
|
}
|
||||||
|
tor_free(warn);
|
||||||
tor_free(ext_source);
|
tor_free(ext_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -727,7 +727,7 @@ connection_or_about_to_close(or_connection_t *or_conn)
|
||||||
control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
|
control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
|
||||||
reason);
|
reason);
|
||||||
if (!authdir_mode_tests_reachability(options))
|
if (!authdir_mode_tests_reachability(options))
|
||||||
control_event_bootstrap_problem(
|
control_event_bootstrap_prob_or(
|
||||||
orconn_end_reason_to_control_string(reason),
|
orconn_end_reason_to_control_string(reason),
|
||||||
reason, or_conn);
|
reason, or_conn);
|
||||||
}
|
}
|
||||||
|
@ -1113,7 +1113,7 @@ connection_or_connect_failed(or_connection_t *conn,
|
||||||
{
|
{
|
||||||
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, reason);
|
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, reason);
|
||||||
if (!authdir_mode_tests_reachability(get_options()))
|
if (!authdir_mode_tests_reachability(get_options()))
|
||||||
control_event_bootstrap_problem(msg, reason, conn);
|
control_event_bootstrap_prob_or(msg, reason, conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** <b>conn</b> got an error in connection_handle_read_impl() or
|
/** <b>conn</b> got an error in connection_handle_read_impl() or
|
||||||
|
@ -1236,7 +1236,7 @@ connection_or_connect, (const tor_addr_t *_addr, uint16_t port,
|
||||||
fmt_addrport(&TO_CONN(conn)->addr, TO_CONN(conn)->port),
|
fmt_addrport(&TO_CONN(conn)->addr, TO_CONN(conn)->port),
|
||||||
transport_name, transport_name);
|
transport_name, transport_name);
|
||||||
|
|
||||||
control_event_bootstrap_problem(
|
control_event_bootstrap_prob_or(
|
||||||
"Can't connect to bridge",
|
"Can't connect to bridge",
|
||||||
END_OR_CONN_REASON_PT_MISSING,
|
END_OR_CONN_REASON_PT_MISSING,
|
||||||
conn);
|
conn);
|
||||||
|
@ -1714,7 +1714,7 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
|
||||||
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
|
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
|
||||||
END_OR_CONN_REASON_OR_IDENTITY);
|
END_OR_CONN_REASON_OR_IDENTITY);
|
||||||
if (!authdir_mode_tests_reachability(options))
|
if (!authdir_mode_tests_reachability(options))
|
||||||
control_event_bootstrap_problem(
|
control_event_bootstrap_prob_or(
|
||||||
"Unexpected identity in router certificate",
|
"Unexpected identity in router certificate",
|
||||||
END_OR_CONN_REASON_OR_IDENTITY,
|
END_OR_CONN_REASON_OR_IDENTITY,
|
||||||
conn);
|
conn);
|
||||||
|
|
102
src/or/control.c
102
src/or/control.c
|
@ -6754,80 +6754,112 @@ control_event_bootstrap(bootstrap_status_t status, int progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when Tor has failed to make bootstrapping progress in a way
|
/** Called when Tor has failed to make bootstrapping progress in a way
|
||||||
* that indicates a problem. <b>warn</b> gives a hint as to why, and
|
* that indicates a problem. <b>warn</b> gives a human-readable hint
|
||||||
* <b>reason</b> provides an "or_conn_end_reason" tag. <b>or_conn</b>
|
* as to why, and <b>reason</b> provides a controller-facing short
|
||||||
* is the connection that caused this problem.
|
* tag. <b>conn</b> is the connection that caused this problem and
|
||||||
|
* can be NULL if a connection cannot be easily identified.
|
||||||
*/
|
*/
|
||||||
MOCK_IMPL(void,
|
void
|
||||||
control_event_bootstrap_problem, (const char *warn, int reason,
|
control_event_bootstrap_problem(const char *warn, const char *reason,
|
||||||
or_connection_t *or_conn))
|
const connection_t *conn, int dowarn)
|
||||||
{
|
{
|
||||||
int status = bootstrap_percent;
|
int status = bootstrap_percent;
|
||||||
const char *tag = "", *summary = "";
|
const char *tag = "", *summary = "";
|
||||||
char buf[BOOTSTRAP_MSG_LEN];
|
char buf[BOOTSTRAP_MSG_LEN];
|
||||||
const char *recommendation = "ignore";
|
const char *recommendation = "ignore";
|
||||||
int severity;
|
int severity;
|
||||||
|
char *or_id = NULL, *hostaddr = NULL;
|
||||||
|
or_connection_t *or_conn = NULL;
|
||||||
|
|
||||||
/* bootstrap_percent must not be in "undefined" state here. */
|
/* bootstrap_percent must not be in "undefined" state here. */
|
||||||
tor_assert(status >= 0);
|
tor_assert(status >= 0);
|
||||||
|
|
||||||
if (or_conn->have_noted_bootstrap_problem)
|
|
||||||
return;
|
|
||||||
|
|
||||||
or_conn->have_noted_bootstrap_problem = 1;
|
|
||||||
|
|
||||||
if (bootstrap_percent == 100)
|
if (bootstrap_percent == 100)
|
||||||
return; /* already bootstrapped; nothing to be done here. */
|
return; /* already bootstrapped; nothing to be done here. */
|
||||||
|
|
||||||
bootstrap_problems++;
|
bootstrap_problems++;
|
||||||
|
|
||||||
if (bootstrap_problems >= BOOTSTRAP_PROBLEM_THRESHOLD)
|
if (bootstrap_problems >= BOOTSTRAP_PROBLEM_THRESHOLD)
|
||||||
recommendation = "warn";
|
dowarn = 1;
|
||||||
|
|
||||||
if (reason == END_OR_CONN_REASON_NO_ROUTE)
|
|
||||||
recommendation = "warn";
|
|
||||||
|
|
||||||
/* If we are using bridges and all our OR connections are now
|
|
||||||
closed, it means that we totally failed to connect to our
|
|
||||||
bridges. Throw a warning. */
|
|
||||||
if (get_options()->UseBridges && !any_other_active_or_conns(or_conn))
|
|
||||||
recommendation = "warn";
|
|
||||||
|
|
||||||
if (we_are_hibernating())
|
if (we_are_hibernating())
|
||||||
recommendation = "ignore";
|
dowarn = 0;
|
||||||
|
|
||||||
while (status>=0 && bootstrap_status_to_string(status, &tag, &summary) < 0)
|
while (status>=0 && bootstrap_status_to_string(status, &tag, &summary) < 0)
|
||||||
status--; /* find a recognized status string based on current progress */
|
status--; /* find a recognized status string based on current progress */
|
||||||
status = bootstrap_percent; /* set status back to the actual number */
|
status = bootstrap_percent; /* set status back to the actual number */
|
||||||
|
|
||||||
severity = !strcmp(recommendation, "warn") ? LOG_WARN : LOG_INFO;
|
severity = dowarn ? LOG_WARN : LOG_INFO;
|
||||||
|
|
||||||
|
if (dowarn)
|
||||||
|
recommendation = "warn";
|
||||||
|
|
||||||
|
if (conn && conn->type == CONN_TYPE_OR) {
|
||||||
|
/* XXX TO_OR_CONN can't deal with const */
|
||||||
|
or_conn = TO_OR_CONN((connection_t *)conn);
|
||||||
|
or_id = tor_strdup(hex_str(or_conn->identity_digest, DIGEST_LEN));
|
||||||
|
} else {
|
||||||
|
or_id = tor_strdup("?");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn)
|
||||||
|
tor_asprintf(&hostaddr, "%s:%d", conn->address, (int)conn->port);
|
||||||
|
else
|
||||||
|
hostaddr = tor_strdup("?");
|
||||||
|
|
||||||
log_fn(severity,
|
log_fn(severity,
|
||||||
LD_CONTROL, "Problem bootstrapping. Stuck at %d%%: %s. (%s; %s; "
|
LD_CONTROL, "Problem bootstrapping. Stuck at %d%%: %s. (%s; %s; "
|
||||||
"count %d; recommendation %s; host %s at %s:%d)",
|
"count %d; recommendation %s; host %s at %s)",
|
||||||
status, summary, warn,
|
status, summary, warn, reason,
|
||||||
orconn_end_reason_to_control_string(reason),
|
|
||||||
bootstrap_problems, recommendation,
|
bootstrap_problems, recommendation,
|
||||||
hex_str(or_conn->identity_digest, DIGEST_LEN),
|
or_id, hostaddr);
|
||||||
or_conn->base_.address,
|
|
||||||
or_conn->base_.port);
|
|
||||||
|
|
||||||
connection_or_report_broken_states(severity, LD_HANDSHAKE);
|
connection_or_report_broken_states(severity, LD_HANDSHAKE);
|
||||||
|
|
||||||
tor_snprintf(buf, sizeof(buf),
|
tor_snprintf(buf, sizeof(buf),
|
||||||
"BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\" WARNING=\"%s\" REASON=%s "
|
"BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\" WARNING=\"%s\" REASON=%s "
|
||||||
"COUNT=%d RECOMMENDATION=%s HOSTID=\"%s\" HOSTADDR=\"%s:%d\"",
|
"COUNT=%d RECOMMENDATION=%s HOSTID=\"%s\" HOSTADDR=\"%s\"",
|
||||||
bootstrap_percent, tag, summary, warn,
|
bootstrap_percent, tag, summary, warn, reason, bootstrap_problems,
|
||||||
orconn_end_reason_to_control_string(reason), bootstrap_problems,
|
|
||||||
recommendation,
|
recommendation,
|
||||||
hex_str(or_conn->identity_digest, DIGEST_LEN),
|
or_id, hostaddr);
|
||||||
or_conn->base_.address,
|
|
||||||
(int)or_conn->base_.port);
|
|
||||||
|
|
||||||
tor_snprintf(last_sent_bootstrap_message,
|
tor_snprintf(last_sent_bootstrap_message,
|
||||||
sizeof(last_sent_bootstrap_message),
|
sizeof(last_sent_bootstrap_message),
|
||||||
"WARN %s", buf);
|
"WARN %s", buf);
|
||||||
control_event_client_status(LOG_WARN, "%s", buf);
|
control_event_client_status(LOG_WARN, "%s", buf);
|
||||||
|
|
||||||
|
tor_free(hostaddr);
|
||||||
|
tor_free(or_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when Tor has failed to make bootstrapping progress in a way
|
||||||
|
* that indicates a problem. <b>warn</b> gives a hint as to why, and
|
||||||
|
* <b>reason</b> provides an "or_conn_end_reason" tag. <b>or_conn</b>
|
||||||
|
* is the connection that caused this problem.
|
||||||
|
*/
|
||||||
|
MOCK_IMPL(void,
|
||||||
|
control_event_bootstrap_prob_or, (const char *warn, int reason,
|
||||||
|
or_connection_t *or_conn))
|
||||||
|
{
|
||||||
|
int dowarn = 0;
|
||||||
|
|
||||||
|
if (or_conn->have_noted_bootstrap_problem)
|
||||||
|
return;
|
||||||
|
|
||||||
|
or_conn->have_noted_bootstrap_problem = 1;
|
||||||
|
|
||||||
|
if (reason == END_OR_CONN_REASON_NO_ROUTE)
|
||||||
|
dowarn = 1;
|
||||||
|
|
||||||
|
/* If we are using bridges and all our OR connections are now
|
||||||
|
closed, it means that we totally failed to connect to our
|
||||||
|
bridges. Throw a warning. */
|
||||||
|
if (get_options()->UseBridges && !any_other_active_or_conns(or_conn))
|
||||||
|
dowarn = 1;
|
||||||
|
|
||||||
|
control_event_bootstrap_problem(warn,
|
||||||
|
orconn_end_reason_to_control_string(reason),
|
||||||
|
TO_CONN(or_conn), dowarn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** We just generated a new summary of which countries we've seen clients
|
/** We just generated a new summary of which countries we've seen clients
|
||||||
|
|
|
@ -99,9 +99,11 @@ void enable_control_logging(void);
|
||||||
void monitor_owning_controller_process(const char *process_spec);
|
void monitor_owning_controller_process(const char *process_spec);
|
||||||
|
|
||||||
int control_event_bootstrap(bootstrap_status_t status, int progress);
|
int control_event_bootstrap(bootstrap_status_t status, int progress);
|
||||||
MOCK_DECL(void, control_event_bootstrap_problem,(const char *warn,
|
MOCK_DECL(void, control_event_bootstrap_prob_or,(const char *warn,
|
||||||
int reason,
|
int reason,
|
||||||
or_connection_t *or_conn));
|
or_connection_t *or_conn));
|
||||||
|
void control_event_bootstrap_problem(const char *warn, const char *reason,
|
||||||
|
const connection_t *conn, int dowarn);
|
||||||
|
|
||||||
void control_event_clients_seen(const char *controller_str);
|
void control_event_clients_seen(const char *controller_str);
|
||||||
void control_event_transport_launched(const char *mode,
|
void control_event_transport_launched(const char *mode,
|
||||||
|
|
|
@ -1989,14 +1989,16 @@ networkstatus_set_current_consensus(const char *consensus,
|
||||||
char tbuf[ISO_TIME_LEN+1];
|
char tbuf[ISO_TIME_LEN+1];
|
||||||
char dbuf[64];
|
char dbuf[64];
|
||||||
long delta = now - c->valid_after;
|
long delta = now - c->valid_after;
|
||||||
|
char *flavormsg = NULL;
|
||||||
format_iso_time(tbuf, c->valid_after);
|
format_iso_time(tbuf, c->valid_after);
|
||||||
format_time_interval(dbuf, sizeof(dbuf), delta);
|
format_time_interval(dbuf, sizeof(dbuf), delta);
|
||||||
log_warn(LD_GENERAL, "Our clock is %s behind the time published in the "
|
log_warn(LD_GENERAL, "Our clock is %s behind the time published in the "
|
||||||
"consensus network status document (%s UTC). Tor needs an "
|
"consensus network status document (%s UTC). Tor needs an "
|
||||||
"accurate clock to work correctly. Please check your time and "
|
"accurate clock to work correctly. Please check your time and "
|
||||||
"date settings!", dbuf, tbuf);
|
"date settings!", dbuf, tbuf);
|
||||||
control_event_general_status(LOG_WARN,
|
tor_asprintf(&flavormsg, "%s flavor consensus", flavor);
|
||||||
"CLOCK_SKEW MIN_SKEW=%ld SOURCE=CONSENSUS", delta);
|
clock_skew_warning(NULL, delta, 1, LD_GENERAL, flavormsg, "CONSENSUS");
|
||||||
|
tor_free(flavormsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
router_dir_info_changed();
|
router_dir_info_changed();
|
||||||
|
|
|
@ -497,14 +497,14 @@ test_ext_or_handshake(void *arg)
|
||||||
"te road There is always another ", 64);
|
"te road There is always another ", 64);
|
||||||
/* Send the wrong response. */
|
/* Send the wrong response. */
|
||||||
WRITE("not with a bang but a whimper...", 32);
|
WRITE("not with a bang but a whimper...", 32);
|
||||||
MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem);
|
MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
|
||||||
tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
|
tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
|
||||||
CONTAINS("\x00", 1);
|
CONTAINS("\x00", 1);
|
||||||
tt_assert(TO_CONN(conn)->marked_for_close);
|
tt_assert(TO_CONN(conn)->marked_for_close);
|
||||||
/* XXXX Hold-open-until-flushed. */
|
/* XXXX Hold-open-until-flushed. */
|
||||||
close_closeable_connections();
|
close_closeable_connections();
|
||||||
conn = NULL;
|
conn = NULL;
|
||||||
UNMOCK(control_event_bootstrap_problem);
|
UNMOCK(control_event_bootstrap_prob_or);
|
||||||
|
|
||||||
MOCK(connection_start_reading, note_read_started);
|
MOCK(connection_start_reading, note_read_started);
|
||||||
MOCK(connection_stop_reading, note_read_stopped);
|
MOCK(connection_stop_reading, note_read_stopped);
|
||||||
|
@ -552,26 +552,26 @@ test_ext_or_handshake(void *arg)
|
||||||
do_ext_or_handshake(conn);
|
do_ext_or_handshake(conn);
|
||||||
/* USERADDR command with an extra NUL byte */
|
/* USERADDR command with an extra NUL byte */
|
||||||
WRITE("\x00\x01\x00\x0d""1.2.3.4:5678\x00", 17);
|
WRITE("\x00\x01\x00\x0d""1.2.3.4:5678\x00", 17);
|
||||||
MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem);
|
MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
|
||||||
tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
|
tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
|
||||||
CONTAINS("", 0);
|
CONTAINS("", 0);
|
||||||
tt_assert(TO_CONN(conn)->marked_for_close);
|
tt_assert(TO_CONN(conn)->marked_for_close);
|
||||||
close_closeable_connections();
|
close_closeable_connections();
|
||||||
conn = NULL;
|
conn = NULL;
|
||||||
UNMOCK(control_event_bootstrap_problem);
|
UNMOCK(control_event_bootstrap_prob_or);
|
||||||
|
|
||||||
/* Now fail the TRANSPORT command. */
|
/* Now fail the TRANSPORT command. */
|
||||||
conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
|
conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
|
||||||
do_ext_or_handshake(conn);
|
do_ext_or_handshake(conn);
|
||||||
/* TRANSPORT command with an extra NUL byte */
|
/* TRANSPORT command with an extra NUL byte */
|
||||||
WRITE("\x00\x02\x00\x08""rfc1149\x00", 12);
|
WRITE("\x00\x02\x00\x08""rfc1149\x00", 12);
|
||||||
MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem);
|
MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
|
||||||
tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
|
tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
|
||||||
CONTAINS("", 0);
|
CONTAINS("", 0);
|
||||||
tt_assert(TO_CONN(conn)->marked_for_close);
|
tt_assert(TO_CONN(conn)->marked_for_close);
|
||||||
close_closeable_connections();
|
close_closeable_connections();
|
||||||
conn = NULL;
|
conn = NULL;
|
||||||
UNMOCK(control_event_bootstrap_problem);
|
UNMOCK(control_event_bootstrap_prob_or);
|
||||||
|
|
||||||
/* Now fail the TRANSPORT command. */
|
/* Now fail the TRANSPORT command. */
|
||||||
conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
|
conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
|
||||||
|
@ -579,13 +579,13 @@ test_ext_or_handshake(void *arg)
|
||||||
/* TRANSPORT command with transport name with symbols (not a
|
/* TRANSPORT command with transport name with symbols (not a
|
||||||
C-identifier) */
|
C-identifier) */
|
||||||
WRITE("\x00\x02\x00\x07""rf*1149", 11);
|
WRITE("\x00\x02\x00\x07""rf*1149", 11);
|
||||||
MOCK(control_event_bootstrap_problem, ignore_bootstrap_problem);
|
MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
|
||||||
tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
|
tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
|
||||||
CONTAINS("", 0);
|
CONTAINS("", 0);
|
||||||
tt_assert(TO_CONN(conn)->marked_for_close);
|
tt_assert(TO_CONN(conn)->marked_for_close);
|
||||||
close_closeable_connections();
|
close_closeable_connections();
|
||||||
conn = NULL;
|
conn = NULL;
|
||||||
UNMOCK(control_event_bootstrap_problem);
|
UNMOCK(control_event_bootstrap_prob_or);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
UNMOCK(connection_write_to_buf_impl_);
|
UNMOCK(connection_write_to_buf_impl_);
|
||||||
|
|
Loading…
Add table
Reference in a new issue