Browse Source

Forget all rendezvous client state on SIGNAL NEWNYM

Robert Ransom 13 years ago
parent
commit
440e48ddf2
5 changed files with 56 additions and 0 deletions
  1. 5 0
      changes/forget-rend-descs-on-newnym
  2. 2 0
      src/or/main.c
  3. 2 0
      src/or/or.h
  4. 37 0
      src/or/rendclient.c
  5. 10 0
      src/or/rendcommon.c

+ 5 - 0
changes/forget-rend-descs-on-newnym

@@ -0,0 +1,5 @@
+  o Security fixes:
+    - Forget all hidden service descriptors cached as a client when
+      processing a SIGNAL NEWNYM command.  Fixes bug 3000.  Bugfix on
+      0.0.6.
+

+ 2 - 0
src/or/main.c

@@ -785,6 +785,8 @@ signewnym_impl(time_t now)
 {
   circuit_expire_all_dirty_circs();
   addressmap_clear_transient();
+  rend_cache_purge();
+  rend_client_cancel_descriptor_fetches();
   time_of_last_signewnym = now;
   signewnym_is_pending = 0;
 }

+ 2 - 0
src/or/or.h

@@ -4039,6 +4039,7 @@ int rend_client_introduction_acked(origin_circuit_t *circ,
                                    size_t request_len);
 void rend_client_refetch_renddesc(const char *query);
 void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
+void rend_client_cancel_descriptor_fetches(void);
 int rend_client_remove_intro_point(extend_info_t *failed_intro,
                                    const rend_data_t *rend_query);
 int rend_client_rendezvous_acked(origin_circuit_t *circ,
@@ -4137,6 +4138,7 @@ typedef struct rend_cache_entry_t {
 void rend_cache_init(void);
 void rend_cache_clean(void);
 void rend_cache_clean_v2_descs_as_dir(void);
+void rend_cache_purge(void);
 void rend_cache_free_all(void);
 int rend_valid_service_id(const char *query);
 int rend_cache_lookup_desc(const char *query, int version, const char **desc,

+ 37 - 0
src/or/rendclient.c

@@ -557,8 +557,45 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query)
   return;
 }
 
+/** Cancel all rendezvous descriptor fetches currently in progress.
+ */
+void
+rend_client_cancel_descriptor_fetches(void)
+{
+  smartlist_t *connection_array = get_connection_array();
+
+  SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) {
+    if (conn->type == CONN_TYPE_DIR &&
+        (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC ||
+         conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2)) {
+      /* It's a rendezvous descriptor fetch in progress -- cancel it
+       * by marking the connection for close.
+       *
+       * Even if this connection has already reached EOF, this is
+       * enough to make sure that if the descriptor hasn't been
+       * processed yet, it won't be.  See the end of
+       * connection_handle_read; connection_reached_eof (indirectly)
+       * processes whatever response the connection received. */
+
+      const rend_data_t *rd = (TO_DIR_CONN(conn))->rend_data;
+      if (!rd) {
+        log_warn(LD_BUG | LD_REND,
+                 "Marking for close dir conn fetching rendezvous "
+                 "descriptor for unknown service!");
+      } else {
+        log_debug(LD_REND, "Marking for close dir conn fetching v%d "
+                  "rendezvous descriptor for service %s",
+                  (int)(rd->rend_desc_version),
+                  safe_str(rd->onion_address));
+      }
+      connection_mark_for_close(conn);
+    }
+  } SMARTLIST_FOREACH_END(conn);
+}
+
 /** Remove failed_intro from ent. If ent now has no intro points, or
  * service is unrecognized, then launch a new renddesc fetch.
+
  *
  * Return -1 if error, 0 if no intro points remain or service
  * unrecognized, 1 if recognized and some intro points remain.

+ 10 - 0
src/or/rendcommon.c

@@ -871,6 +871,16 @@ rend_cache_clean(void)
   }
 }
 
+/** Remove ALL entries from the rendezvous service descriptor cache.
+ */
+void
+rend_cache_purge(void)
+{
+  if (rend_cache)
+    strmap_free(rend_cache, _rend_cache_entry_free);
+  rend_cache = strmap_new();
+}
+
 /** Remove all old v2 descriptors and those for which this hidden service
  * directory is not responsible for any more. */
 void