Tor

for Project:

This is the bug-tracker for Tor.  There is a guide for reporting bugs.

Tor is a connection-based low-latency anonymous communication system 
that protects TCP streams: web browsing, instant messaging, irc, ssh, etc. 
See https://www.torproject.org/ for more information.

To report bugs in the Torbutton Firefox browser extension, 
select the Torbutton project on this tracker.

To report bugs in the Vidalia front-end program, go to 
http://trac.vidalia-project.net/wiki/ReportingBugs .

Thanks for your help!



Task #814 — Fetching v0 and v2 rendezvous descriptors in parallel sometimes fails

Attached to Project— Tor
Opened by Karsten Loesing (karsten) - Wednesday, 10 Sep 2008, 12:16am
Bug Report
Tor client
Closed
Karsten Loesing (karsten)
All
Low
Normal
0.2.1.4-alpha
Undecided
0% complete
The logic to download v0 and v2 rendezvous descriptors in parallel does not
work correctly. If the v0 request returns first and unsuccessfully, the
hidden service connection is closed with the statement "[notice] Closing
stream for '[...].onion': hidden service is unavailable (try again later)."
A subsequent successful result of a v2 request cannot be processed
correctly; while the descriptor is stored for later use, it cannot be used
for the requesting connection any more.

This is a minor problem, since hidden services that only publish v2
descriptors are still rare (unless people perform tests with them).

Patch follows.



This task depends upon

This task blocks these from closing
Closed by  Roger Dingledine (arma)
Date:  Tuesday, 16 Sep 2008, 3:51pm.
Reason for closing:  Fixed
Additional comments about closing:  0

Comments (4) | Attachments (0) | Related Tasks (0/0) | Notifications (2) | Reminders (0) | History |

Comment by Karsten Loesing - Wednesday, 10 Sep 2008, 12:21am

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/src/or/rendclient.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/src/or/rendclient.c    (revision 16810)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/src/or/rendclient.c    (working copy)
@@ -666,9 +666,22 @@
           connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
       }
     } else { /* 404, or fetch didn't get that far */
-      log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
-                 "unavailable (try again later).", safe_str(query));
-      connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+      /* Are there fetch requests for this descriptor going on in parallel?
+       * If so, don't close the connection just because of this request
+       * failing. */
+      int parallel_fetches = 0;
+      SMARTLIST_FOREACH(conns, connection_t *, c, {
+        if (c->type == CONN_TYPE_DIR &&
+            (c->purpose == DIR_PURPOSE_FETCH_RENDDESC ||
+             c->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) &&
+            !rend_cmp_service_ids(query, TO_DIR_CONN(c)->rend_query))
+          parallel_fetches++;
+      });
+      if (parallel_fetches < 2) {
+        log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
+                   "unavailable (try again later).", safe_str(query));
+        connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+      }
     }
   });
 }




Comment by Karsten Loesing - Wednesday, 10 Sep 2008, 12:49am

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/ChangeLog
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/ChangeLog  (revision 16818)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv-changes/ChangeLog  (working copy)
@@ -25,6 +25,10 @@
       for bug 811.
     - Catch and report a few more bootstrapping failure cases when Tor
       fails to establish a TCP connection. Cleanup on 0.2.1.x.
+    - When fetching v0 and v2 rendezvous service descriptors in parallel,
+      do not fail the whole hidden service request only because the v0
+      descriptor fetch request fails; the v2 request might still succeed.
+      Fixes bug 814. Bugfix on 0.2.0.10-alpha.

   o Minor features:
     - Use a lockfile to make sure that two Tor processes are not




Comment by Karsten Loesing - Thursday, 11 Sep 2008, 1:42am

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog  (revision 16835)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog  (working copy)
@@ -24,6 +24,12 @@
       for bug 811.
     - Catch and report a few more bootstrapping failure cases when Tor
       fails to establish a TCP connection. Cleanup on 0.2.1.x.
+    - When fetching v0 and v2 rendezvous service descriptors in parallel,
+      do not fail the whole hidden service request only because the v0
+      descriptor fetch request fails; the v2 request might still succeed.
+      The other way round, when the last v2 request fails and no v0 request
+      is going on, do fail the hidden service request. Fixes bug 814.
+      Bugfix on 0.2.0.10-alpha.

   o Minor features:
     - Use a lockfile to make sure that two Tor processes are not
Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c    (revision 16835)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c    (working copy)
@@ -462,6 +462,8 @@
   log_info(LD_REND, "Could not pick one of the responsible hidden "
                     "service directories to fetch descriptors, because "
                     "we already tried them all unsuccessfully.");
+  /* Close pending connections (unless a rend desc has arrived by magic). */
+  rend_client_desc_here(query);
   return;
 }

@@ -666,9 +668,13 @@
           connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
       }
     } else { /* 404, or fetch didn't get that far */
-      log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
-                 "unavailable (try again later).", safe_str(query));
-      connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+      /* Unless there are requests for another descriptor version pending,
+       * close the connection. */
+      if (!connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query, -1)) {
+        log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
+                   "unavailable (try again later).", safe_str(query));
+        connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+      }
     }
   });
 }




Comment by Karsten Loesing - Friday, 12 Sep 2008, 4:32pm

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog  (revision 16872)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/ChangeLog  (working copy)
@@ -24,6 +24,12 @@
       for bug 811.
     - Catch and report a few more bootstrapping failure cases when Tor
       fails to establish a TCP connection. Cleanup on 0.2.1.x.
+    - When fetching v0 and v2 rendezvous service descriptors in parallel,
+      do not fail the whole hidden service request only because the v0
+      descriptor fetch request fails; the v2 request might still succeed.
+      The other way round, when the last v2 request fails and no v0 request
+      is going on, do fail the hidden service request. Fixes bug 814.
+      Bugfix on 0.2.0.10-alpha.

   o Minor features:
     - Use a lockfile to make sure that two Tor processes are not
Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/connection.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/connection.c    (revision 16838)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/connection.c    (working copy)
@@ -522,8 +522,13 @@
          * failed: forget about this router, and maybe try again. */
         connection_dir_request_failed(dir_conn);
       }
-      if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC)
-        rend_client_desc_here(dir_conn->rend_query); /* give it a try */
+      if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC) {
+        /* Give it a try. However, there is no re-fetching for v0 rend
+         * descriptors; if the response is empty or the descriptor is
+         * unusable, close pending connections (unless a v2 request is
+         * still in progress). */
+        rend_client_desc_here(dir_conn->rend_query, 0);
+      }
       /* If we were trying to fetch a v2 rend desc and did not succeed,
        * retry as needed. (If a fetch is successful, the connection state
        * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/directory.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/directory.c (revision 16838)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/directory.c (working copy)
@@ -1893,7 +1893,7 @@
         } else {
           /* success. notify pending connections about this. */
           conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
-          rend_client_desc_here(conn->rend_query);
+          rend_client_desc_here(conn->rend_query, -1);
         }
         break;
       case 404:
@@ -1939,7 +1939,7 @@
             log_info(LD_REND, "Successfully fetched v2 rendezvous "
                      "descriptor.");
             conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
-            rend_client_desc_here(conn->rend_query);
+            rend_client_desc_here(conn->rend_query, -1);
             break;
         }
         break;
Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/or.h
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/or.h    (revision 16838)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/or.h    (working copy)
@@ -3839,7 +3839,7 @@
                                  size_t request_len);
 int rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
                                    size_t request_len);
-void rend_client_desc_here(const char *query);
+void rend_client_desc_here(const char *query, int rend_version);

 extend_info_t *rend_client_get_random_intro(const char *query);

Index: /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c
===================================================================
--- /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c    (revision 16838)
+++ /home/karsten/tor/hidserv-project/projects/tor-trunk-hidserv/src/or/rendclient.c    (working copy)
@@ -462,6 +462,8 @@
   log_info(LD_REND, "Could not pick one of the responsible hidden "
                     "service directories to fetch descriptors, because "
                     "we already tried them all unsuccessfully.");
+  /* Close pending connections (unless a v0 request is still going on). */
+  rend_client_desc_here(query, 2);
   return;
 }

@@ -625,11 +627,14 @@

 /** Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that
  * are waiting on query. If there's a working cache entry here
- * with at least one intro point, move them to the next state;
- * else fail them.
+ * with at least one intro point, move them to the next state. If
+ * rend_version is non-negative, fail connections that have
+ * requested query unless there are still descriptor fetch
+ * requests in progress for other descriptor versions than
+ * rend_version.
  */
 void
-rend_client_desc_here(const char *query)
+rend_client_desc_here(const char *query, int rend_version)
 {
   edge_connection_t *conn;
   rend_cache_entry_t *entry;
@@ -666,9 +671,15 @@
           connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
       }
     } else { /* 404, or fetch didn't get that far */
-      log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
-                 "unavailable (try again later).", safe_str(query));
-      connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+      /* Unless there are requests for another descriptor version pending,
+       * close the connection. */
+      if (rend_version >= 0 &&
+          !connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query,
+                                                  rend_version == 0 ? 2 : 0)) {
+        log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
+                   "unavailable (try again later).", safe_str(query));
+        connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+      }
     }
   });
 }