[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [tor/master] addr: New function relay_address_new_suggestion()



commit 192d367b411019760f92f58adde7592476341d6b
Author: David Goulet <dgoulet@xxxxxxxxxxxxxx>
Date:   Mon Jul 6 09:42:10 2020 -0400

    addr: New function relay_address_new_suggestion()
    
    This behaves like router_new_address_suggestion() but differs in couple of
    ways:
    
      1. It takes a tor_addr_t instead of an address string and supports both
         AF_INET and AF_INET6.
      2. It does _not_ use the last_guessed_ip local cache and instead only relies
         on the last resolved address cache in resolve_addr.c
    
    It is not used at this commit. This function is made to process a suggested
    address found in a NETINFO cell exactly like router_new_address_suggestion()
    does with the address a directory suggests us.
    
    Related to #40022
    
    Signed-off-by: David Goulet <dgoulet@xxxxxxxxxxxxxx>
---
 src/app/config/resolve_addr.c       | 29 ++++++++++++++++++++
 src/app/config/resolve_addr.h       |  3 +++
 src/feature/nodelist/dirlist.c      | 28 +++++++++++++++++++
 src/feature/nodelist/dirlist.h      |  5 ++++
 src/feature/relay/relay_find_addr.c | 54 +++++++++++++++++++++++++++++++++++++
 src/feature/relay/relay_find_addr.h |  3 +++
 6 files changed, 122 insertions(+)

diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c
index 2a11ba3c0..75b5eb75b 100644
--- a/src/app/config/resolve_addr.c
+++ b/src/app/config/resolve_addr.c
@@ -44,6 +44,12 @@ typedef enum {
 /** Last resolved addresses. */
 static tor_addr_t last_resolved_addrs[IDX_SIZE];
 
+/** Last suggested addresses.
+ *
+ * These addresses come from a NETINFO cell from a trusted relay (currently
+ * only authorities). We only use those in last resort. */
+static tor_addr_t last_suggested_addrs[IDX_SIZE];
+
 static inline int
 af_to_idx(const int family)
 {
@@ -60,6 +66,29 @@ af_to_idx(const int family)
   }
 }
 
+/** Copy the last suggested address of family into addr_out.
+ *
+ * If no last suggested address exists, the addr_out is a null address (use
+ * tor_addr_is_null() to confirm). */
+void
+resolved_addr_get_suggested(int family, tor_addr_t *addr_out)
+{
+  tor_addr_copy(addr_out, &last_suggested_addrs[af_to_idx(family)]);
+}
+
+/** Set the last suggested address into our cache. This is called when we get
+ * a new NETINFO cell from a trusted source. */
+void
+resolved_addr_set_suggested(const tor_addr_t *addr)
+{
+  if (BUG(tor_addr_family(addr) != AF_INET ||
+          tor_addr_family(addr) != AF_INET6)) {
+    return;
+  }
+  tor_addr_copy(&last_suggested_addrs[af_to_idx(tor_addr_family(addr))],
+                addr);
+}
+
 /** Copy the last resolved address of family into addr_out.
  *
  * If not last resolved address existed, the addr_out is a null address (use
diff --git a/src/app/config/resolve_addr.h b/src/app/config/resolve_addr.h
index 055d59a8f..7ba70541a 100644
--- a/src/app/config/resolve_addr.h
+++ b/src/app/config/resolve_addr.h
@@ -20,6 +20,9 @@ void resolved_addr_reset_last(int family);
 void resolved_addr_set_last(const tor_addr_t *addr, const char *method_used,
                             const char *hostname_used);
 
+void resolved_addr_get_suggested(int family, tor_addr_t *addr_out);
+void resolved_addr_set_suggested(const tor_addr_t *addr);
+
 MOCK_DECL(bool, is_local_to_resolve_addr, (const tor_addr_t *addr));
 
 #ifdef RESOLVE_ADDR_PRIVATE
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index bd647ab53..c1864faed 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -250,6 +250,34 @@ router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
   return 0;
 }
 
+/** 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. */
+bool
+router_addr_is_trusted_dir_type(const tor_addr_t *addr, dirinfo_type_t type)
+{
+  int family = tor_addr_family(addr);
+
+  if (!trusted_dir_servers) {
+    return false;
+  }
+
+  SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, dir_server_t *, ent) {
+    /* Ignore entries that don't match the given type. */
+    if (type != NO_DIRINFO && (type & ent->type) == 0) {
+      continue;
+    }
+    /* Match IPv4 or IPv6 address. */
+    if ((family == AF_INET && tor_addr_eq_ipv4h(addr, ent->addr)) ||
+        (family == AF_INET6 && tor_addr_eq(addr, &ent->ipv6_addr))) {
+      return true;
+    }
+  } SMARTLIST_FOREACH_END(ent);
+
+  return false;
+}
+
 /** 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
diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h
index 9201e76a9..c9310ff35 100644
--- a/src/feature/nodelist/dirlist.h
+++ b/src/feature/nodelist/dirlist.h
@@ -25,6 +25,11 @@ int router_digest_is_fallback_dir(const char *digest);
 MOCK_DECL(dir_server_t *, trusteddirserver_get_by_v3_auth_digest,
           (const char *d));
 
+bool router_addr_is_trusted_dir_type(const tor_addr_t *addr,
+                                     dirinfo_type_t type);
+#define router_addr_is_trusted_dir(d) \
+  router_addr_is_trusted_dir_type((d), NO_DIRINFO)
+
 int router_digest_is_trusted_dir_type(const char *digest,
                                       dirinfo_type_t type);
 #define router_digest_is_trusted_dir(d) \
diff --git a/src/feature/relay/relay_find_addr.c b/src/feature/relay/relay_find_addr.c
index a51457ddb..699eb7e38 100644
--- a/src/feature/relay/relay_find_addr.c
+++ b/src/feature/relay/relay_find_addr.c
@@ -15,6 +15,7 @@
 
 #include "feature/control/control_events.h"
 #include "feature/dircommon/dir_connection_st.h"
+#include "feature/nodelist/dirlist.h"
 #include "feature/relay/relay_find_addr.h"
 #include "feature/relay/router.h"
 #include "feature/relay/routermode.h"
@@ -37,6 +38,59 @@ router_guess_address_from_dir_headers(uint32_t *guess)
   return -1;
 }
 
+/** Consider the address suggestion suggested_addr as a possible one to use as
+ * our address.
+ *
+ * This is called when a valid NETINFO cell is recevied containing a candidate
+ * for our address.
+ *
+ * The suggested address is ignored if it does NOT come from a trusted source.
+ * At the moment, we only look a trusted directory authorities.
+ *
+ * The suggested address is ignored if it is internal or it is the same as the
+ * given peer_addr which is the address from the endpoint that sent the
+ * NETINFO cell.
+ *
+ * The suggested address is set in our suggested address cache if everything
+ * passes. */
+void
+relay_address_new_suggestion(const tor_addr_t *suggested_addr,
+                             const tor_addr_t *peer_addr)
+{
+  const or_options_t *options = get_options();
+
+  tor_assert(suggested_addr);
+  tor_assert(peer_addr);
+
+  /* This should never be called on a non Tor relay. */
+  if (BUG(!server_mode(options))) {
+    return;
+  }
+
+  /* Is the peer a trusted source? Ignore anything coming from non trusted
+   * source. In this case, we only look at trusted authorities. */
+  if (!router_addr_is_trusted_dir(peer_addr)) {
+    return;
+  }
+
+  /* Ignore a suggestion that is an internal address or the same as the one
+   * the peer address. */
+  if (tor_addr_is_internal(suggested_addr, 0)) {
+    /* Do not believe anyone who says our address is internal. */
+    return;
+  }
+  if (tor_addr_eq(suggested_addr, peer_addr)) {
+    /* Do not believe anyone who says our address is their address. */
+    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+           "A relay endpoint %s is telling us that their address is ours.",
+           fmt_addr(peer_addr));
+    return;
+  }
+
+  /* Save the suggestion in our cache. */
+  resolved_addr_set_suggested(suggested_addr);
+}
+
 /** A directory server <b>d_conn</b> told us our IP address is
  * <b>suggestion</b>.
  * If this address is different from the one we think we are now, and
diff --git a/src/feature/relay/relay_find_addr.h b/src/feature/relay/relay_find_addr.h
index ac51a977e..d856e706e 100644
--- a/src/feature/relay/relay_find_addr.h
+++ b/src/feature/relay/relay_find_addr.h
@@ -15,6 +15,9 @@ MOCK_DECL(int, router_pick_published_address,
 void router_new_address_suggestion(const char *suggestion,
                                    const dir_connection_t *d_conn);
 
+void relay_address_new_suggestion(const tor_addr_t *suggested_addr,
+                                  const tor_addr_t *peer_addr);
+
 #ifdef RELAY_FIND_ADDR_PRIVATE
 
 #endif /* RELAY_FIND_ADDR_PRIVATE */



_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits