Choose the correct dirport when contacting an authority.

This is part of an implementation for proposal 330.

This implementation doesn't handle authdirs' IPv6 dirports (yet).
This commit is contained in:
Nick Mathewson
2021-02-23 15:25:51 -05:00
parent 4e977cce40
commit ae0aff87ce
3 changed files with 80 additions and 3 deletions
+36 -2
View File
@@ -1164,6 +1164,7 @@ directory_request_set_routerstatus(directory_request_t *req,
{
req->routerstatus = status;
}
/**
* Helper: update the addresses, ports, and identities in <b>req</b>
* from the routerstatus object in <b>req</b>. Return 0 on success.
@@ -1206,7 +1207,7 @@ directory_request_set_dir_from_routerstatus(directory_request_t *req)
return -1;
}
/* At this point, if we are a client making a direct connection to a
/* At this point, if we are a client making a direct connection to a
* directory server, we have selected a server that has at least one address
* allowed by ClientUseIPv4/6 and Reachable{"",OR,Dir}Addresses. This
* selection uses the preference in ClientPreferIPv6{OR,Dir}Port, if
@@ -1221,6 +1222,37 @@ directory_request_set_dir_from_routerstatus(directory_request_t *req)
return -1;
}
/* One last thing: If we're talking to an authority, we might want to use
* a special HTTP port for it based on our purpose.
*/
if (req->indirection == DIRIND_DIRECT_CONN && status->is_authority) {
const dir_server_t *ds = router_get_trusteddirserver_by_digest(
status->identity_digest);
if (ds) {
const tor_addr_port_t *v4 = NULL;
if (authdir_mode_v3(get_options())) {
// An authority connecting to another authority should always
// prefer the VOTING usage, if one is specifically configured.
v4 = trusted_dir_server_get_dirport_exact(
ds, AUTH_USAGE_VOTING, AF_INET);
}
if (! v4) {
// Everybody else should prefer a usage dependent on their
// the dir_purpose.
auth_dirport_usage_t usage =
auth_dirport_usage_for_purpose(req->dir_purpose);
v4 = trusted_dir_server_get_dirport(ds, usage, AF_INET);
}
tor_assert_nonfatal(v4);
if (v4) {
// XXXX We could, if we wanted, also select a v6 address. But a v4
// address must exist here, and we as a relay are required to support
// ipv4. So we just that.
tor_addr_port_copy(&use_dir_ap, v4);
}
}
}
directory_request_set_or_addr_port(req, &use_or_ap);
directory_request_set_dir_addr_port(req, &use_dir_ap);
directory_request_set_directory_id_digest(req, status->identity_digest);
@@ -1239,7 +1271,7 @@ directory_initiate_request,(directory_request_t *request))
tor_assert_nonfatal(
! directory_request_dir_contact_info_specified(request));
if (directory_request_set_dir_from_routerstatus(request) < 0) {
return;
return; // or here XXXX
}
}
@@ -1363,6 +1395,8 @@ directory_initiate_request,(directory_request_t *request))
entry_guard_cancel(&guard_state);
}
// XXXX This is the case where we replace.
switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr,
port, &socket_error)) {
case -1:
+38 -1
View File
@@ -297,6 +297,42 @@ router_addr_is_trusted_dir_type(const tor_addr_t *addr, dirinfo_type_t type)
return false;
}
/** Return an appropriate usage value describing which authdir port to use
* for a given directory connection purpose.
*/
auth_dirport_usage_t
auth_dirport_usage_for_purpose(int purpose)
{
switch (purpose) {
case DIR_PURPOSE_FETCH_SERVERDESC:
case DIR_PURPOSE_FETCH_EXTRAINFO:
case DIR_PURPOSE_FETCH_CONSENSUS:
case DIR_PURPOSE_FETCH_CERTIFICATE:
case DIR_PURPOSE_FETCH_MICRODESC:
return AUTH_USAGE_DOWNLOAD;
case DIR_PURPOSE_UPLOAD_DIR:
return AUTH_USAGE_UPLOAD;
case DIR_PURPOSE_UPLOAD_VOTE:
case DIR_PURPOSE_UPLOAD_SIGNATURES:
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
case DIR_PURPOSE_FETCH_STATUS_VOTE:
return AUTH_USAGE_VOTING;
case DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2:
case DIR_PURPOSE_SERVER:
case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
case DIR_PURPOSE_FETCH_RENDDESC_V2:
case DIR_PURPOSE_UPLOAD_HSDESC:
case DIR_PURPOSE_FETCH_HSDESC:
case DIR_PURPOSE_HAS_FETCHED_HSDESC:
default:
tor_assert_nonfatal_unreached();
return AUTH_USAGE_LEGACY;
}
}
/** Create a directory server at <b>address</b>:<b>port</b>, with OR identity
* key <b>digest</b> which has DIGEST_LEN bytes. If <b>address</b> is NULL,
* add ourself. If <b>is_authority</b>, this is a directory authority. Return
@@ -373,6 +409,7 @@ dir_server_new(int is_authority,
ent->fake_status.ipv4_dirport = ent->ipv4_dirport;
ent->fake_status.ipv4_orport = ent->ipv4_orport;
ent->fake_status.ipv6_orport = ent->ipv6_orport;
ent->fake_status.is_authority = !! is_authority;
return ent;
}
@@ -465,7 +502,7 @@ trusted_dir_server_add_dirport(dir_server_t *ds,
* Helper for trusted_dir_server_get_dirport: only return the exact requested
* usage type.
*/
static const tor_addr_port_t *
const tor_addr_port_t *
trusted_dir_server_get_dirport_exact(const dir_server_t *ds,
auth_dirport_usage_t usage,
int addr_family)
+6
View File
@@ -40,6 +40,8 @@ smartlist_t *router_get_trusted_dir_servers_mutable(void);
smartlist_t *router_get_fallback_dir_servers_mutable(void);
void mark_all_dirservers_up(smartlist_t *server_list);
auth_dirport_usage_t auth_dirport_usage_for_purpose(int purpose);
dir_server_t *router_get_trusteddirserver_by_digest(const char *d);
dir_server_t *router_get_fallback_dirserver_by_digest(
const char *digest);
@@ -53,6 +55,10 @@ MOCK_DECL(int, router_digest_is_trusted_dir_type,
const tor_addr_port_t *trusted_dir_server_get_dirport(const dir_server_t *ds,
auth_dirport_usage_t usage,
int addr_family);
const tor_addr_port_t *trusted_dir_server_get_dirport_exact(
const dir_server_t *ds,
auth_dirport_usage_t usage,
int addr_family);
bool router_addr_is_trusted_dir_type(const tor_addr_t *addr,
dirinfo_type_t type);