mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Allow asking a bridge's own descriptor over one-hop connection
When we refactored purpose_needs_anonymity(), we made it so _all_ bridge requests required anonymity. But that missed the case that we are allowed to ask a bridge for its own descriptor. With this patch, we consider the resource, and allow "authority.z" ("your own descriptor, compressed") for a bridge's server descriptor to be non-anonymous. Fix for bug 20410; bug not in any released Tor.
This commit is contained in:
parent
01482e30ad
commit
8cc528c750
@ -2434,7 +2434,9 @@ connection_ap_handshake_send_begin(entry_connection_t *ap_conn)
|
||||
* Otherwise, directory connections are typically one-hop.
|
||||
* This matches the earlier check for directory connection path anonymity
|
||||
* in directory_initiate_command_rend(). */
|
||||
if (purpose_needs_anonymity(linked_dir_conn_base->purpose, 0)) {
|
||||
if (purpose_needs_anonymity(linked_dir_conn_base->purpose,
|
||||
TO_DIR_CONN(linked_dir_conn_base)->router_purpose,
|
||||
TO_DIR_CONN(linked_dir_conn_base)->requested_resource)) {
|
||||
assert_circ_anonymity_ok(circ, options);
|
||||
}
|
||||
} else {
|
||||
|
@ -127,14 +127,23 @@ static void connection_dir_close_consensus_fetches(
|
||||
* specifically been configured to be over an anonymous connection,
|
||||
* or 3) if the router is a bridge */
|
||||
int
|
||||
purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
|
||||
purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
const char *resource)
|
||||
{
|
||||
if (get_options()->AllDirActionsPrivate)
|
||||
return 1;
|
||||
|
||||
if (router_purpose == ROUTER_PURPOSE_BRIDGE)
|
||||
if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
|
||||
if (dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC
|
||||
&& resource && !strcmp(resource, "authority.z")) {
|
||||
/* We are asking a bridge for its own descriptor. That doesn't need
|
||||
anonymity. */
|
||||
return 0;
|
||||
}
|
||||
/* Assume all other bridge stuff needs anonymity. */
|
||||
return 1; /* if no circuits yet, this might break bootstrapping, but it's
|
||||
* needed to be safe. */
|
||||
}
|
||||
|
||||
switch (dir_purpose)
|
||||
{
|
||||
@ -364,7 +373,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
|
||||
(int) extrainfo_len);
|
||||
}
|
||||
if (purpose_needs_anonymity(dir_purpose, router_purpose)) {
|
||||
if (purpose_needs_anonymity(dir_purpose, router_purpose, NULL)) {
|
||||
indirection = DIRIND_ANONYMOUS;
|
||||
} else if (!fascist_firewall_allows_dir_server(ds,
|
||||
FIREWALL_DIR_CONNECTION,
|
||||
@ -458,7 +467,8 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
|
||||
int prefer_authority = (directory_fetches_from_authorities(options)
|
||||
|| want_authority == DL_WANT_AUTHORITY);
|
||||
int require_authority = 0;
|
||||
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
|
||||
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose,
|
||||
resource);
|
||||
dirinfo_type_t type = dir_fetch_type(dir_purpose, router_purpose, resource);
|
||||
time_t if_modified_since = 0;
|
||||
|
||||
@ -592,7 +602,7 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
|
||||
"While fetching directory info, "
|
||||
"no running dirservers known. Will try again later. "
|
||||
"(purpose %d)", dir_purpose);
|
||||
if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
|
||||
if (!purpose_needs_anonymity(dir_purpose, router_purpose, resource)) {
|
||||
/* remember we tried them all and failed. */
|
||||
directory_all_unreachable(time(NULL));
|
||||
}
|
||||
@ -1142,7 +1152,7 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
|
||||
|
||||
log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
|
||||
|
||||
if (purpose_needs_anonymity(dir_purpose, router_purpose)) {
|
||||
if (purpose_needs_anonymity(dir_purpose, router_purpose, resource)) {
|
||||
tor_assert(anonymized_connection ||
|
||||
rend_non_anonymous_mode_enabled(options));
|
||||
}
|
||||
|
@ -132,7 +132,8 @@ int download_status_get_n_failures(const download_status_t *dls);
|
||||
int download_status_get_n_attempts(const download_status_t *dls);
|
||||
time_t download_status_get_next_attempt_at(const download_status_t *dls);
|
||||
|
||||
int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose);
|
||||
int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
const char *resource);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
/* Used only by directory.c and test_dir.c */
|
||||
|
@ -929,7 +929,8 @@ authority_certs_fetch_resource_impl(const char *resource,
|
||||
const routerstatus_t *rs)
|
||||
{
|
||||
const or_options_t *options = get_options();
|
||||
int get_via_tor = purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0);
|
||||
int get_via_tor = purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0,
|
||||
resource);
|
||||
|
||||
/* Make sure bridge clients never connect to anything but a bridge */
|
||||
if (options->UseBridges) {
|
||||
|
@ -3258,7 +3258,7 @@ test_dir_purpose_needs_anonymity_returns_true_by_default(void *arg)
|
||||
(void)arg;
|
||||
|
||||
tor_capture_bugs_(1);
|
||||
tt_int_op(1, ==, purpose_needs_anonymity(0, 0));
|
||||
tt_int_op(1, ==, purpose_needs_anonymity(0, 0, NULL));
|
||||
tt_int_op(1, ==, smartlist_len(tor_get_captured_bug_log_()));
|
||||
tor_end_capture_bugs_();
|
||||
done: ;
|
||||
@ -3269,9 +3269,21 @@ test_dir_purpose_needs_anonymity_returns_true_for_bridges(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE));
|
||||
tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE, NULL));
|
||||
tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE,
|
||||
"foobar"));
|
||||
tt_int_op(1, ==, purpose_needs_anonymity(DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2,
|
||||
ROUTER_PURPOSE_BRIDGE));
|
||||
ROUTER_PURPOSE_BRIDGE, NULL));
|
||||
done: ;
|
||||
}
|
||||
|
||||
static void
|
||||
test_dir_purpose_needs_anonymity_returns_false_for_own_bridge_desc(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC,
|
||||
ROUTER_PURPOSE_BRIDGE,
|
||||
"authority.z"));
|
||||
done: ;
|
||||
}
|
||||
|
||||
@ -3282,11 +3294,11 @@ test_dir_purpose_needs_anonymity_returns_true_for_sensitive_purpose(void *arg)
|
||||
|
||||
tt_int_op(1, ==, purpose_needs_anonymity(
|
||||
DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2,
|
||||
ROUTER_PURPOSE_GENERAL));
|
||||
ROUTER_PURPOSE_GENERAL, NULL));
|
||||
tt_int_op(1, ==, purpose_needs_anonymity(
|
||||
DIR_PURPOSE_UPLOAD_RENDDESC_V2, 0));
|
||||
DIR_PURPOSE_UPLOAD_RENDDESC_V2, 0, NULL));
|
||||
tt_int_op(1, ==, purpose_needs_anonymity(
|
||||
DIR_PURPOSE_FETCH_RENDDESC_V2, 0));
|
||||
DIR_PURPOSE_FETCH_RENDDESC_V2, 0, NULL));
|
||||
done: ;
|
||||
}
|
||||
|
||||
@ -3296,17 +3308,24 @@ test_dir_purpose_needs_anonymity_ret_false_for_non_sensitive_conn(void *arg)
|
||||
(void)arg;
|
||||
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_DIR,
|
||||
ROUTER_PURPOSE_GENERAL));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_VOTE, 0));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_SIGNATURES, 0));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_STATUS_VOTE, 0));
|
||||
ROUTER_PURPOSE_GENERAL, NULL));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_VOTE, 0, NULL));
|
||||
tt_int_op(0, ==,
|
||||
purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_SIGNATURES, 0, NULL));
|
||||
tt_int_op(0, ==,
|
||||
purpose_needs_anonymity(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(
|
||||
DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_CONSENSUS, 0));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, 0));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_EXTRAINFO, 0));
|
||||
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC, 0));
|
||||
DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, NULL));
|
||||
tt_int_op(0, ==,
|
||||
purpose_needs_anonymity(DIR_PURPOSE_FETCH_CONSENSUS, 0, NULL));
|
||||
tt_int_op(0, ==,
|
||||
purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0, NULL));
|
||||
tt_int_op(0, ==,
|
||||
purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, 0, NULL));
|
||||
tt_int_op(0, ==,
|
||||
purpose_needs_anonymity(DIR_PURPOSE_FETCH_EXTRAINFO, 0, NULL));
|
||||
tt_int_op(0, ==,
|
||||
purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC, 0, NULL));
|
||||
done: ;
|
||||
}
|
||||
|
||||
@ -5512,6 +5531,7 @@ struct testcase_t dir_tests[] = {
|
||||
DIR(dirserv_set_routerstatus_testing, 0),
|
||||
DIR(http_handling, 0),
|
||||
DIR(purpose_needs_anonymity_returns_true_for_bridges, 0),
|
||||
DIR(purpose_needs_anonymity_returns_false_for_own_bridge_desc, 0),
|
||||
DIR(purpose_needs_anonymity_returns_true_by_default, 0),
|
||||
DIR(purpose_needs_anonymity_returns_true_for_sensitive_purpose, 0),
|
||||
DIR(purpose_needs_anonymity_ret_false_for_non_sensitive_conn, 0),
|
||||
|
Loading…
Reference in New Issue
Block a user