[tor-commits] [tor/master] Choose the correct dirport when contacting an authority.

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


commit ae0aff87ce321b2765a30472af9a2a310441408f
Author: Nick Mathewson <nickm at torproject.org>
Date:   Tue Feb 23 15:25:51 2021 -0500

    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).
---
 src/feature/dirclient/dirclient.c | 38 ++++++++++++++++++++++++++++++++++++--
 src/feature/nodelist/dirlist.c    | 39 ++++++++++++++++++++++++++++++++++++++-
 src/feature/nodelist/dirlist.h    |  6 ++++++
 3 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index a5dd856729..257cf2c72d 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -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:
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index c9d0a991e5..cc2795a5f5 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -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)
diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h
index 70bbb780d1..c17589c12e 100644
--- a/src/feature/nodelist/dirlist.h
+++ b/src/feature/nodelist/dirlist.h
@@ -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);





More information about the tor-commits mailing list