[tor-commits] [tor/master] prop224: Purge client state on NEWNYM

nickm at torproject.org nickm at torproject.org
Fri Sep 8 16:14:23 UTC 2017


commit 22295759afa90f19b06e2b657ce84d518c2390fd
Author: David Goulet <dgoulet at torproject.org>
Date:   Wed Aug 30 09:15:54 2017 -0400

    prop224: Purge client state on NEWNYM
    
    Closes #23355
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/or/connection.c | 19 +++++++++++++++----
 src/or/connection.h |  1 +
 src/or/hs_cache.c   | 31 +++++++++++++++++++++++++++++++
 src/or/hs_cache.h   |  2 ++
 src/or/hs_client.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
 src/or/hs_client.h  |  2 ++
 src/or/main.c       |  3 ++-
 src/or/rendcache.c  |  4 ++--
 8 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/src/or/connection.c b/src/or/connection.c
index 31a682387..01d7752e8 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -4113,16 +4113,27 @@ connection_write_to_buf_impl_,(const char *string, size_t len,
     return ret_conns; \
   STMT_END
 
-/* Return a list of connections that aren't close and matches the given state.
- * The returned list can be empty and must be freed using smartlist_free().
- * The caller does NOT have owernship of the objects in the list so it must
- * not free them nor reference them as they can disapear. */
+/* Return a list of connections that aren't close and matches the given type
+ * and state. The returned list can be empty and must be freed using
+ * smartlist_free(). The caller does NOT have owernship of the objects in the
+ * list so it must not free them nor reference them as they can disappear. */
 smartlist_t *
 connection_list_by_type_state(int type, int state)
 {
   CONN_GET_ALL_TEMPLATE(conn, (conn->type == type && conn->state == state));
 }
 
+/* Return a list of connections that aren't close and matches the given type
+ * and purpose. The returned list can be empty and must be freed using
+ * smartlist_free(). The caller does NOT have owernship of the objects in the
+ * list so it must not free them nor reference them as they can disappear. */
+smartlist_t *
+connection_list_by_type_purpose(int type, int purpose)
+{
+  CONN_GET_ALL_TEMPLATE(conn,
+                        (conn->type == type && conn->purpose == purpose));
+}
+
 /** Return a connection_t * from get_connection_array() that satisfies test on
  * var, and that is not marked for close. */
 #define CONN_GET_TEMPLATE(var, test)               \
diff --git a/src/or/connection.h b/src/or/connection.h
index 0bcf0ccdc..0aa13ada3 100644
--- a/src/or/connection.h
+++ b/src/or/connection.h
@@ -183,6 +183,7 @@ connection_t *connection_get_by_type_state(int type, int state);
 connection_t *connection_get_by_type_state_rendquery(int type, int state,
                                                      const char *rendquery);
 smartlist_t *connection_list_by_type_state(int type, int state);
+smartlist_t *connection_list_by_type_purpose(int type, int purpose);
 smartlist_t *connection_dir_list_by_purpose_and_resource(
                                                   int purpose,
                                                   const char *resource);
diff --git a/src/or/hs_cache.c b/src/or/hs_cache.c
index 6962c5ce4..78e2adacf 100644
--- a/src/or/hs_cache.c
+++ b/src/or/hs_cache.c
@@ -726,6 +726,23 @@ hs_cache_clean_as_client(time_t now)
   cache_clean_v3_as_client(now);
 }
 
+/* Purge the client descriptor cache. */
+void
+hs_cache_purge_as_client(void)
+{
+  DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_client, key,
+                              hs_cache_client_descriptor_t *, entry) {
+    size_t entry_size = cache_get_client_entry_size(entry);
+    MAP_DEL_CURRENT(key);
+    cache_client_desc_free(entry);
+    /* Update our OOM. We didn't use the remove() function because we are in
+     * a loop so we have to explicitely decrement. */
+    rend_cache_decrement_allocation(entry_size);
+  } DIGEST256MAP_FOREACH_END;
+
+  log_info(LD_REND, "Hidden service client descriptor cache purged.");
+}
+
 /* For a given service identity public key and an introduction authentication
  * key, note the given failure in the client intro state cache. */
 void
@@ -779,6 +796,20 @@ hs_cache_client_intro_state_clean(time_t now)
   } DIGEST256MAP_FOREACH_END;
 }
 
+/* Purge the client introduction state cache. */
+void
+hs_cache_client_intro_state_purge(void)
+{
+  DIGEST256MAP_FOREACH_MODIFY(hs_cache_client_intro_state, key,
+                              hs_cache_client_intro_state_t *, cache) {
+    MAP_DEL_CURRENT(key);
+    cache_client_intro_state_free(cache);
+  } DIGEST256MAP_FOREACH_END;
+
+  log_info(LD_REND, "Hidden service client introduction point state "
+                    "cache purged.");
+}
+
 /**************** Generics *********************************/
 
 /* Do a round of OOM cleanup on all directory caches. Return the amount of
diff --git a/src/or/hs_cache.h b/src/or/hs_cache.h
index 2a4d2dbb2..8dbc842b9 100644
--- a/src/or/hs_cache.h
+++ b/src/or/hs_cache.h
@@ -84,6 +84,7 @@ hs_cache_lookup_as_client(const ed25519_public_key_t *key);
 int hs_cache_store_as_client(const char *desc_str,
                              const ed25519_public_key_t *identity_pk);
 void hs_cache_clean_as_client(time_t now);
+void hs_cache_purge_as_client(void);
 
 /* Client failure cache. */
 void hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk,
@@ -93,6 +94,7 @@ const hs_cache_intro_state_t *hs_cache_client_intro_state_find(
                                        const ed25519_public_key_t *service_pk,
                                        const ed25519_public_key_t *auth_key);
 void hs_cache_client_intro_state_clean(time_t now);
+void hs_cache_client_intro_state_purge(void);
 
 #ifdef HS_CACHE_PRIVATE
 
diff --git a/src/or/hs_client.c b/src/or/hs_client.c
index 99be058eb..0015a9016 100644
--- a/src/or/hs_client.c
+++ b/src/or/hs_client.c
@@ -29,6 +29,30 @@
 #include "hs_ntor.h"
 #include "circuitbuild.h"
 
+/* Cancel all descriptor fetches currently in progress. */
+static void
+cancel_descriptor_fetches(void)
+{
+  smartlist_t *conns =
+    connection_list_by_type_state(CONN_TYPE_DIR, DIR_PURPOSE_FETCH_HSDESC);
+  SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
+    const hs_ident_dir_conn_t *ident = TO_DIR_CONN(conn)->hs_ident;
+    if (BUG(ident == NULL)) {
+      /* A directory connection fetching a service descriptor can't have an
+       * empty hidden service identifier. */
+      continue;
+    }
+    log_debug(LD_REND, "Marking for close a directory connection fetching "
+                       "a hidden service descriptor for service %s.",
+              safe_str_client(ed25519_fmt(&ident->identity_pk)));
+    connection_mark_for_close(conn);
+  } SMARTLIST_FOREACH_END(conn);
+
+  /* No ownership of the objects in this list. */
+  smartlist_free(conns);
+  log_info(LD_REND, "Hidden service client descriptor fetches cancelled.");
+}
+
 /* Get all connections that are waiting on a circuit and flag them back to
  * waiting for a hidden service descriptor for the given service key
  * service_identity_pk. */
@@ -1251,3 +1275,24 @@ hs_client_reextend_intro_circuit(origin_circuit_t *circ)
   return ret;
 }
 
+/* Purge all potentially remotely-detectable state held in the hidden
+ * service client code. Called on SIGNAL NEWNYM. */
+void
+hs_client_purge_state(void)
+{
+  /* v2 subsystem. */
+  rend_client_purge_state();
+
+  /* Cancel all descriptor fetches. Do this first so once done we are sure
+   * that our descriptor cache won't modified. */
+  cancel_descriptor_fetches();
+  /* Purge the introduction point state cache. */
+  hs_cache_client_intro_state_purge();
+  /* Purge the descriptor cache. */
+  hs_cache_purge_as_client();
+  /* Purge the last hidden service request cache. */
+  hs_purge_last_hid_serv_requests();
+
+  log_info(LD_REND, "Hidden service client state has been purged.");
+}
+
diff --git a/src/or/hs_client.h b/src/or/hs_client.h
index 8ed0501c9..a0f7c6b46 100644
--- a/src/or/hs_client.h
+++ b/src/or/hs_client.h
@@ -46,5 +46,7 @@ extend_info_t *hs_client_get_random_intro_from_edge(
 
 int hs_client_reextend_intro_circuit(origin_circuit_t *circ);
 
+void hs_client_purge_state(void);
+
 #endif /* TOR_HS_CLIENT_H */
 
diff --git a/src/or/main.c b/src/or/main.c
index 5d51d1dea..b67e72544 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -80,6 +80,7 @@
 #include "hibernate.h"
 #include "hs_cache.h"
 #include "hs_circuitmap.h"
+#include "hs_client.h"
 #include "keypin.h"
 #include "main.h"
 #include "microdesc.h"
@@ -1142,7 +1143,7 @@ signewnym_impl(time_t now)
 
   circuit_mark_all_dirty_circs_as_unusable();
   addressmap_clear_transient();
-  rend_client_purge_state();
+  hs_client_purge_state();
   time_of_last_signewnym = now;
   signewnym_is_pending = 0;
 
diff --git a/src/or/rendcache.c b/src/or/rendcache.c
index 792f6a130..b98b2bccf 100644
--- a/src/or/rendcache.c
+++ b/src/or/rendcache.c
@@ -303,7 +303,7 @@ void
 rend_cache_purge(void)
 {
   if (rend_cache) {
-    log_info(LD_REND, "Purging HS descriptor cache");
+    log_info(LD_REND, "Purging HS v2 descriptor cache");
     strmap_free(rend_cache, rend_cache_entry_free_);
   }
   rend_cache = strmap_new();
@@ -315,7 +315,7 @@ void
 rend_cache_failure_purge(void)
 {
   if (rend_cache_failure) {
-    log_info(LD_REND, "Purging HS failure cache");
+    log_info(LD_REND, "Purging HS v2 failure cache");
     strmap_free(rend_cache_failure, rend_cache_failure_entry_free_);
   }
   rend_cache_failure = strmap_new();





More information about the tor-commits mailing list