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

[or-cvs] [tor/master 1/6] Fall back to direct descriptor request to bridges when requests to authorities fail due to a network error.



Author: Robert Hogan <robert@xxxxxxxxxxxxxxx>
Date: Tue, 10 Aug 2010 22:07:50 +0100
Subject: Fall back to direct descriptor request to bridges when
Commit: d6744d611f933e77398ed80ac45cabfec16430c1

Bug#1138
"When a Tor client starts up using a bridge, and UpdateBridgesFromAuthority
is set, Tor will go to the authority first and look up the bridge by
fingerprint. If the bridge authority is filtered, Tor will never notice that
the bridge authority lookup failed. So it will never fall back."

Add connection_dir_bridge_routerdesc_failed(), a function for unpacking
the bridge information from a failed request, and ensure
connection_dir_request_failed() calls it if the failed request
was for a bridge descriptor.

Test:

1. for ip in `grep -iR 'router ' cached-descriptors|cut -d ' ' -f 3`;
do sudo iptables -A OUTPUT -p tcp -d $ip -j DROP; done
2. remove all files from user tor directory
3. Put the following in torrc:

UseBridges 1
UpdateBridgesFromAuthority 1
Bridge 85.108.88.19:443 7E1B28DB47C175392A0E8E4A287C7CB8686575B7

4. Launch tor - it should fall back to downloading descriptors
   directly from the bridge.

Initial patch reviewed and corrected by mingw-san.
---
 changes/bug1138    |    5 ++++
 src/or/directory.c |   64 ++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 57 insertions(+), 12 deletions(-)
 create mode 100644 changes/bug1138

diff --git a/changes/bug1138 b/changes/bug1138
new file mode 100644
index 0000000..ffb83bd
--- /dev/null
+++ b/changes/bug1138
@@ -0,0 +1,5 @@
+  o Major bugfixes:
+    - Fall back to direct descriptor request to bridges when
+      requests to authorities fail due to a network error.
+      Bugfix in 0.2.1.19, closes bug 1138.
+
diff --git a/src/or/directory.c b/src/or/directory.c
index a3e575a..11dce8c 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -67,8 +67,10 @@ static void http_set_address_origin(const char *headers, connection_t *conn);
 static void connection_dir_download_networkstatus_failed(
                                dir_connection_t *conn, int status_code);
 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
+static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn);
 static void connection_dir_download_cert_failed(
                                dir_connection_t *conn, int status_code);
+static void connection_dir_retry_bridges(smartlist_t* failed, int was_ei);
 static void dir_networkstatus_download_failed(smartlist_t *failed,
                                               int status_code);
 static void dir_routerdesc_download_failed(smartlist_t *failed,
@@ -592,6 +594,8 @@ connection_dir_request_failed(dir_connection_t *conn)
              conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
     log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
              conn->_base.address);
+    if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
+      connection_dir_bridge_routerdesc_failed(conn);
     connection_dir_download_routerdesc_failed(conn);
   } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
     networkstatus_consensus_download_failed(0);
@@ -645,6 +649,25 @@ connection_dir_download_networkstatus_failed(dir_connection_t *conn,
   }
 }
 
+/** Helper: Attempt to fetch directly the descriptors of each bridge
+ * listed in <b>failed</b>.
+ */
+static void
+connection_dir_retry_bridges(smartlist_t* failed, int was_ei)
+{
+  char digest[DIGEST_LEN];
+  tor_assert(!was_ei); /* not supported yet */
+  SMARTLIST_FOREACH(failed, const char *, cp,
+  {
+    if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
+      log_warn(LD_BUG, "Malformed fingerprint in list: %s",
+              escaped(cp));
+      continue;
+    }
+    retry_bridge_descriptor_fetch_directly(digest);
+  });
+}
+
 /** Called when an attempt to download one or more router descriptors
  * or extra-info documents on connection <b>conn</b> failed.
  */
@@ -662,6 +685,33 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn)
   (void) conn;
 }
 
+/** Called when an attempt to download a bridge's routerdesc from
+ * one of the authorities failed due to a network error. If
+ * possible attempt to download descriptors from the bridge directly.
+ */
+static void
+connection_dir_bridge_routerdesc_failed(dir_connection_t *conn)
+{
+  int was_ei;
+  smartlist_t *which = NULL;
+
+  /* Requests for bridge descriptors are in the form 'fp/', so ignore
+     anything else. */
+  if (conn->requested_resource && strcmpstart(conn->requested_resource,"fp/"))
+    return;
+
+  which = smartlist_create();
+  dir_split_resource_into_fingerprints(conn->requested_resource + 3,
+                                        which, NULL, 0);
+
+  was_ei =  conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
+  if (smartlist_len(which)) {
+    connection_dir_retry_bridges(which, was_ei);
+    SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
+  }
+  smartlist_free(which);
+}
+
 /** Called when an attempt to fetch a certificate fails. */
 static void
 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
@@ -3498,18 +3548,8 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
   time_t now = time(NULL);
   int server = directory_fetches_from_authorities(get_options());
   if (!was_descriptor_digests) {
-    if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
-      tor_assert(!was_extrainfo); /* not supported yet */
-      SMARTLIST_FOREACH(failed, const char *, cp,
-      {
-        if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
-          log_warn(LD_BUG, "Malformed fingerprint in list: %s",
-                   escaped(cp));
-          continue;
-        }
-        retry_bridge_descriptor_fetch_directly(digest);
-      });
-    }
+    if (router_purpose == ROUTER_PURPOSE_BRIDGE)
+      connection_dir_retry_bridges(failed, was_extrainfo);
     return; /* FFFF should implement for other-than-router-purpose someday */
   }
   SMARTLIST_FOREACH(failed, const char *, cp,
-- 
1.7.1