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

[or-cvs] [tor/master] Let bridge users use the non-primary address of a multi-homed bridge



Author: Roger Dingledine <arma@xxxxxxxxxxxxxx>
Date: Thu, 3 Jun 2010 20:29:29 -0400
Subject: Let bridge users use the non-primary address of a multi-homed bridge
Commit: 7e300cbba36a0716b8d4ca6373ffbe372fca9713

---
 changes/bait-and-switch-bridges |    8 +++++++
 src/or/circuitbuild.c           |   41 ++++++++++++++++++++++++++++++++------
 src/or/connection_or.c          |   15 ++++++++++---
 src/or/or.h                     |    2 +
 4 files changed, 55 insertions(+), 11 deletions(-)
 create mode 100644 changes/bait-and-switch-bridges

diff --git a/changes/bait-and-switch-bridges b/changes/bait-and-switch-bridges
new file mode 100644
index 0000000..5b89c4e
--- /dev/null
+++ b/changes/bait-and-switch-bridges
@@ -0,0 +1,8 @@
+  o Minor bugfixes:
+    - If you run a bridge that listens on multiple IP addresses, and
+      some user configures a bridge address that uses a different IP
+      address than your bridge writes in its router descriptor, and the
+      user doesn't specify an identity key, their Tor would discard the
+      descriptor because "it isn't one of our configured bridges", and
+      fail to bootstrap. Now believe the descriptor and bootstrap anyway.
+      Bugfix on 0.2.0.3-alpha.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index fff56f0..417d8ec 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -4053,29 +4053,56 @@ clear_bridge_list(void)
  * (either by comparing keys if possible, else by comparing addr/port).
  * Else return NULL. */
 static bridge_info_t *
-routerinfo_get_configured_bridge(routerinfo_t *ri)
+get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port,
+                                          const char *digest)
 {
   if (!bridge_list)
     return NULL;
   SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
     {
       if (tor_digest_is_zero(bridge->identity) &&
-          tor_addr_eq_ipv4h(&bridge->addr, ri->addr) &&
-          bridge->port == ri->or_port)
+          !tor_addr_compare(&bridge->addr, addr, CMP_EXACT) &&
+          bridge->port == port)
         return bridge;
-      if (!memcmp(bridge->identity, ri->cache_info.identity_digest,
-                  DIGEST_LEN))
+      if (!memcmp(bridge->identity, digest, DIGEST_LEN))
         return bridge;
     }
   SMARTLIST_FOREACH_END(bridge);
   return NULL;
 }
 
+/** Wrapper around get_configured_bridge_by_addr_port_digest() to look
+ * it up via router descriptor <b>ri</b>. */
+static bridge_info_t *
+get_configured_bridge_by_routerinfo(routerinfo_t *ri)
+{
+  tor_addr_t addr;
+  tor_addr_from_ipv4h(&addr, ri->addr);
+  return get_configured_bridge_by_addr_port_digest(&addr,
+                              ri->or_port, ri->cache_info.identity_digest);
+}
+
 /** Return 1 if <b>ri</b> is one of our known bridges, else 0. */
 int
 routerinfo_is_a_configured_bridge(routerinfo_t *ri)
 {
-  return routerinfo_get_configured_bridge(ri) ? 1 : 0;
+  return get_configured_bridge_by_routerinfo(ri) ? 1 : 0;
+}
+
+/** We made a connection to a router at <b>addr</b>:<b>port</b>
+ * without knowing its digest. Its digest turned out to be <b>digest</b>.
+ * If it was a bridge, and we still don't know its digest, record it.
+ */
+void
+learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest)
+{
+  bridge_info_t *bridge =
+    get_configured_bridge_by_addr_port_digest(addr, port, digest);
+  if (bridge && tor_digest_is_zero(bridge->identity)) {
+    memcpy(bridge->identity, digest, DIGEST_LEN);
+    log_notice(LD_DIR, "Learned fingerprint %s for bridge %s:%d",
+               hex_str(digest, DIGEST_LEN), fmt_addr(addr), port);
+  }
 }
 
 /** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b>
@@ -4215,7 +4242,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
   tor_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE);
   if (get_options()->UseBridges) {
     int first = !any_bridge_descriptors_known();
-    bridge_info_t *bridge = routerinfo_get_configured_bridge(ri);
+    bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri);
     time_t now = time(NULL);
     ri->is_running = 1;
 
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index cdb4646..247cc4e 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -926,16 +926,19 @@ connection_or_nonopen_was_started_here(or_connection_t *conn)
  * the certificate to be weird or absent.
  *
  * If we return 0, and the certificate is as expected, write a hash of the
- * identity key into digest_rcvd, which must have DIGEST_LEN space in it. (If
- * we return -1 this buffer is undefined.)  If the certificate is invalid
- * or missing on an incoming connection, we return 0 and set digest_rcvd to
- * DIGEST_LEN 0 bytes.
+ * identity key into <b>digest_rcvd_out</b>, which must have DIGEST_LEN
+ * space in it.
+ * If the certificate is invalid or missing on an incoming connection,
+ * we return 0 and set <b>digest_rcvd_out</b> to DIGEST_LEN NUL bytes.
+ * (If we return -1, the contents of this buffer are undefined.)
  *
  * As side effects,
  * 1) Set conn->circ_id_type according to tor-spec.txt.
  * 2) If we're an authdirserver and we initiated the connection: drop all
  *    descriptors that claim to be on that IP/port but that aren't
  *    this guy; and note that this guy is reachable.
+ * 3) If this is a bridge and we didn't configure its identity
+ *    fingerprint, remember the keyid we just learned.
  */
 static int
 connection_or_check_valid_tls_handshake(or_connection_t *conn,
@@ -1007,6 +1010,10 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
     log_info(LD_HANDSHAKE, "Connected to router %s at %s:%d without knowing "
                     "its key. Hoping for the best.",
                     conn->nickname, conn->_base.address, conn->_base.port);
+    /* if it's a bridge and we didn't know its identity fingerprint, now
+     * we do -- remember it for future attempts. */
+    learned_router_identity(&conn->_base.addr, conn->_base.port,
+                            digest_rcvd_out);
   }
 
   if (started_here) {
diff --git a/src/or/or.h b/src/or/or.h
index ec8dd3a..832bdd6 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2997,6 +2997,8 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
 
 void clear_bridge_list(void);
 int routerinfo_is_a_configured_bridge(routerinfo_t *ri);
+void
+learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest);
 void bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
                             char *digest);
 void retry_bridge_descriptor_fetch_directly(const char *digest);
-- 
1.6.5