aboutsummaryrefslogtreecommitdiff
path: root/src/feature/nodelist
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@torproject.org>2021-04-23 12:48:55 -0400
committerDavid Goulet <dgoulet@torproject.org>2021-04-23 12:48:55 -0400
commit3bd7367274576ca1b2229561e34044f86e26d337 (patch)
tree64c3c972eb993bfef79d61fb896e6d39b3e82614 /src/feature/nodelist
parent973fcf056a21087157e2f07ac94899521b50e1d4 (diff)
parentebb826f4a15c90d480bb5384facc9d05e13505ab (diff)
downloadtor-3bd7367274576ca1b2229561e34044f86e26d337.tar.gz
tor-3bd7367274576ca1b2229561e34044f86e26d337.zip
Merge branch 'tor-gitlab/mr/327'
Conflicts: src/test/test.c Minor comment issue.
Diffstat (limited to 'src/feature/nodelist')
-rw-r--r--src/feature/nodelist/dirlist.c147
-rw-r--r--src/feature/nodelist/dirlist.h35
2 files changed, 181 insertions, 1 deletions
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index 1f18bd71a2..57b55f0127 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -43,6 +43,14 @@
#include "feature/dirclient/dir_server_st.h"
#include "feature/nodelist/node_st.h"
+/** Information about an (HTTP) dirport for a directory authority. */
+struct auth_dirport_t {
+ /** What is the intended usage for this dirport? One of AUTH_USAGE_* */
+ auth_dirport_usage_t usage;
+ /** What is the correct address/port ? */
+ tor_addr_port_t dirport;
+};
+
/** Global list of a dir_server_t object for each directory
* authority. */
static smartlist_t *trusted_dir_servers = NULL;
@@ -66,6 +74,11 @@ add_trusted_dir_to_nodelist_addr_set(const dir_server_t *dir)
/* IPv6 DirPort is not a thing yet for authorities. */
nodelist_add_addr_to_address_set(&dir->ipv6_addr, dir->ipv6_orport, 0);
}
+ if (dir->auth_dirports) {
+ SMARTLIST_FOREACH_BEGIN(dir->auth_dirports, const auth_dirport_t *, p) {
+ nodelist_add_addr_to_address_set(&p->dirport.addr, 0, p->dirport.port);
+ } SMARTLIST_FOREACH_END(p);
+ }
}
/** Go over the trusted directory server list and add their address(es) to the
@@ -256,7 +269,10 @@ MOCK_IMPL(int, router_digest_is_trusted_dir_type,
/** Return true iff the given address matches a trusted directory that matches
* at least one bit of type.
*
- * If type is NO_DIRINFO or ALL_DIRINFO, any authority is matched. */
+ * If type is NO_DIRINFO or ALL_DIRINFO, any authority is matched.
+ *
+ * Only ORPorts' addresses are considered.
+ */
bool
router_addr_is_trusted_dir_type(const tor_addr_t *addr, dirinfo_type_t type)
{
@@ -281,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
@@ -357,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;
}
@@ -404,10 +457,98 @@ trusted_dir_server_new(const char *nickname, const char *address,
ipv6_addrport,
digest,
v3_auth_digest, type, weight);
+
+ if (ipv4_dirport) {
+ tor_addr_port_t p;
+ memset(&p, 0, sizeof(p));
+ tor_addr_copy(&p.addr, &ipv4_addr);
+ p.port = ipv4_dirport;
+ trusted_dir_server_add_dirport(result, AUTH_USAGE_LEGACY, &p);
+ }
tor_free(hostname);
return result;
}
+/**
+ * Add @a dirport as an HTTP DirPort contact point for the directory authority
+ * @a ds, for use when contacting that authority for the given @a usage.
+ *
+ * Multiple ports of the same usage are allowed; if present, then only
+ * the first one of each address family is currently used.
+ */
+void
+trusted_dir_server_add_dirport(dir_server_t *ds,
+ auth_dirport_usage_t usage,
+ const tor_addr_port_t *dirport)
+{
+ tor_assert(ds);
+ tor_assert(dirport);
+
+ if (BUG(! ds->is_authority)) {
+ return;
+ }
+
+ if (ds->auth_dirports == NULL) {
+ ds->auth_dirports = smartlist_new();
+ }
+
+ auth_dirport_t *port = tor_malloc_zero(sizeof(auth_dirport_t));
+ port->usage = usage;
+ tor_addr_port_copy(&port->dirport, dirport);
+ smartlist_add(ds->auth_dirports, port);
+}
+
+/**
+ * Helper for trusted_dir_server_get_dirport: only return the exact requested
+ * usage type.
+ */
+const tor_addr_port_t *
+trusted_dir_server_get_dirport_exact(const dir_server_t *ds,
+ auth_dirport_usage_t usage,
+ int addr_family)
+{
+ tor_assert(ds);
+ tor_assert_nonfatal(addr_family == AF_INET || addr_family == AF_INET6);
+ if (ds->auth_dirports == NULL)
+ return NULL;
+
+ SMARTLIST_FOREACH_BEGIN(ds->auth_dirports, const auth_dirport_t *, port) {
+ if (port->usage == usage &&
+ tor_addr_family(&port->dirport.addr) == addr_family) {
+ return &port->dirport;
+ }
+ } SMARTLIST_FOREACH_END(port);
+
+ return NULL;
+}
+
+/**
+ * Return the DirPort of the authority @a ds for with the usage type
+ * @a usage and address family @a addr_family. If none is found, try
+ * again with an AUTH_USAGE_LEGACY dirport, if there is one. Return NULL
+ * if no port can be found.
+ */
+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 *port;
+
+ while (1) {
+ port = trusted_dir_server_get_dirport_exact(ds, usage, addr_family);
+ if (port)
+ return port;
+
+ // If we tried LEGACY, there is no fallback from this point.
+ if (usage == AUTH_USAGE_LEGACY)
+ return NULL;
+
+ // Try again with LEGACY.
+ usage = AUTH_USAGE_LEGACY;
+ }
+}
+
/** Return a new dir_server_t for a fallback directory server at
* <b>addr</b>:<b>or_port</b>/<b>dir_port</b>, with identity key digest
* <b>id_digest</b> */
@@ -447,6 +588,10 @@ dir_server_free_(dir_server_t *ds)
if (!ds)
return;
+ if (ds->auth_dirports) {
+ SMARTLIST_FOREACH(ds->auth_dirports, auth_dirport_t *, p, tor_free(p));
+ smartlist_free(ds->auth_dirports);
+ }
tor_free(ds->nickname);
tor_free(ds->description);
tor_free(ds->address);
diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h
index f744fecf92..3b4faf07af 100644
--- a/src/feature/nodelist/dirlist.h
+++ b/src/feature/nodelist/dirlist.h
@@ -11,6 +11,28 @@
#ifndef TOR_DIRLIST_H
#define TOR_DIRLIST_H
+typedef struct auth_dirport_t auth_dirport_t;
+/**
+ * Different usages for an authority's HTTP directory port.
+ *
+ * Historically, only legacy ports existed; proposal 330 added multiple types
+ * of dirport to better enable authorities to offload work and resist DoS
+ * attacks.
+ **/
+typedef enum auth_dirport_usage_t {
+ /** Flag for an authority's dirport that is intended for misc/legacy
+ * usage. May be used when no other dirport is available. */
+ AUTH_USAGE_LEGACY,
+ /** Flag for an authority's dirport that is intended for descriptor uploads
+ * only. */
+ AUTH_USAGE_UPLOAD,
+ /** Flag for an authority's dirport that is intended for voting only */
+ AUTH_USAGE_VOTING,
+ /** Flag for an authority's dirport that is intended for relay downloads
+ * only. */
+ AUTH_USAGE_DOWNLOAD,
+} auth_dirport_usage_t;
+
int get_n_authorities(dirinfo_type_t type);
const smartlist_t *router_get_trusted_dir_servers(void);
const smartlist_t *router_get_fallback_dir_servers(void);
@@ -18,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);
@@ -28,6 +52,14 @@ MOCK_DECL(dir_server_t *, trusteddirserver_get_by_v3_auth_digest,
MOCK_DECL(int, router_digest_is_trusted_dir_type,
(const char *digest, dirinfo_type_t 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);
#define router_addr_is_trusted_dir(d) \
@@ -41,6 +73,9 @@ dir_server_t *trusted_dir_server_new(const char *nickname, const char *address,
const tor_addr_port_t *addrport_ipv6,
const char *digest, const char *v3_auth_digest,
dirinfo_type_t type, double weight);
+void trusted_dir_server_add_dirport(dir_server_t *ds,
+ auth_dirport_usage_t usage,
+ const tor_addr_port_t *dirport);
dir_server_t *fallback_dir_server_new(const tor_addr_t *addr,
uint16_t dir_port, uint16_t or_port,
const tor_addr_port_t *addrport_ipv6,