diff options
Diffstat (limited to 'src/feature/rend/rendcache.c')
-rw-r--r-- | src/feature/rend/rendcache.c | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/src/feature/rend/rendcache.c b/src/feature/rend/rendcache.c index 1c3badaff3..04f6390a7f 100644 --- a/src/feature/rend/rendcache.c +++ b/src/feature/rend/rendcache.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2019, The Tor Project, Inc. */ +/* Copyright (c) 2015-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -19,6 +19,8 @@ #include "feature/rend/rend_intro_point_st.h" #include "feature/rend/rend_service_descriptor_st.h" +#include "lib/ctime/di_ops.h" + /** Map from service id (as generated by rend_get_service_id) to * rend_cache_entry_t. */ STATIC strmap_t *rend_cache = NULL; @@ -35,7 +37,7 @@ STATIC digestmap_t *rend_cache_v2_dir = NULL; * or discard a new descriptor we just fetched. Here is a description of the * cache behavior. * - * Everytime tor discards an IP (ex: receives a NACK), we add an entry to + * Every time tor discards an IP (ex: receives a NACK), we add an entry to * this cache noting the identity digest of the IP and it's failure type for * the service ID. The reason we indexed this cache by service ID is to * differentiate errors that can occur only for a specific service like a @@ -45,7 +47,7 @@ STATIC digestmap_t *rend_cache_v2_dir = NULL; * looked up in this cache and if present, it is discarded from the fetched * descriptor. At the end, all IP(s) in the cache, for a specific service * ID, that were NOT present in the descriptor are removed from this cache. - * Which means that if at least one IP was not in this cache, thus usuable, + * Which means that if at least one IP was not in this cache, thus usable, * it's considered a new descriptor so we keep it. Else, if all IPs were in * this cache, we discard the descriptor as it's considered unusable. * @@ -226,6 +228,17 @@ rend_cache_entry_free_void(void *p) rend_cache_entry_free_(p); } +/** Check if a failure cache entry exists for the given intro point. */ +bool +rend_cache_intro_failure_exists(const char *service_id, + const uint8_t *intro_identity) +{ + tor_assert(service_id); + tor_assert(intro_identity); + + return cache_failure_intro_lookup(intro_identity, service_id, NULL); +} + /** Free all storage held by the service descriptor cache. */ void rend_cache_free_all(void) @@ -244,7 +257,7 @@ rend_cache_free_all(void) /** Remove all entries that re REND_CACHE_FAILURE_MAX_AGE old. This is * called every second. * - * We have to clean these regurlarly else if for whatever reasons an hidden + * We have to clean these regularly else if for whatever reasons an hidden * service goes offline and a client tries to connect to it during that * time, a failure entry is created and the client will be unable to connect * for a while even though the service has return online. */ @@ -327,8 +340,9 @@ rend_cache_failure_purge(void) /** Lookup the rend failure cache using a relay identity digest in * <b>identity</b> which has DIGEST_LEN bytes and service ID <b>service_id</b> - * which is a null-terminated string. If found, the intro failure is set in - * <b>intro_entry</b> else it stays untouched. Return 1 iff found else 0. */ + * which is a null-terminated string. If @a intro_entry is provided, then it + * is set to the entry on success, and to NULL on failure. + * Return 1 iff found else 0. */ STATIC int cache_failure_intro_lookup(const uint8_t *identity, const char *service_id, rend_cache_failure_intro_t **intro_entry) @@ -513,9 +527,16 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e) rend_cache_entry_t *entry = NULL; static const int default_version = 2; - tor_assert(rend_cache); tor_assert(query); + /* This is possible if we are in the shutdown process and the cache was + * freed while some other subsystem might do a lookup to the cache for + * cleanup reasons such HS circuit cleanup for instance. */ + if (!rend_cache) { + ret = -ENOENT; + goto end; + } + if (!rend_valid_v2_service_id(query)) { ret = -EINVAL; goto end; @@ -593,10 +614,10 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc) char desc_id_digest[DIGEST_LEN]; tor_assert(rend_cache_v2_dir); if (base32_decode(desc_id_digest, DIGEST_LEN, - desc_id, REND_DESC_ID_V2_LEN_BASE32) < 0) { + desc_id, REND_DESC_ID_V2_LEN_BASE32) != DIGEST_LEN) { log_fn(LOG_PROTOCOL_WARN, LD_REND, "Rejecting v2 rendezvous descriptor request -- descriptor ID " - "contains illegal characters: %s", + "has wrong length or illegal characters: %s", safe_str(desc_id)); return -1; } @@ -854,7 +875,8 @@ rend_cache_store_v2_desc_as_client(const char *desc, *entry = NULL; } if (base32_decode(want_desc_id, sizeof(want_desc_id), - desc_id_base32, strlen(desc_id_base32)) != 0) { + desc_id_base32, strlen(desc_id_base32)) != + sizeof(want_desc_id)) { log_warn(LD_BUG, "Couldn't decode base32 %s for descriptor id.", escaped_safe_str_client(desc_id_base32)); goto err; @@ -888,8 +910,8 @@ rend_cache_store_v2_desc_as_client(const char *desc, if (intro_content && intro_size > 0) { int n_intro_points; if (rend_data->auth_type != REND_NO_AUTH && - !tor_mem_is_zero(rend_data->descriptor_cookie, - sizeof(rend_data->descriptor_cookie))) { + !safe_mem_is_zero(rend_data->descriptor_cookie, + sizeof(rend_data->descriptor_cookie))) { char *ipos_decrypted = NULL; size_t ipos_decrypted_size; if (rend_decrypt_introduction_points(&ipos_decrypted, @@ -1005,4 +1027,3 @@ rend_cache_store_v2_desc_as_client(const char *desc, tor_free(intro_content); return retval; } - |