Tor 0.4.9.3-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
hs_cache.c
Go to the documentation of this file.
1/* Copyright (c) 2016-2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file hs_cache.c
6 * \brief Handle hidden service descriptor caches.
7 **/
8
9/* For unit tests.*/
10#define HS_CACHE_PRIVATE
11
12#include "core/or/or.h"
13#include "app/config/config.h"
16#include "lib/cc/torint.h"
17#include "feature/hs/hs_ident.h"
24
25#include "feature/hs/hs_cache.h"
26
28
29/**
30 * Spare room for 1000 descriptors when pruning cache to avoid thrashing
31 * and memory fragmentation. */
32#define HSCACHE_PRUNE_SPARE_ROOM (1000 * HS_DESC_MAX_LEN)
33
34/* Total counter of the cache size. */
35static size_t hs_cache_total_allocation = 0;
36
37static int cached_client_descriptor_has_expired(time_t now,
38 const hs_cache_client_descriptor_t *cached_desc);
39
40/** Helper function: Return true iff the cache entry has a decrypted
41 * descriptor.
42 *
43 * A NULL desc object in the entry means that we were not able to decrypt the
44 * descriptor because we are likely lacking client authorization. It is still
45 * a valid entry but some operations can't be done without the decrypted
46 * descriptor thus this function MUST be used to safe guard access to the
47 * decrypted desc object. */
48static inline bool
49entry_has_decrypted_descriptor(const hs_cache_client_descriptor_t *entry)
50{
51 tor_assert(entry);
52 return (entry->desc != NULL);
53}
54
55/********************** Directory HS cache ******************/
56
57/** Directory descriptor cache. Map indexed by blinded key. */
58static digest256map_t *hs_cache_v3_dir;
59
60/** Remove a given descriptor from our cache. */
61static void
63{
64 tor_assert(desc);
65 digest256map_remove(hs_cache_v3_dir, desc->key);
66}
67
68/** Store a given descriptor in our cache. */
69static void
71{
72 tor_assert(desc);
73 digest256map_set(hs_cache_v3_dir, desc->key, desc);
74}
75
76/** Query our cache and return the entry or NULL if not found. */
78lookup_v3_desc_as_dir(const uint8_t *key)
79{
80 tor_assert(key);
81 return digest256map_get(hs_cache_v3_dir, key);
82}
83
84#define cache_dir_desc_free(val) \
85 FREE_AND_NULL(hs_cache_dir_descriptor_t, cache_dir_desc_free_, (val))
86
87/** Free a directory descriptor object. */
88static void
90{
91 if (desc == NULL) {
92 return;
93 }
94 hs_desc_plaintext_data_free(desc->plaintext_data);
96 tor_free(desc);
97}
98
99/** Helper function: Use by the free all function using the digest256map
100 * interface to cache entries. */
101static void
103{
105}
106
107/** Create a new directory cache descriptor object from a encoded descriptor.
108 * On success, return the heap-allocated cache object, otherwise return NULL if
109 * we can't decode the descriptor. */
111cache_dir_desc_new(const char *desc)
112{
114
115 tor_assert(desc);
116
117 dir_desc = tor_malloc_zero(sizeof(hs_cache_dir_descriptor_t));
118 dir_desc->plaintext_data =
119 tor_malloc_zero(sizeof(hs_desc_plaintext_data_t));
120 dir_desc->encoded_desc = tor_strdup(desc);
121
122 if (hs_desc_decode_plaintext(desc, dir_desc->plaintext_data) < 0) {
123 log_debug(LD_DIR, "Unable to decode descriptor. Rejecting.");
124 goto err;
125 }
126
127 /* The blinded pubkey is the indexed key. */
128 dir_desc->key = dir_desc->plaintext_data->blinded_pubkey.pubkey;
129 dir_desc->created_ts = time(NULL);
130 return dir_desc;
131
132 err:
133 cache_dir_desc_free(dir_desc);
134 return NULL;
135}
136
137/** Return the size of a cache entry in bytes. */
138static size_t
140{
141 return (sizeof(*entry) + hs_desc_plaintext_obj_size(entry->plaintext_data)
142 + strlen(entry->encoded_desc));
143}
144
145/** Try to store a valid version 3 descriptor in the directory cache. Return 0
146 * on success else a negative value is returned indicating that we have a
147 * newer version in our cache. On error, caller is responsible to free the
148 * given descriptor desc. */
149static int
151{
152 hs_cache_dir_descriptor_t *cache_entry;
153
154 tor_assert(desc);
155
156 /* Check if we've exceeded the MaxHSDirCacheBytes limit after adding
157 * this descriptor. If so, prune excess bytes leaving room for more. */
158 const size_t max_cache_bytes = hs_cache_get_max_bytes();
159 const size_t current_cache_bytes = hs_cache_get_total_allocation();
160 if (max_cache_bytes > 0 && current_cache_bytes > max_cache_bytes) {
161 /* We prune only 1000 descriptors worth of memory here because
162 * pruning is an expensive O(n^2) option to keep finding lowest
163 * download count descs. */
164 size_t bytes_to_remove = current_cache_bytes/2;
165 /* Ensure user didn't set a really low max hsdir cache vlue */
166 if (HSCACHE_PRUNE_SPARE_ROOM < max_cache_bytes) {
167 bytes_to_remove = current_cache_bytes -
168 (max_cache_bytes - HSCACHE_PRUNE_SPARE_ROOM);
169 }
170 size_t removed = hs_cache_handle_oom(bytes_to_remove);
171 static ratelim_t hs_cache_oom_ratelim = RATELIM_INIT(600);
172 log_fn_ratelim(&hs_cache_oom_ratelim, LOG_NOTICE, LD_REND,
173 "HSDir cache exceeded limit (%zu > %zu bytes). "
174 "Pruned %zu bytes during an HS descriptor upload.",
175 current_cache_bytes, max_cache_bytes, removed);
176 }
177
178 /* Verify if we have an entry in the cache for that key and if yes, check
179 * if we should replace it? */
180 cache_entry = lookup_v3_desc_as_dir(desc->key);
181 if (cache_entry != NULL) {
182 /* Only replace descriptor if revision-counter is greater than the one
183 * in our cache */
184 if (cache_entry->plaintext_data->revision_counter >=
186 log_info(LD_REND, "Descriptor revision counter in our cache is "
187 "greater or equal than the one we received (%d/%d). "
188 "Rejecting!",
189 (int)cache_entry->plaintext_data->revision_counter,
190 (int)desc->plaintext_data->revision_counter);
191 goto err;
192 }
193 /* We now know that the descriptor we just received is a new one so
194 * preserve the downloaded counter from the old entry and then
195 * remove the entry we currently have from our cache so we can then
196 * store the new one. */
197 desc->n_downloaded = cache_entry->n_downloaded;
198 remove_v3_desc_as_dir(cache_entry);
200 cache_dir_desc_free(cache_entry);
201 }
202
203 /* Store the descriptor we just got. We are sure here that either we
204 * don't have the entry or we have a newer descriptor and the old one
205 * has been removed from the cache. We do this *after* pruning
206 * other descriptors so that this descriptor is not immediately pruned,
207 * if new. This prevents probing to detect OOM threshholds via its
208 * absence. */
210
211 /* Update our total cache size with this entry for the OOM. This uses the
212 * old HS protocol cache subsystem for which we are tied with. */
214
215 /* Update HSv3 statistics */
216 if (get_options()->HiddenServiceStatistics) {
218 }
219
220 return 0;
221
222 err:
223 return -1;
224}
225
226/** Using the query which is the base64 encoded blinded key of a version 3
227 * descriptor, lookup in our directory cache the entry. If found, 1 is
228 * returned and desc_out is populated with a newly allocated string being the
229 * encoded descriptor. If not found, 0 is returned and desc_out is untouched.
230 * On error, a negative value is returned and desc_out is untouched. */
231static int
232cache_lookup_v3_as_dir(const char *query, const char **desc_out)
233{
234 int found = 0;
235 ed25519_public_key_t blinded_key;
236 const hs_cache_dir_descriptor_t *entry;
237
238 tor_assert(query);
239
240 /* Decode blinded key using the given query value. */
241 if (ed25519_public_from_base64(&blinded_key, query) < 0) {
242 log_info(LD_REND, "Unable to decode the v3 HSDir query %s.",
243 safe_str_client(query));
244 goto err;
245 }
246
247 entry = lookup_v3_desc_as_dir(blinded_key.pubkey);
248 if (entry != NULL) {
249 found = 1;
250 if (desc_out) {
251 *desc_out = entry->encoded_desc;
252 }
253 }
254
255 return found;
256
257 err:
258 return -1;
259}
260
261/** Clean the v3 cache by removing entries that are below or equal the
262 * downloaded target.
263 *
264 * Stop when the max_remove_bytes is reached. It is possible that more bytes
265 * are removed if max_remove_bytes is not aligned on cache entry size.
266 *
267 * Return the amount of bytes freed. The next_lowest param is set to the
268 * lowest n_downloaded value in the cache that is above target.
269 *
270 * If both next_lowest and returned value are 0, the cache is empty. */
271STATIC size_t
273 const size_t max_remove_bytes,
274 uint64_t *next_lowest)
275{
276 size_t bytes_removed = 0;
277 uint64_t lowest = 0;
278
279 if (!hs_cache_v3_dir) { /* No cache to clean. Just return. */
280 goto end;
281 }
282
283 log_info(LD_REND, "Cleaning HS cache for downloaded target of %" PRIu64
284 ". Maximum bytes to removed: %" TOR_PRIuSZ,
285 target, max_remove_bytes);
286
287 DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_dir, key,
288 hs_cache_dir_descriptor_t *, entry) {
289 /* Downloaded counter is above target, ignore. Record next lowest. */
290 if (entry->n_downloaded > target) {
291 if (lowest == 0 || lowest > entry->n_downloaded) {
292 lowest = entry->n_downloaded;
293 }
294 continue;
295 }
296 /* We have removed enough, avoid cleaning this entry. Reason we continue
297 * the loop is so we can find the next lowest value. Yes, with many
298 * entries, this could be expensive but this is only called during OOM
299 * cleanup which should be fairly rare. */
300 if (bytes_removed >= max_remove_bytes) {
301 continue;
302 }
303 size_t entry_size = cache_get_dir_entry_size(entry);
304 /* Logging. */
305 {
306 char key_b64[BASE64_DIGEST256_LEN + 1];
307 digest256_to_base64(key_b64, (const char *) key);
308 log_info(LD_REND, "Removing v3 descriptor '%s' from HSDir cache. "
309 "Downloaded %" PRIu64 " times and "
310 "size of %" TOR_PRIuSZ " bytes",
311 safe_str_client(key_b64), entry->n_downloaded, entry_size);
312 }
313 /* Remove it from our cache. */
314 MAP_DEL_CURRENT(key);
315 bytes_removed += entry_size;
316 /* Entry is not in the cache anymore, destroy it. */
317 cache_dir_desc_free(entry);
318 /* Update our cache entry allocation size for the OOM. */
320 } DIGEST256MAP_FOREACH_END;
321
322 end:
323 *next_lowest = lowest;
324 return bytes_removed;
325}
326
327/** Clean the v3 cache by removing any entry that has expired using the
328 * <b>global_cutoff</b> value. If <b>global_cutoff</b> is 0, the cleaning
329 * process will use the lifetime found in the plaintext data section. Return
330 * the number of bytes cleaned. */
331STATIC size_t
332cache_clean_v3_as_dir(time_t now, time_t global_cutoff)
333{
334 size_t bytes_removed = 0;
335
336 /* Code flow error if this ever happens. */
337 tor_assert(global_cutoff >= 0);
338
339 if (!hs_cache_v3_dir) { /* No cache to clean. Just return. */
340 return 0;
341 }
342
343 DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_dir, key,
344 hs_cache_dir_descriptor_t *, entry) {
345 size_t entry_size;
346 time_t cutoff = global_cutoff;
347 if (!cutoff) {
348 /* Cutoff is the lifetime of the entry found in the descriptor. */
349 cutoff = now - entry->plaintext_data->lifetime_sec;
350 }
351
352 /* If the entry has been created _after_ the cutoff, not expired so
353 * continue to the next entry in our v3 cache. */
354 if (entry->created_ts > cutoff) {
355 continue;
356 }
357 /* Here, our entry has expired, remove and free. */
358 MAP_DEL_CURRENT(key);
359 entry_size = cache_get_dir_entry_size(entry);
360 bytes_removed += entry_size;
361 /* Entry is not in the cache anymore, destroy it. */
362 cache_dir_desc_free(entry);
363 /* Update our cache entry allocation size for the OOM. */
365 /* Logging. */
366 {
367 char key_b64[BASE64_DIGEST256_LEN + 1];
368 digest256_to_base64(key_b64, (const char *) key);
369 log_info(LD_REND, "Removing v3 descriptor '%s' from HSDir cache",
370 safe_str_client(key_b64));
371 }
372 } DIGEST256MAP_FOREACH_END;
373
374 return bytes_removed;
375}
376
377/** Given an encoded descriptor, store it in the directory cache depending on
378 * which version it is. Return a negative value on error. On success, 0 is
379 * returned. */
380int
381hs_cache_store_as_dir(const char *desc)
382{
383 hs_cache_dir_descriptor_t *dir_desc = NULL;
384
385 tor_assert(desc);
386
387 /* Create a new cache object. This can fail if the descriptor plaintext data
388 * is unparseable which in this case a log message will be triggered. */
389 dir_desc = cache_dir_desc_new(desc);
390 if (dir_desc == NULL) {
391 goto err;
392 }
393
394 /* Call the right function against the descriptor version. At this point,
395 * we are sure that the descriptor's version is supported else the
396 * decoding would have failed. */
397 switch (dir_desc->plaintext_data->version) {
398 case HS_VERSION_THREE:
399 default:
400 if (cache_store_v3_as_dir(dir_desc) < 0) {
401 goto err;
402 }
403 break;
404 }
405 return 0;
406
407 err:
408 cache_dir_desc_free(dir_desc);
409 return -1;
410}
411
412/** Using the query, lookup in our directory cache the entry. If found, 1 is
413 * returned and desc_out is populated with a newly allocated string being
414 * the encoded descriptor. If not found, 0 is returned and desc_out is
415 * untouched. On error, a negative value is returned and desc_out is
416 * untouched. */
417int
418hs_cache_lookup_as_dir(uint32_t version, const char *query,
419 const char **desc_out)
420{
421 int found;
422
423 tor_assert(query);
424 /* This should never be called with an unsupported version. */
426
427 switch (version) {
428 case HS_VERSION_THREE:
429 default:
430 found = cache_lookup_v3_as_dir(query, desc_out);
431 break;
432 }
433
434 return found;
435}
436
437/** Using the given directory identifier, lookup the descriptor in our cache
438 * and if present, increment the downloaded counter. This is done when the
439 * directory connection fetching this descriptor is closed. */
440void
442{
444
445 tor_assert(ident);
446
447 entry = lookup_v3_desc_as_dir(ident->blinded_pk.pubkey);
448 if (entry) {
449 entry->n_downloaded++;
450 }
451}
452
453/** Clean all directory caches using the current time now. */
454void
456{
457 /* Now, clean the v3 cache. Set the cutoff to 0 telling the cleanup function
458 * to compute the cutoff by itself using the lifetime value. */
459 cache_clean_v3_as_dir(now, 0);
460}
461
462/********************** Client-side HS cache ******************/
463
464/** Client-side HS descriptor cache. Map indexed by service identity key. */
465static digest256map_t *hs_cache_v3_client;
466
467/** Client-side introduction point state cache. Map indexed by service public
468 * identity key (onion address). It contains hs_cache_client_intro_state_t
469 * objects all related to a specific service. */
470static digest256map_t *hs_cache_client_intro_state;
471
472#define cache_client_desc_free(val) \
473 FREE_AND_NULL(hs_cache_client_descriptor_t, cache_client_desc_free_, (val))
474
475/** Free memory allocated by <b>desc</b>. */
476static void
477cache_client_desc_free_(hs_cache_client_descriptor_t *desc)
478{
479 if (desc == NULL) {
480 return;
481 }
482 hs_descriptor_free(desc->desc);
483 memwipe(&desc->key, 0, sizeof(desc->key));
484 memwipe(desc->encoded_desc, 0, strlen(desc->encoded_desc));
485 tor_free(desc->encoded_desc);
486 tor_free(desc);
487}
488
489/** Helper function: Use by the free all function to clear the client cache */
490static void
492{
493 hs_cache_client_descriptor_t *desc = ptr;
494 cache_client_desc_free(desc);
495}
496
497/** Return the size of a client cache entry in bytes. */
498static size_t
499cache_get_client_entry_size(const hs_cache_client_descriptor_t *entry)
500{
501 size_t size = 0;
502
503 if (entry == NULL) {
504 goto end;
505 }
506 size += sizeof(*entry);
507
508 if (entry->encoded_desc) {
509 size += strlen(entry->encoded_desc);
510 }
511
513 size += hs_desc_obj_size(entry->desc);
514 }
515
516 end:
517 return size;
518}
519
520/** Remove a given descriptor from our cache. */
521static void
522remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
523{
524 tor_assert(desc);
525 digest256map_remove(hs_cache_v3_client, desc->key.pubkey);
526 /* Update cache size with this entry for the OOM handler. */
528}
529
530/** Store a given descriptor in our cache. */
531static void
532store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
533{
534 hs_cache_client_descriptor_t *cached_desc;
535
536 tor_assert(desc);
537
538 /* Because the lookup function doesn't return an expired entry, it can linger
539 * in the cache until we clean it up or a new descriptor is stored. So,
540 * before adding, we'll make sure we are not overwriting an old descriptor
541 * (which is OK in terms of semantic) but leads to memory leak. */
542 cached_desc = digest256map_get(hs_cache_v3_client, desc->key.pubkey);
543 if (cached_desc) {
544 cache_client_desc_free(cached_desc);
545 }
546 digest256map_set(hs_cache_v3_client, desc->key.pubkey, desc);
547 /* Update cache size with this entry for the OOM handler. */
549}
550
551/** Query our cache and return the entry or NULL if not found or if expired. */
552STATIC hs_cache_client_descriptor_t *
553lookup_v3_desc_as_client(const uint8_t *key)
554{
555 time_t now = approx_time();
556 hs_cache_client_descriptor_t *cached_desc;
557
558 tor_assert(key);
559
560 /* Do the lookup */
561 cached_desc = digest256map_get(hs_cache_v3_client, key);
562 if (!cached_desc) {
563 return NULL;
564 }
565
566 /* Don't return expired entries */
567 if (cached_client_descriptor_has_expired(now, cached_desc)) {
568 return NULL;
569 }
570
571 return cached_desc;
572}
573
574/** Parse the encoded descriptor in <b>desc_str</b> using
575 * <b>service_identity_pk</b> to decrypt it first.
576 *
577 * If everything goes well, allocate and return a new
578 * hs_cache_client_descriptor_t object. In case of error, return NULL. */
579static hs_cache_client_descriptor_t *
580cache_client_desc_new(const char *desc_str,
581 const ed25519_public_key_t *service_identity_pk,
582 hs_desc_decode_status_t *decode_status_out)
583{
585 hs_descriptor_t *desc = NULL;
586 hs_cache_client_descriptor_t *client_desc = NULL;
587
588 tor_assert(desc_str);
589 tor_assert(service_identity_pk);
590
591 /* Decode the descriptor we just fetched. */
592 ret = hs_client_decode_descriptor(desc_str, service_identity_pk, &desc);
593 if (ret != HS_DESC_DECODE_OK &&
594 ret != HS_DESC_DECODE_NEED_CLIENT_AUTH &&
595 ret != HS_DESC_DECODE_BAD_CLIENT_AUTH) {
596 /* In the case of a missing or bad client authorization, we'll keep the
597 * descriptor in the cache because those credentials can arrive later. */
598 goto end;
599 }
600 /* Make sure we do have a descriptor if decoding was successful. */
601 if (ret == HS_DESC_DECODE_OK) {
602 tor_assert(desc);
603 } else {
604 if (BUG(desc != NULL)) {
605 /* We are not suppose to have a descriptor if the decoding code is not
606 * indicating success. Just in case, bail early to recover. */
607 goto end;
608 }
609 }
610
611 /* All is good: make a cache object for this descriptor */
612 client_desc = tor_malloc_zero(sizeof(hs_cache_client_descriptor_t));
613 ed25519_pubkey_copy(&client_desc->key, service_identity_pk);
614 /* Set expiration time for this cached descriptor to be the start of the next
615 * time period since that's when clients need to start using the next blinded
616 * pk of the service (and hence will need its next descriptor). */
617 client_desc->expiration_ts = hs_get_start_time_of_next_time_period(0);
618 client_desc->desc = desc;
619 client_desc->encoded_desc = tor_strdup(desc_str);
620
621 end:
622 if (decode_status_out) {
623 *decode_status_out = ret;
624 }
625 return client_desc;
626}
627
628/** Return a newly allocated and initialized hs_cache_intro_state_t object. */
631{
632 hs_cache_intro_state_t *state = tor_malloc_zero(sizeof(*state));
633 state->created_ts = approx_time();
634 return state;
635}
636
637#define cache_intro_state_free(val) \
638 FREE_AND_NULL(hs_cache_intro_state_t, cache_intro_state_free_, (val))
639
640/** Free an hs_cache_intro_state_t object. */
641static void
646
647/** Helper function: used by the free all function. */
648static void
650{
652}
653
654/** Return a newly allocated and initialized hs_cache_client_intro_state_t
655 * object. */
658{
659 hs_cache_client_intro_state_t *cache = tor_malloc_zero(sizeof(*cache));
660 cache->intro_points = digest256map_new();
661 return cache;
662}
663
664#define cache_client_intro_state_free(val) \
665 FREE_AND_NULL(hs_cache_client_intro_state_t, \
666 cache_client_intro_state_free_, (val))
667
668/** Free a cache_client_intro_state object. */
669static void
671{
672 if (cache == NULL) {
673 return;
674 }
675 digest256map_free(cache->intro_points, cache_intro_state_free_void);
676 tor_free(cache);
677}
678
679/** Helper function: used by the free all function. */
680static void
685
686/** For the given service identity key service_pk and an introduction
687 * authentication key auth_key, lookup the intro state object. Return 1 if
688 * found and put it in entry if not NULL. Return 0 if not found and entry is
689 * untouched. */
690static int
692 const ed25519_public_key_t *auth_key,
694{
697
698 tor_assert(service_pk);
699 tor_assert(auth_key);
700 tor_assert_nonfatal(!ed25519_public_key_is_zero(service_pk));
701 tor_assert_nonfatal(!ed25519_public_key_is_zero(auth_key));
702
703 /* Lookup the intro state cache for this service key. */
704 cache = digest256map_get(hs_cache_client_intro_state, service_pk->pubkey);
705 if (cache == NULL) {
706 goto not_found;
707 }
708
709 /* From the cache we just found for the service, lookup in the introduction
710 * points map for the given authentication key. */
711 state = digest256map_get(cache->intro_points, auth_key->pubkey);
712 if (state == NULL) {
713 goto not_found;
714 }
715 if (entry) {
716 *entry = state;
717 }
718 return 1;
719 not_found:
720 return 0;
721}
722
723/** Note the given failure in state. */
724static void
726 rend_intro_point_failure_t failure)
727{
728 tor_assert(state);
729 switch (failure) {
730 case INTRO_POINT_FAILURE_GENERIC:
731 state->error = 1;
732 break;
733 case INTRO_POINT_FAILURE_TIMEOUT:
734 state->timed_out = 1;
735 break;
736 case INTRO_POINT_FAILURE_UNREACHABLE:
737 state->unreachable_count++;
738 break;
739 default:
741 return;
742 }
743}
744
745/** For the given service identity key service_pk and an introduction
746 * authentication key auth_key, add an entry in the client intro state cache
747 * If no entry exists for the service, it will create one. If state is non
748 * NULL, it will point to the new intro state entry. */
749static void
751 const ed25519_public_key_t *auth_key,
753{
754 hs_cache_intro_state_t *entry, *old_entry;
756
757 tor_assert(service_pk);
758 tor_assert(auth_key);
759
760 /* Lookup the state cache for this service key. */
761 cache = digest256map_get(hs_cache_client_intro_state, service_pk->pubkey);
762 if (cache == NULL) {
764 digest256map_set(hs_cache_client_intro_state, service_pk->pubkey, cache);
765 }
766
767 entry = cache_intro_state_new();
768 old_entry = digest256map_set(cache->intro_points, auth_key->pubkey, entry);
769 /* This should never happened because the code flow is to lookup the entry
770 * before adding it. But, just in case, non fatal assert and free it. */
771 tor_assert_nonfatal(old_entry == NULL);
772 tor_free(old_entry);
773
774 if (state) {
775 *state = entry;
776 }
777}
778
779/** Remove every intro point state entry from cache that has been created
780 * before or at the cutoff. */
781static void
784{
785 tor_assert(cache);
786
787 DIGEST256MAP_FOREACH_MODIFY(cache->intro_points, key,
788 hs_cache_intro_state_t *, entry) {
789 if (entry->created_ts <= cutoff) {
790 cache_intro_state_free(entry);
791 MAP_DEL_CURRENT(key);
792 }
793 } DIGEST256MAP_FOREACH_END;
794}
795
796/** Return true iff no intro points are in this cache. */
797static int
799{
800 return digest256map_isempty(cache->intro_points);
801}
802
803/** Check whether <b>client_desc</b> is useful for us, and store it in the
804 * client-side HS cache if so. The client_desc is freed if we already have a
805 * fresher (higher revision counter count) in the cache. */
806static int
807cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
808{
809 hs_cache_client_descriptor_t *cache_entry;
810
811 /* TODO: Heavy code duplication with cache_store_as_dir(). Consider
812 * refactoring and uniting! */
813
814 tor_assert(client_desc);
815
816 /* Check if we already have a descriptor from this HS in cache. If we do,
817 * check if this descriptor is newer than the cached one only if we have a
818 * decoded descriptor. We do keep non-decoded descriptor that requires
819 * client authorization. */
820 cache_entry = lookup_v3_desc_as_client(client_desc->key.pubkey);
821 if (cache_entry != NULL) {
822 /* If the current or the new cache entry don't have a decrypted descriptor
823 * (missing client authorization), we always replace the current one with
824 * the new one. Reason is that we can't inspect the revision counter
825 * within the plaintext data so we blindly replace. */
826 if (!entry_has_decrypted_descriptor(cache_entry) ||
827 !entry_has_decrypted_descriptor(client_desc)) {
828 remove_v3_desc_as_client(cache_entry);
829 cache_client_desc_free(cache_entry);
830 goto store;
831 }
832
833 /* From this point on, we know that the decrypted descriptor is in the
834 * current entry and new object thus safe to access. */
835
836 /* If we have an entry in our cache that has a revision counter greater
837 * than the one we just fetched, discard the one we fetched. */
838 if (cache_entry->desc->plaintext_data.revision_counter >
839 client_desc->desc->plaintext_data.revision_counter) {
840 cache_client_desc_free(client_desc);
841 goto done;
842 }
843 /* Remove old entry. Make space for the new one! */
844 remove_v3_desc_as_client(cache_entry);
845
846 /* We just removed an old descriptor and will replace it. We'll close all
847 * intro circuits related to this old one so we don't have leftovers. We
848 * leave the rendezvous circuits opened because they could be in use. */
850
851 /* Free it. */
852 cache_client_desc_free(cache_entry);
853 }
854
855 store:
856 /* Store descriptor in cache */
857 store_v3_desc_as_client(client_desc);
858
859 done:
860 return 0;
861}
862
863/** Return true iff the cached client descriptor at <b>cached_desc</b> has
864 * expired. */
865static int
867 const hs_cache_client_descriptor_t *cached_desc)
868{
869 /* We use the current consensus time to see if we should expire this
870 * descriptor since we use consensus time for all other parts of the protocol
871 * as well (e.g. to build the blinded key and compute time periods). */
872 const networkstatus_t *ns =
875 /* If we don't have a recent consensus, consider this entry expired since we
876 * will want to fetch a new HS desc when we get a live consensus. */
877 if (!ns) {
878 return 1;
879 }
880
881 if (cached_desc->expiration_ts <= ns->valid_after) {
882 return 1;
883 }
884
885 return 0;
886}
887
888/** clean the client cache using now as the current time. Return the total size
889 * of removed bytes from the cache. */
890static size_t
892{
893 size_t bytes_removed = 0;
894
895 if (!hs_cache_v3_client) { /* No cache to clean. Just return. */
896 return 0;
897 }
898
899 DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_client, key,
900 hs_cache_client_descriptor_t *, entry) {
901 size_t entry_size;
902
903 /* If the entry has not expired, continue to the next cached entry */
904 if (!cached_client_descriptor_has_expired(now, entry)) {
905 continue;
906 }
907 /* Here, our entry has expired, remove and free. */
908 MAP_DEL_CURRENT(key);
909 entry_size = cache_get_client_entry_size(entry);
910 bytes_removed += entry_size;
911
912 /* We just removed an old descriptor. We need to close all intro circuits
913 * if the descriptor is decrypted so we don't have leftovers that can be
914 * selected while lacking a descriptor. Circuits are selected by intro
915 * authentication key thus we need the descriptor. We leave the rendezvous
916 * circuits opened because they could be in use. */
919 }
920 /* Entry is not in the cache anymore, destroy it. */
921 cache_client_desc_free(entry);
922 /* Update our OOM. We didn't use the remove() function because we are in
923 * a loop so we have to explicitly decrement. */
925 /* Logging. */
926 {
927 char key_b64[BASE64_DIGEST256_LEN + 1];
928 digest256_to_base64(key_b64, (const char *) key);
929 log_info(LD_REND, "Removing hidden service v3 descriptor '%s' "
930 "from client cache",
931 safe_str_client(key_b64));
932 }
933 } DIGEST256MAP_FOREACH_END;
934
935 return bytes_removed;
936}
937
938/** Public API: Given the HS ed25519 identity public key in <b>key</b>, return
939 * its HS encoded descriptor if it's stored in our cache, or NULL if not. */
940const char *
942{
943 hs_cache_client_descriptor_t *cached_desc = NULL;
944
945 tor_assert(key);
946
947 cached_desc = lookup_v3_desc_as_client(key->pubkey);
948 if (cached_desc) {
949 tor_assert(cached_desc->encoded_desc);
950 return cached_desc->encoded_desc;
951 }
952
953 return NULL;
954}
955
956/** Public API: Given the HS ed25519 identity public key in <b>key</b>, return
957 * its HS descriptor if it's stored in our cache, or NULL if not or if the
958 * descriptor was never decrypted. The later can happen if we are waiting for
959 * client authorization to be added. */
960const hs_descriptor_t *
962{
963 hs_cache_client_descriptor_t *cached_desc = NULL;
964
965 tor_assert(key);
966
967 cached_desc = lookup_v3_desc_as_client(key->pubkey);
968 if (cached_desc && entry_has_decrypted_descriptor(cached_desc)) {
969 return cached_desc->desc;
970 }
971
972 return NULL;
973}
974
975/** Public API: Given an encoded descriptor, store it in the client HS cache.
976 * Return a decode status which changes how we handle the SOCKS connection
977 * depending on its value:
978 *
979 * HS_DESC_DECODE_OK: Returned on success. Descriptor was properly decoded
980 * and is now stored.
981 *
982 * HS_DESC_DECODE_NEED_CLIENT_AUTH: Client authorization is needed but the
983 * descriptor was still stored.
984 *
985 * HS_DESC_DECODE_BAD_CLIENT_AUTH: Client authorization for this descriptor
986 * was not usable but the descriptor was
987 * still stored.
988 *
989 * Any other codes means indicate where the error occurred and the descriptor
990 * was not stored. */
992hs_cache_store_as_client(const char *desc_str,
993 const ed25519_public_key_t *identity_pk)
994{
996 hs_cache_client_descriptor_t *client_desc = NULL;
997
998 tor_assert(desc_str);
999 tor_assert(identity_pk);
1000
1001 /* Create client cache descriptor object */
1002 client_desc = cache_client_desc_new(desc_str, identity_pk, &ret);
1003 if (!client_desc) {
1004 log_warn(LD_GENERAL, "HSDesc parsing failed!");
1005 log_debug(LD_GENERAL, "Failed to parse HSDesc: %s.", escaped(desc_str));
1006 goto err;
1007 }
1008
1009 /* Push it to the cache */
1010 if (cache_store_as_client(client_desc) < 0) {
1011 ret = HS_DESC_DECODE_GENERIC_ERROR;
1012 goto err;
1013 }
1014
1015 return ret;
1016
1017 err:
1018 cache_client_desc_free(client_desc);
1019 return ret;
1020}
1021
1022/** Remove and free a client cache descriptor entry for the given onion
1023 * service ed25519 public key. If the descriptor is decoded, the intro
1024 * circuits are closed if any.
1025 *
1026 * This does nothing if no descriptor exists for the given key. */
1027void
1029{
1030 hs_cache_client_descriptor_t *cached_desc = NULL;
1031
1032 tor_assert(key);
1033
1034 cached_desc = lookup_v3_desc_as_client(key->pubkey);
1035 if (!cached_desc) {
1036 return;
1037 }
1038 /* If we have a decrypted/decoded descriptor, attempt to close its
1039 * introduction circuit(s). We shouldn't have circuit(s) without a
1040 * descriptor else it will lead to a failure. */
1041 if (entry_has_decrypted_descriptor(cached_desc)) {
1043 }
1044 /* Remove and free. */
1045 remove_v3_desc_as_client(cached_desc);
1046 cache_client_desc_free(cached_desc);
1047
1048 /* Logging. */
1049 {
1050 char key_b64[BASE64_DIGEST256_LEN + 1];
1051 digest256_to_base64(key_b64, (const char *) key);
1052 log_info(LD_REND, "Onion service v3 descriptor '%s' removed "
1053 "from client cache",
1054 safe_str_client(key_b64));
1055 }
1056}
1057
1058/** Clean all client caches using the current time now. */
1059void
1061{
1062 /* Now, clean the v3 cache. Set the cutoff to 0 telling the cleanup function
1063 * to compute the cutoff by itself using the lifetime value. */
1065}
1066
1067/** Purge the client descriptor cache. */
1068void
1070{
1071 DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_client, key,
1072 hs_cache_client_descriptor_t *, entry) {
1073 size_t entry_size = cache_get_client_entry_size(entry);
1074 MAP_DEL_CURRENT(key);
1075 cache_client_desc_free(entry);
1076 /* Update our OOM. We didn't use the remove() function because we are in
1077 * a loop so we have to explicitly decrement. */
1079 } DIGEST256MAP_FOREACH_END;
1080
1081 log_info(LD_REND, "Hidden service client descriptor cache purged.");
1082}
1083
1084/** For a given service identity public key and an introduction authentication
1085 * key, note the given failure in the client intro state cache. */
1086void
1088 const ed25519_public_key_t *auth_key,
1089 rend_intro_point_failure_t failure)
1090{
1091 int found;
1093
1094 tor_assert(service_pk);
1095 tor_assert(auth_key);
1096
1097 found = cache_client_intro_state_lookup(service_pk, auth_key, &entry);
1098 if (!found) {
1099 /* Create a new entry and add it to the cache. */
1100 cache_client_intro_state_add(service_pk, auth_key, &entry);
1101 }
1102 /* Note down the entry. */
1103 cache_client_intro_state_note(entry, failure);
1104}
1105
1106/** For a given service identity public key and an introduction authentication
1107 * key, return true iff it is present in the failure cache. */
1110 const ed25519_public_key_t *auth_key)
1111{
1112 hs_cache_intro_state_t *state = NULL;
1113 cache_client_intro_state_lookup(service_pk, auth_key, &state);
1114 return state;
1115}
1116
1117/** Cleanup the client introduction state cache. */
1118void
1120{
1121 time_t cutoff = now - HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE;
1122
1123 DIGEST256MAP_FOREACH_MODIFY(hs_cache_client_intro_state, key,
1125 /* Cleanup intro points failure. */
1126 cache_client_intro_state_clean(cutoff, cache);
1127
1128 /* Is this cache empty for this service key? If yes, remove it from the
1129 * cache. Else keep it. */
1131 cache_client_intro_state_free(cache);
1132 MAP_DEL_CURRENT(key);
1133 }
1134 } DIGEST256MAP_FOREACH_END;
1135}
1136
1137/** Purge the client introduction state cache. */
1138void
1140{
1141 DIGEST256MAP_FOREACH_MODIFY(hs_cache_client_intro_state, key,
1143 MAP_DEL_CURRENT(key);
1144 cache_client_intro_state_free(cache);
1145 } DIGEST256MAP_FOREACH_END;
1146
1147 log_info(LD_REND, "Hidden service client introduction point state "
1148 "cache purged.");
1149}
1150
1151/* This is called when new client authorization was added to the global state.
1152 * It attempts to decode the descriptor of the given service identity key.
1153 *
1154 * Return true if decoding was successful else false. */
1155bool
1156hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk)
1157{
1158 bool ret = false;
1159 hs_cache_client_descriptor_t *cached_desc = NULL;
1160
1161 tor_assert(service_pk);
1162
1163 if (!hs_cache_v3_client) {
1164 return false;
1165 }
1166
1167 cached_desc = lookup_v3_desc_as_client(service_pk->pubkey);
1168 if (cached_desc == NULL || entry_has_decrypted_descriptor(cached_desc)) {
1169 /* No entry for that service or the descriptor is already decoded. */
1170 goto end;
1171 }
1172
1173 /* Attempt a decode. If we are successful, inform the caller. */
1174 if (hs_client_decode_descriptor(cached_desc->encoded_desc, service_pk,
1175 &cached_desc->desc) == HS_DESC_DECODE_OK) {
1176 ret = true;
1177 }
1178
1179 end:
1180 return ret;
1181}
1182
1183/**************** Generics *********************************/
1184
1185/** Do a round of OOM cleanup on all directory caches. Return the amount of
1186 * removed bytes. It is possible that the returned value is lower than
1187 * min_remove_bytes if the caches get emptied out so the caller should be
1188 * aware of this. */
1189size_t
1190hs_cache_handle_oom(size_t min_remove_bytes)
1191{
1192 size_t bytes_removed = 0;
1193 /* The downloaded counter value to remove. Start at 0 and increment to the
1194 * next lowest value in the cache. */
1195 uint64_t target = 0;
1196
1197 /* Our OOM handler called with 0 bytes to remove is a code flow error. */
1198 tor_assert(min_remove_bytes != 0);
1199
1200 /* Loop until we have an empty cache or we have removed enough bytes. */
1201 do {
1202 /* This is valid due to the loop condition. At the start, min_remove_bytes
1203 * can't be 0. */
1204 size_t bytes_to_free = (min_remove_bytes - bytes_removed);
1205 size_t bytes_freed =
1206 cache_clean_v3_by_downloaded_as_dir(target, bytes_to_free, &target);
1207 if (bytes_freed == 0 && target == 0) {
1208 /* Indicate that the cache is empty. */
1209 break;
1210 }
1211 bytes_removed += bytes_freed;
1212 } while (bytes_removed < min_remove_bytes);
1213
1214 return bytes_removed;
1215}
1216
1217/** Return the maximum size of a v3 HS descriptor. */
1218unsigned int
1220{
1221 return (unsigned) networkstatus_get_param(NULL,
1222 "HSV3MaxDescriptorSize",
1223 HS_DESC_MAX_LEN, 1, INT32_MAX);
1224}
1225
1226/** Initialize the hidden service cache subsystem. */
1227void
1229{
1230 /* Calling this twice is very wrong code flow. */
1232 hs_cache_v3_dir = digest256map_new();
1233
1235 hs_cache_v3_client = digest256map_new();
1236
1238 hs_cache_client_intro_state = digest256map_new();
1239}
1240
1241/** Cleanup the hidden service cache subsystem. */
1242void
1244{
1245 digest256map_free(hs_cache_v3_dir, cache_dir_desc_free_void);
1246 hs_cache_v3_dir = NULL;
1247
1249 hs_cache_v3_client = NULL;
1250
1251 digest256map_free(hs_cache_client_intro_state,
1254 hs_cache_total_allocation = 0;
1255}
1256
1257/** Get the configured maximum cache size. */
1258uint64_t
1260{
1261 uint64_t opt = get_options()->MaxHSDirCacheBytes;
1262 return opt != 0 ? opt : get_options()->MaxMemInQueues / 5;
1263}
1264
1265/* Return total size of the cache. */
1266size_t
1267hs_cache_get_total_allocation(void)
1268{
1269 return hs_cache_total_allocation;
1270}
1271
1272/** Decrement the total bytes attributed to the rendezvous cache by n. */
1273void
1275{
1276 static int have_underflowed = 0;
1277
1278 if (hs_cache_total_allocation >= n) {
1279 hs_cache_total_allocation -= n;
1280 } else {
1281 hs_cache_total_allocation = 0;
1282 if (! have_underflowed) {
1283 have_underflowed = 1;
1284 log_warn(LD_BUG, "Underflow in hs_cache_decrement_allocation");
1285 }
1286 }
1287}
1288
1289/** Increase the total bytes attributed to the rendezvous cache by n. */
1290void
1292{
1293 static int have_overflowed = 0;
1294 if (hs_cache_total_allocation <= SIZE_MAX - n) {
1295 hs_cache_total_allocation += n;
1296 } else {
1297 hs_cache_total_allocation = SIZE_MAX;
1298 if (! have_overflowed) {
1299 have_overflowed = 1;
1300 log_warn(LD_BUG, "Overflow in hs_cache_increment_allocation");
1301 }
1302 }
1303}
1304
1305#ifdef TOR_UNIT_TESTS
1306
1307/** Test only: Set the downloaded counter value of a HSDir cache entry. */
1308void
1309dir_set_downloaded(const ed25519_public_key_t *pk, uint64_t value)
1310{
1312 if (entry) {
1313 entry->n_downloaded = value;
1314 }
1315}
1316
1317#endif /* TOR_UNIT_TESTS */
time_t approx_time(void)
Definition approx_time.c:32
const or_options_t * get_options(void)
Definition config.c:948
Header file for config.c.
#define BASE64_DIGEST256_LEN
void ed25519_pubkey_copy(ed25519_public_key_t *dest, const ed25519_public_key_t *src)
int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
void digest256_to_base64(char *d64, const char *digest)
int ed25519_public_from_base64(ed25519_public_key_t *pkey, const char *input)
Header for crypto_format.c.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition crypto_util.c:55
Common functions for cryptographic routines.
const char * escaped(const char *s)
Definition escape.c:126
static void cache_intro_state_free_(hs_cache_intro_state_t *state)
Definition hs_cache.c:642
static void cache_dir_desc_free_(hs_cache_dir_descriptor_t *desc)
Definition hs_cache.c:89
static void remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
Definition hs_cache.c:522
void hs_cache_client_intro_state_clean(time_t now)
Definition hs_cache.c:1119
void hs_cache_clean_as_client(time_t now)
Definition hs_cache.c:1060
static digest256map_t * hs_cache_v3_client
Definition hs_cache.c:465
uint64_t hs_cache_get_max_bytes(void)
Definition hs_cache.c:1259
static digest256map_t * hs_cache_v3_dir
Definition hs_cache.c:58
static void cache_dir_desc_free_void(void *ptr)
Definition hs_cache.c:102
static void cache_client_intro_state_add(const ed25519_public_key_t *service_pk, const ed25519_public_key_t *auth_key, hs_cache_intro_state_t **state)
Definition hs_cache.c:750
static int cache_lookup_v3_as_dir(const char *query, const char **desc_out)
Definition hs_cache.c:232
void hs_cache_client_intro_state_purge(void)
Definition hs_cache.c:1139
size_t hs_cache_handle_oom(size_t min_remove_bytes)
Definition hs_cache.c:1190
static void remove_v3_desc_as_dir(const hs_cache_dir_descriptor_t *desc)
Definition hs_cache.c:62
hs_desc_decode_status_t hs_cache_store_as_client(const char *desc_str, const ed25519_public_key_t *identity_pk)
Definition hs_cache.c:992
static int cache_client_intro_state_is_empty(const hs_cache_client_intro_state_t *cache)
Definition hs_cache.c:798
void hs_cache_remove_as_client(const ed25519_public_key_t *key)
Definition hs_cache.c:1028
static size_t cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry)
Definition hs_cache.c:139
static hs_cache_dir_descriptor_t * cache_dir_desc_new(const char *desc)
Definition hs_cache.c:111
static void cache_client_intro_state_free_(hs_cache_client_intro_state_t *cache)
Definition hs_cache.c:670
void hs_cache_free_all(void)
Definition hs_cache.c:1243
int hs_cache_lookup_as_dir(uint32_t version, const char *query, const char **desc_out)
Definition hs_cache.c:418
static hs_cache_intro_state_t * cache_intro_state_new(void)
Definition hs_cache.c:630
static void cache_intro_state_free_void(void *state)
Definition hs_cache.c:649
static void cache_client_intro_state_clean(time_t cutoff, hs_cache_client_intro_state_t *cache)
Definition hs_cache.c:782
static void store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
Definition hs_cache.c:532
static int cached_client_descriptor_has_expired(time_t now, const hs_cache_client_descriptor_t *cached_desc)
Definition hs_cache.c:866
STATIC size_t cache_clean_v3_by_downloaded_as_dir(const uint64_t target, const size_t max_remove_bytes, uint64_t *next_lowest)
Definition hs_cache.c:272
void hs_cache_mark_dowloaded_as_dir(const hs_ident_dir_conn_t *ident)
Definition hs_cache.c:441
void hs_cache_decrement_allocation(size_t n)
Definition hs_cache.c:1274
const char * hs_cache_lookup_encoded_as_client(const ed25519_public_key_t *key)
Definition hs_cache.c:941
STATIC size_t cache_clean_v3_as_dir(time_t now, time_t global_cutoff)
Definition hs_cache.c:332
static bool entry_has_decrypted_descriptor(const hs_cache_client_descriptor_t *entry)
Definition hs_cache.c:49
static void cache_client_desc_free_void(void *ptr)
Definition hs_cache.c:491
int hs_cache_store_as_dir(const char *desc)
Definition hs_cache.c:381
static digest256map_t * hs_cache_client_intro_state
Definition hs_cache.c:470
static int cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
Definition hs_cache.c:807
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)
Definition hs_cache.c:1109
unsigned int hs_cache_get_max_descriptor_size(void)
Definition hs_cache.c:1219
void hs_cache_clean_as_dir(time_t now)
Definition hs_cache.c:455
void hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk, const ed25519_public_key_t *auth_key, rend_intro_point_failure_t failure)
Definition hs_cache.c:1087
static void store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc)
Definition hs_cache.c:70
static hs_cache_client_descriptor_t * cache_client_desc_new(const char *desc_str, const ed25519_public_key_t *service_identity_pk, hs_desc_decode_status_t *decode_status_out)
Definition hs_cache.c:580
void hs_cache_purge_as_client(void)
Definition hs_cache.c:1069
static int cache_client_intro_state_lookup(const ed25519_public_key_t *service_pk, const ed25519_public_key_t *auth_key, hs_cache_intro_state_t **entry)
Definition hs_cache.c:691
static size_t cache_clean_v3_as_client(time_t now)
Definition hs_cache.c:891
static int cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc)
Definition hs_cache.c:150
void hs_cache_increment_allocation(size_t n)
Definition hs_cache.c:1291
#define HSCACHE_PRUNE_SPARE_ROOM
Definition hs_cache.c:32
STATIC hs_cache_dir_descriptor_t * lookup_v3_desc_as_dir(const uint8_t *key)
Definition hs_cache.c:78
static size_t cache_get_client_entry_size(const hs_cache_client_descriptor_t *entry)
Definition hs_cache.c:499
void hs_cache_init(void)
Definition hs_cache.c:1228
static void cache_client_desc_free_(hs_cache_client_descriptor_t *desc)
Definition hs_cache.c:477
const hs_descriptor_t * hs_cache_lookup_as_client(const ed25519_public_key_t *key)
Definition hs_cache.c:961
static hs_cache_client_intro_state_t * cache_client_intro_state_new(void)
Definition hs_cache.c:657
static void cache_client_intro_state_note(hs_cache_intro_state_t *state, rend_intro_point_failure_t failure)
Definition hs_cache.c:725
static void cache_client_intro_state_free_void(void *entry)
Definition hs_cache.c:681
STATIC hs_cache_client_descriptor_t * lookup_v3_desc_as_client(const uint8_t *key)
Definition hs_cache.c:553
Header file for hs_cache.c.
#define HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE
Definition hs_cache.h:24
void hs_client_close_intro_circuits_from_desc(const hs_descriptor_t *desc)
Definition hs_client.c:2713
hs_desc_decode_status_t hs_client_decode_descriptor(const char *desc_str, const ed25519_public_key_t *service_identity_pk, hs_descriptor_t **desc)
Definition hs_client.c:2148
Header file containing client data for the HS subsystem.
time_t hs_get_start_time_of_next_time_period(time_t now)
Definition hs_common.c:324
Header file containing common data for the whole HS subsystem.
#define HS_VERSION_THREE
Definition hs_common.h:23
size_t hs_desc_plaintext_obj_size(const hs_desc_plaintext_data_t *data)
size_t hs_desc_obj_size(const hs_descriptor_t *data)
hs_desc_decode_status_t hs_desc_decode_plaintext(const char *encoded, hs_desc_plaintext_data_t *plaintext)
Header file for hs_descriptor.c.
hs_desc_decode_status_t
static int hs_desc_is_supported_version(uint32_t version)
#define HS_DESC_MAX_LEN
Header file containing circuit and connection identifier data for the whole HS subsystem.
#define LD_REND
Definition log.h:84
#define log_fn_ratelim(ratelim, severity, domain, args,...)
Definition log.h:288
#define LD_BUG
Definition log.h:86
#define LD_GENERAL
Definition log.h:62
#define LD_DIR
Definition log.h:88
#define LOG_NOTICE
Definition log.h:50
#define tor_free(p)
Definition malloc.h:56
#define MAP_DEL_CURRENT(keyvar)
Definition map.h:140
int usable_consensus_flavor(void)
Definition microdesc.c:1088
Header file for microdesc.c.
networkstatus_t * networkstatus_get_reasonably_live_consensus(time_t now, int flavor)
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
Networkstatus consensus/vote structure.
Master header file for Tor-specific functionality.
void rep_hist_hsdir_stored_maybe_new_v3_onion(const uint8_t *blinded_key)
Definition rephist.c:2595
Header file for rephist.c.
digest256map_t * intro_points
Definition hs_cache.h:52
hs_desc_plaintext_data_t * plaintext_data
Definition hs_cache.h:68
const uint8_t * key
Definition hs_cache.h:61
unsigned int error
Definition hs_cache.h:40
unsigned int timed_out
Definition hs_cache.h:43
uint32_t unreachable_count
Definition hs_cache.h:46
ed25519_public_key_t blinded_pubkey
ed25519_public_key_t blinded_pk
Definition hs_ident.h:95
uint64_t MaxMemInQueues
uint64_t MaxHSDirCacheBytes
#define STATIC
Definition testsupport.h:32
Integer definitions used throughout Tor.
#define tor_assert_nonfatal_unreached()
Definition util_bug.h:177
#define tor_assert(expr)
Definition util_bug.h:103