[tor-commits] [tor/master] Add support for knowing multiple HTTP DirPorts for an authority.

dgoulet at torproject.org dgoulet at torproject.org
Fri Apr 23 16:55:30 UTC 2021


commit 4e977cce40ed95f4f25f8511eb8791072d691c93
Author: Nick Mathewson <nickm at torproject.org>
Date:   Tue Feb 23 14:09:03 2021 -0500

    Add support for knowing multiple HTTP DirPorts for an authority.
    
    (These aren't yet set or used.)
---
 src/feature/dirclient/dir_server_st.h |   6 ++
 src/feature/nodelist/dirlist.c        | 110 +++++++++++++++++++++++++++++++++-
 src/feature/nodelist/dirlist.h        |  29 +++++++++
 3 files changed, 144 insertions(+), 1 deletion(-)

diff --git a/src/feature/dirclient/dir_server_st.h b/src/feature/dirclient/dir_server_st.h
index 57530a571b..d1ecbcf515 100644
--- a/src/feature/dirclient/dir_server_st.h
+++ b/src/feature/dirclient/dir_server_st.h
@@ -16,6 +16,8 @@
 #include "core/or/or.h"
 #include "feature/nodelist/routerstatus_st.h"
 
+struct smartlist_t;
+
 /** Represents information about a single trusted or fallback directory
  * server. */
 struct dir_server_t {
@@ -48,6 +50,10 @@ struct dir_server_t {
   time_t addr_current_at; /**< When was the document that we derived the
                            * address information from published? */
 
+  /** Authority only.  Can be null. If present, a list of auth_dirport_t
+   * representing HTTP dirports for this authority. */
+  struct smartlist_t *auth_dirports;
+
   routerstatus_t fake_status; /**< Used when we need to pass this trusted
                                * dir_server_t to
                                * directory_request_set_routerstatus.
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index 423c4106e2..c9d0a991e5 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)
 {
@@ -404,10 +420,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.
+ */
+static 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 +551,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 ae3debf4e5..70bbb780d1 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);
@@ -28,6 +50,10 @@ 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);
+
 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 +67,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,





More information about the tor-commits mailing list