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