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) \
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);
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
} 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
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,
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
#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. */
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.");
+}
+
int hs_client_reextend_intro_circuit(origin_circuit_t *circ);
+void hs_client_purge_state(void);
+
#endif /* TOR_HS_CLIENT_H */
#include "hibernate.h"
#include "hs_cache.h"
#include "hs_circuitmap.h"
+#include "hs_client.h"
#include "keypin.h"
#include "main.h"
#include "microdesc.h"
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;
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();
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();