Tor  0.4.6.0-alpha-dev
hs_cache.c
Go to the documentation of this file.
1 /* Copyright (c) 2016-2020, 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 "feature/hs/hs_ident.h"
17 #include "feature/hs/hs_common.h"
18 #include "feature/hs/hs_client.h"
21 #include "feature/rend/rendcache.h"
22 #include "feature/stats/rephist.h"
23 
24 #include "feature/hs/hs_cache.h"
25 
27 
28 static int cached_client_descriptor_has_expired(time_t now,
29  const hs_cache_client_descriptor_t *cached_desc);
30 
31 /** Helper function: Return true iff the cache entry has a decrypted
32  * descriptor.
33  *
34  * A NULL desc object in the entry means that we were not able to decrypt the
35  * descriptor because we are likely lacking client authorization. It is still
36  * a valid entry but some operations can't be done without the decrypted
37  * descriptor thus this function MUST be used to safe guard access to the
38  * decrypted desc object. */
39 static inline bool
40 entry_has_decrypted_descriptor(const hs_cache_client_descriptor_t *entry)
41 {
42  tor_assert(entry);
43  return (entry->desc != NULL);
44 }
45 
46 /********************** Directory HS cache ******************/
47 
48 /** Directory descriptor cache. Map indexed by blinded key. */
49 static digest256map_t *hs_cache_v3_dir;
50 
51 /** Remove a given descriptor from our cache. */
52 static void
54 {
55  tor_assert(desc);
56  digest256map_remove(hs_cache_v3_dir, desc->key);
57 }
58 
59 /** Store a given descriptor in our cache. */
60 static void
62 {
63  tor_assert(desc);
64  digest256map_set(hs_cache_v3_dir, desc->key, desc);
65 }
66 
67 /** Query our cache and return the entry or NULL if not found. */
69 lookup_v3_desc_as_dir(const uint8_t *key)
70 {
71  tor_assert(key);
72  return digest256map_get(hs_cache_v3_dir, key);
73 }
74 
75 #define cache_dir_desc_free(val) \
76  FREE_AND_NULL(hs_cache_dir_descriptor_t, cache_dir_desc_free_, (val))
77 
78 /** Free a directory descriptor object. */
79 static void
81 {
82  if (desc == NULL) {
83  return;
84  }
85  hs_desc_plaintext_data_free(desc->plaintext_data);
86  tor_free(desc->encoded_desc);
87  tor_free(desc);
88 }
89 
90 /** Helper function: Use by the free all function using the digest256map
91  * interface to cache entries. */
92 static void
94 {
96 }
97 
98 /** Create a new directory cache descriptor object from a encoded descriptor.
99  * On success, return the heap-allocated cache object, otherwise return NULL if
100  * we can't decode the descriptor. */
102 cache_dir_desc_new(const char *desc)
103 {
104  hs_cache_dir_descriptor_t *dir_desc;
105 
106  tor_assert(desc);
107 
108  dir_desc = tor_malloc_zero(sizeof(hs_cache_dir_descriptor_t));
109  dir_desc->plaintext_data =
110  tor_malloc_zero(sizeof(hs_desc_plaintext_data_t));
111  dir_desc->encoded_desc = tor_strdup(desc);
112 
113  if (hs_desc_decode_plaintext(desc, dir_desc->plaintext_data) < 0) {
114  log_debug(LD_DIR, "Unable to decode descriptor. Rejecting.");
115  goto err;
116  }
117 
118  /* The blinded pubkey is the indexed key. */
119  dir_desc->key = dir_desc->plaintext_data->blinded_pubkey.pubkey;
120  dir_desc->created_ts = time(NULL);
121  return dir_desc;
122 
123  err:
124  cache_dir_desc_free(dir_desc);
125  return NULL;
126 }
127 
128 /** Return the size of a cache entry in bytes. */
129 static size_t
131 {
132  return (sizeof(*entry) + hs_desc_plaintext_obj_size(entry->plaintext_data)
133  + strlen(entry->encoded_desc));
134 }
135 
136 /** Try to store a valid version 3 descriptor in the directory cache. Return 0
137  * on success else a negative value is returned indicating that we have a
138  * newer version in our cache. On error, caller is responsible to free the
139  * given descriptor desc. */
140 static int
142 {
143  hs_cache_dir_descriptor_t *cache_entry;
144 
145  tor_assert(desc);
146 
147  /* Verify if we have an entry in the cache for that key and if yes, check
148  * if we should replace it? */
149  cache_entry = lookup_v3_desc_as_dir(desc->key);
150  if (cache_entry != NULL) {
151  /* Only replace descriptor if revision-counter is greater than the one
152  * in our cache */
153  if (cache_entry->plaintext_data->revision_counter >=
155  log_info(LD_REND, "Descriptor revision counter in our cache is "
156  "greater or equal than the one we received (%d/%d). "
157  "Rejecting!",
158  (int)cache_entry->plaintext_data->revision_counter,
159  (int)desc->plaintext_data->revision_counter);
160  goto err;
161  }
162  /* We now know that the descriptor we just received is a new one so
163  * remove the entry we currently have from our cache so we can then
164  * store the new one. */
165  remove_v3_desc_as_dir(cache_entry);
167  cache_dir_desc_free(cache_entry);
168  }
169  /* Store the descriptor we just got. We are sure here that either we
170  * don't have the entry or we have a newer descriptor and the old one
171  * has been removed from the cache. */
172  store_v3_desc_as_dir(desc);
173 
174  /* Update our total cache size with this entry for the OOM. This uses the
175  * old HS protocol cache subsystem for which we are tied with. */
177 
178  /* Update HSv3 statistics */
179  if (get_options()->HiddenServiceStatistics) {
181  }
182 
183  return 0;
184 
185  err:
186  return -1;
187 }
188 
189 /** Using the query which is the base64 encoded blinded key of a version 3
190  * descriptor, lookup in our directory cache the entry. If found, 1 is
191  * returned and desc_out is populated with a newly allocated string being the
192  * encoded descriptor. If not found, 0 is returned and desc_out is untouched.
193  * On error, a negative value is returned and desc_out is untouched. */
194 static int
195 cache_lookup_v3_as_dir(const char *query, const char **desc_out)
196 {
197  int found = 0;
198  ed25519_public_key_t blinded_key;
199  const hs_cache_dir_descriptor_t *entry;
200 
201  tor_assert(query);
202 
203  /* Decode blinded key using the given query value. */
204  if (ed25519_public_from_base64(&blinded_key, query) < 0) {
205  log_info(LD_REND, "Unable to decode the v3 HSDir query %s.",
206  safe_str_client(query));
207  goto err;
208  }
209 
210  entry = lookup_v3_desc_as_dir(blinded_key.pubkey);
211  if (entry != NULL) {
212  found = 1;
213  if (desc_out) {
214  *desc_out = entry->encoded_desc;
215  }
216  }
217 
218  return found;
219 
220  err:
221  return -1;
222 }
223 
224 /** Clean the v3 cache by removing any entry that has expired using the
225  * <b>global_cutoff</b> value. If <b>global_cutoff</b> is 0, the cleaning
226  * process will use the lifetime found in the plaintext data section. Return
227  * the number of bytes cleaned. */
228 STATIC size_t
229 cache_clean_v3_as_dir(time_t now, time_t global_cutoff)
230 {
231  size_t bytes_removed = 0;
232 
233  /* Code flow error if this ever happens. */
234  tor_assert(global_cutoff >= 0);
235 
236  if (!hs_cache_v3_dir) { /* No cache to clean. Just return. */
237  return 0;
238  }
239 
240  DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_dir, key,
241  hs_cache_dir_descriptor_t *, entry) {
242  size_t entry_size;
243  time_t cutoff = global_cutoff;
244  if (!cutoff) {
245  /* Cutoff is the lifetime of the entry found in the descriptor. */
246  cutoff = now - entry->plaintext_data->lifetime_sec;
247  }
248 
249  /* If the entry has been created _after_ the cutoff, not expired so
250  * continue to the next entry in our v3 cache. */
251  if (entry->created_ts > cutoff) {
252  continue;
253  }
254  /* Here, our entry has expired, remove and free. */
255  MAP_DEL_CURRENT(key);
256  entry_size = cache_get_dir_entry_size(entry);
257  bytes_removed += entry_size;
258  /* Entry is not in the cache anymore, destroy it. */
259  cache_dir_desc_free(entry);
260  /* Update our cache entry allocation size for the OOM. */
262  /* Logging. */
263  {
264  char key_b64[BASE64_DIGEST256_LEN + 1];
265  digest256_to_base64(key_b64, (const char *) key);
266  log_info(LD_REND, "Removing v3 descriptor '%s' from HSDir cache",
267  safe_str_client(key_b64));
268  }
269  } DIGEST256MAP_FOREACH_END;
270 
271  return bytes_removed;
272 }
273 
274 /** Given an encoded descriptor, store it in the directory cache depending on
275  * which version it is. Return a negative value on error. On success, 0 is
276  * returned. */
277 int
278 hs_cache_store_as_dir(const char *desc)
279 {
280  hs_cache_dir_descriptor_t *dir_desc = NULL;
281 
282  tor_assert(desc);
283 
284  /* Create a new cache object. This can fail if the descriptor plaintext data
285  * is unparseable which in this case a log message will be triggered. */
286  dir_desc = cache_dir_desc_new(desc);
287  if (dir_desc == NULL) {
288  goto err;
289  }
290 
291  /* Call the right function against the descriptor version. At this point,
292  * we are sure that the descriptor's version is supported else the
293  * decoding would have failed. */
294  switch (dir_desc->plaintext_data->version) {
295  case HS_VERSION_THREE:
296  default:
297  if (cache_store_v3_as_dir(dir_desc) < 0) {
298  goto err;
299  }
300  break;
301  }
302  return 0;
303 
304  err:
305  cache_dir_desc_free(dir_desc);
306  return -1;
307 }
308 
309 /** Using the query, lookup in our directory cache the entry. If found, 1 is
310  * returned and desc_out is populated with a newly allocated string being
311  * the encoded descriptor. If not found, 0 is returned and desc_out is
312  * untouched. On error, a negative value is returned and desc_out is
313  * untouched. */
314 int
315 hs_cache_lookup_as_dir(uint32_t version, const char *query,
316  const char **desc_out)
317 {
318  int found;
319 
320  tor_assert(query);
321  /* This should never be called with an unsupported version. */
323 
324  switch (version) {
325  case HS_VERSION_THREE:
326  default:
327  found = cache_lookup_v3_as_dir(query, desc_out);
328  break;
329  }
330 
331  return found;
332 }
333 
334 /** Clean all directory caches using the current time now. */
335 void
337 {
338  time_t cutoff;
339 
340  /* Start with v2 cache cleaning. */
341  cutoff = now - rend_cache_max_entry_lifetime();
343 
344  /* Now, clean the v3 cache. Set the cutoff to 0 telling the cleanup function
345  * to compute the cutoff by itself using the lifetime value. */
346  cache_clean_v3_as_dir(now, 0);
347 }
348 
349 /********************** Client-side HS cache ******************/
350 
351 /** Client-side HS descriptor cache. Map indexed by service identity key. */
352 static digest256map_t *hs_cache_v3_client;
353 
354 /** Client-side introduction point state cache. Map indexed by service public
355  * identity key (onion address). It contains hs_cache_client_intro_state_t
356  * objects all related to a specific service. */
357 static digest256map_t *hs_cache_client_intro_state;
358 
359 /** Return the size of a client cache entry in bytes. */
360 static size_t
361 cache_get_client_entry_size(const hs_cache_client_descriptor_t *entry)
362 {
363  size_t size = 0;
364 
365  if (entry == NULL) {
366  goto end;
367  }
368  size += sizeof(*entry);
369 
370  if (entry->encoded_desc) {
371  size += strlen(entry->encoded_desc);
372  }
373 
374  if (entry_has_decrypted_descriptor(entry)) {
375  size += hs_desc_obj_size(entry->desc);
376  }
377 
378  end:
379  return size;
380 }
381 
382 /** Remove a given descriptor from our cache. */
383 static void
384 remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
385 {
386  tor_assert(desc);
387  digest256map_remove(hs_cache_v3_client, desc->key.pubkey);
388  /* Update cache size with this entry for the OOM handler. */
390 }
391 
392 /** Store a given descriptor in our cache. */
393 static void
394 store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
395 {
396  tor_assert(desc);
397  digest256map_set(hs_cache_v3_client, desc->key.pubkey, desc);
398  /* Update cache size with this entry for the OOM handler. */
400 }
401 
402 /** Query our cache and return the entry or NULL if not found or if expired. */
403 STATIC hs_cache_client_descriptor_t *
404 lookup_v3_desc_as_client(const uint8_t *key)
405 {
406  time_t now = approx_time();
407  hs_cache_client_descriptor_t *cached_desc;
408 
409  tor_assert(key);
410 
411  /* Do the lookup */
412  cached_desc = digest256map_get(hs_cache_v3_client, key);
413  if (!cached_desc) {
414  return NULL;
415  }
416 
417  /* Don't return expired entries */
418  if (cached_client_descriptor_has_expired(now, cached_desc)) {
419  return NULL;
420  }
421 
422  return cached_desc;
423 }
424 
425 /** Parse the encoded descriptor in <b>desc_str</b> using
426  * <b>service_identity_pk</b> to decrypt it first.
427  *
428  * If everything goes well, allocate and return a new
429  * hs_cache_client_descriptor_t object. In case of error, return NULL. */
430 static hs_cache_client_descriptor_t *
431 cache_client_desc_new(const char *desc_str,
432  const ed25519_public_key_t *service_identity_pk,
433  hs_desc_decode_status_t *decode_status_out)
434 {
436  hs_descriptor_t *desc = NULL;
437  hs_cache_client_descriptor_t *client_desc = NULL;
438 
439  tor_assert(desc_str);
440  tor_assert(service_identity_pk);
441 
442  /* Decode the descriptor we just fetched. */
443  ret = hs_client_decode_descriptor(desc_str, service_identity_pk, &desc);
444  if (ret != HS_DESC_DECODE_OK &&
445  ret != HS_DESC_DECODE_NEED_CLIENT_AUTH &&
446  ret != HS_DESC_DECODE_BAD_CLIENT_AUTH) {
447  /* In the case of a missing or bad client authorization, we'll keep the
448  * descriptor in the cache because those credentials can arrive later. */
449  goto end;
450  }
451  /* Make sure we do have a descriptor if decoding was successful. */
452  if (ret == HS_DESC_DECODE_OK) {
453  tor_assert(desc);
454  } else {
455  if (BUG(desc != NULL)) {
456  /* We are not suppose to have a descriptor if the decoding code is not
457  * indicating success. Just in case, bail early to recover. */
458  goto end;
459  }
460  }
461 
462  /* All is good: make a cache object for this descriptor */
463  client_desc = tor_malloc_zero(sizeof(hs_cache_client_descriptor_t));
464  ed25519_pubkey_copy(&client_desc->key, service_identity_pk);
465  /* Set expiration time for this cached descriptor to be the start of the next
466  * time period since that's when clients need to start using the next blinded
467  * pk of the service (and hence will need its next descriptor). */
468  client_desc->expiration_ts = hs_get_start_time_of_next_time_period(0);
469  client_desc->desc = desc;
470  client_desc->encoded_desc = tor_strdup(desc_str);
471 
472  end:
473  if (decode_status_out) {
474  *decode_status_out = ret;
475  }
476  return client_desc;
477 }
478 
479 #define cache_client_desc_free(val) \
480  FREE_AND_NULL(hs_cache_client_descriptor_t, cache_client_desc_free_, (val))
481 
482 /** Free memory allocated by <b>desc</b>. */
483 static void
484 cache_client_desc_free_(hs_cache_client_descriptor_t *desc)
485 {
486  if (desc == NULL) {
487  return;
488  }
489  hs_descriptor_free(desc->desc);
490  memwipe(&desc->key, 0, sizeof(desc->key));
491  memwipe(desc->encoded_desc, 0, strlen(desc->encoded_desc));
492  tor_free(desc->encoded_desc);
493  tor_free(desc);
494 }
495 
496 /** Helper function: Use by the free all function to clear the client cache */
497 static void
499 {
500  hs_cache_client_descriptor_t *desc = ptr;
501  cache_client_desc_free(desc);
502 }
503 
504 /** Return a newly allocated and initialized hs_cache_intro_state_t object. */
505 static hs_cache_intro_state_t *
507 {
508  hs_cache_intro_state_t *state = tor_malloc_zero(sizeof(*state));
509  state->created_ts = approx_time();
510  return state;
511 }
512 
513 #define cache_intro_state_free(val) \
514  FREE_AND_NULL(hs_cache_intro_state_t, cache_intro_state_free_, (val))
515 
516 /** Free an hs_cache_intro_state_t object. */
517 static void
519 {
520  tor_free(state);
521 }
522 
523 /** Helper function: used by the free all function. */
524 static void
526 {
528 }
529 
530 /** Return a newly allocated and initialized hs_cache_client_intro_state_t
531  * object. */
534 {
535  hs_cache_client_intro_state_t *cache = tor_malloc_zero(sizeof(*cache));
536  cache->intro_points = digest256map_new();
537  return cache;
538 }
539 
540 #define cache_client_intro_state_free(val) \
541  FREE_AND_NULL(hs_cache_client_intro_state_t, \
542  cache_client_intro_state_free_, (val))
543 
544 /** Free a cache_client_intro_state object. */
545 static void
547 {
548  if (cache == NULL) {
549  return;
550  }
551  digest256map_free(cache->intro_points, cache_intro_state_free_void);
552  tor_free(cache);
553 }
554 
555 /** Helper function: used by the free all function. */
556 static void
558 {
560 }
561 
562 /** For the given service identity key service_pk and an introduction
563  * authentication key auth_key, lookup the intro state object. Return 1 if
564  * found and put it in entry if not NULL. Return 0 if not found and entry is
565  * untouched. */
566 static int
568  const ed25519_public_key_t *auth_key,
569  hs_cache_intro_state_t **entry)
570 {
571  hs_cache_intro_state_t *state;
573 
574  tor_assert(service_pk);
575  tor_assert(auth_key);
576 
577  /* Lookup the intro state cache for this service key. */
578  cache = digest256map_get(hs_cache_client_intro_state, service_pk->pubkey);
579  if (cache == NULL) {
580  goto not_found;
581  }
582 
583  /* From the cache we just found for the service, lookup in the introduction
584  * points map for the given authentication key. */
585  state = digest256map_get(cache->intro_points, auth_key->pubkey);
586  if (state == NULL) {
587  goto not_found;
588  }
589  if (entry) {
590  *entry = state;
591  }
592  return 1;
593  not_found:
594  return 0;
595 }
596 
597 /** Note the given failure in state. */
598 static void
600  rend_intro_point_failure_t failure)
601 {
602  tor_assert(state);
603  switch (failure) {
604  case INTRO_POINT_FAILURE_GENERIC:
605  state->error = 1;
606  break;
607  case INTRO_POINT_FAILURE_TIMEOUT:
608  state->timed_out = 1;
609  break;
610  case INTRO_POINT_FAILURE_UNREACHABLE:
611  state->unreachable_count++;
612  break;
613  default:
615  return;
616  }
617 }
618 
619 /** For the given service identity key service_pk and an introduction
620  * authentication key auth_key, add an entry in the client intro state cache
621  * If no entry exists for the service, it will create one. If state is non
622  * NULL, it will point to the new intro state entry. */
623 static void
625  const ed25519_public_key_t *auth_key,
626  hs_cache_intro_state_t **state)
627 {
628  hs_cache_intro_state_t *entry, *old_entry;
630 
631  tor_assert(service_pk);
632  tor_assert(auth_key);
633 
634  /* Lookup the state cache for this service key. */
635  cache = digest256map_get(hs_cache_client_intro_state, service_pk->pubkey);
636  if (cache == NULL) {
638  digest256map_set(hs_cache_client_intro_state, service_pk->pubkey, cache);
639  }
640 
641  entry = cache_intro_state_new();
642  old_entry = digest256map_set(cache->intro_points, auth_key->pubkey, entry);
643  /* This should never happened because the code flow is to lookup the entry
644  * before adding it. But, just in case, non fatal assert and free it. */
645  tor_assert_nonfatal(old_entry == NULL);
646  tor_free(old_entry);
647 
648  if (state) {
649  *state = entry;
650  }
651 }
652 
653 /** Remove every intro point state entry from cache that has been created
654  * before or at the cutoff. */
655 static void
658 {
659  tor_assert(cache);
660 
661  DIGEST256MAP_FOREACH_MODIFY(cache->intro_points, key,
662  hs_cache_intro_state_t *, entry) {
663  if (entry->created_ts <= cutoff) {
664  cache_intro_state_free(entry);
665  MAP_DEL_CURRENT(key);
666  }
667  } DIGEST256MAP_FOREACH_END;
668 }
669 
670 /** Return true iff no intro points are in this cache. */
671 static int
673 {
674  return digest256map_isempty(cache->intro_points);
675 }
676 
677 /** Check whether <b>client_desc</b> is useful for us, and store it in the
678  * client-side HS cache if so. The client_desc is freed if we already have a
679  * fresher (higher revision counter count) in the cache. */
680 static int
681 cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
682 {
683  hs_cache_client_descriptor_t *cache_entry;
684 
685  /* TODO: Heavy code duplication with cache_store_as_dir(). Consider
686  * refactoring and uniting! */
687 
688  tor_assert(client_desc);
689 
690  /* Check if we already have a descriptor from this HS in cache. If we do,
691  * check if this descriptor is newer than the cached one only if we have a
692  * decoded descriptor. We do keep non-decoded descriptor that requires
693  * client authorization. */
694  cache_entry = lookup_v3_desc_as_client(client_desc->key.pubkey);
695  if (cache_entry != NULL) {
696  /* If the current or the new cache entry don't have a decrypted descriptor
697  * (missing client authorization), we always replace the current one with
698  * the new one. Reason is that we can't inspect the revision counter
699  * within the plaintext data so we blindly replace. */
700  if (!entry_has_decrypted_descriptor(cache_entry) ||
701  !entry_has_decrypted_descriptor(client_desc)) {
702  remove_v3_desc_as_client(cache_entry);
703  cache_client_desc_free(cache_entry);
704  goto store;
705  }
706 
707  /* From this point on, we know that the decrypted descriptor is in the
708  * current entry and new object thus safe to access. */
709 
710  /* If we have an entry in our cache that has a revision counter greater
711  * than the one we just fetched, discard the one we fetched. */
712  if (cache_entry->desc->plaintext_data.revision_counter >
713  client_desc->desc->plaintext_data.revision_counter) {
714  cache_client_desc_free(client_desc);
715  goto done;
716  }
717  /* Remove old entry. Make space for the new one! */
718  remove_v3_desc_as_client(cache_entry);
719 
720  /* We just removed an old descriptor and will replace it. We'll close all
721  * intro circuits related to this old one so we don't have leftovers. We
722  * leave the rendezvous circuits opened because they could be in use. */
723  hs_client_close_intro_circuits_from_desc(cache_entry->desc);
724 
725  /* Free it. */
726  cache_client_desc_free(cache_entry);
727  }
728 
729  store:
730  /* Store descriptor in cache */
731  store_v3_desc_as_client(client_desc);
732 
733  done:
734  return 0;
735 }
736 
737 /** Return true iff the cached client descriptor at <b>cached_desc</b> has
738  * expired. */
739 static int
741  const hs_cache_client_descriptor_t *cached_desc)
742 {
743  /* We use the current consensus time to see if we should expire this
744  * descriptor since we use consensus time for all other parts of the protocol
745  * as well (e.g. to build the blinded key and compute time periods). */
747  /* If we don't have a recent consensus, consider this entry expired since we
748  * will want to fetch a new HS desc when we get a live consensus. */
749  if (!ns) {
750  return 1;
751  }
752 
753  if (cached_desc->expiration_ts <= ns->valid_after) {
754  return 1;
755  }
756 
757  return 0;
758 }
759 
760 /** clean the client cache using now as the current time. Return the total size
761  * of removed bytes from the cache. */
762 static size_t
764 {
765  size_t bytes_removed = 0;
766 
767  if (!hs_cache_v3_client) { /* No cache to clean. Just return. */
768  return 0;
769  }
770 
771  DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_client, key,
772  hs_cache_client_descriptor_t *, entry) {
773  size_t entry_size;
774 
775  /* If the entry has not expired, continue to the next cached entry */
776  if (!cached_client_descriptor_has_expired(now, entry)) {
777  continue;
778  }
779  /* Here, our entry has expired, remove and free. */
780  MAP_DEL_CURRENT(key);
781  entry_size = cache_get_client_entry_size(entry);
782  bytes_removed += entry_size;
783 
784  /* We just removed an old descriptor. We need to close all intro circuits
785  * if the descriptor is decrypted so we don't have leftovers that can be
786  * selected while lacking a descriptor. Circuits are selected by intro
787  * authentication key thus we need the descriptor. We leave the rendezvous
788  * circuits opened because they could be in use. */
789  if (entry_has_decrypted_descriptor(entry)) {
791  }
792  /* Entry is not in the cache anymore, destroy it. */
793  cache_client_desc_free(entry);
794  /* Update our OOM. We didn't use the remove() function because we are in
795  * a loop so we have to explicitly decrement. */
797  /* Logging. */
798  {
799  char key_b64[BASE64_DIGEST256_LEN + 1];
800  digest256_to_base64(key_b64, (const char *) key);
801  log_info(LD_REND, "Removing hidden service v3 descriptor '%s' "
802  "from client cache",
803  safe_str_client(key_b64));
804  }
805  } DIGEST256MAP_FOREACH_END;
806 
807  return bytes_removed;
808 }
809 
810 /** Public API: Given the HS ed25519 identity public key in <b>key</b>, return
811  * its HS encoded descriptor if it's stored in our cache, or NULL if not. */
812 const char *
814 {
815  hs_cache_client_descriptor_t *cached_desc = NULL;
816 
817  tor_assert(key);
818 
819  cached_desc = lookup_v3_desc_as_client(key->pubkey);
820  if (cached_desc) {
821  tor_assert(cached_desc->encoded_desc);
822  return cached_desc->encoded_desc;
823  }
824 
825  return NULL;
826 }
827 
828 /** Public API: Given the HS ed25519 identity public key in <b>key</b>, return
829  * its HS descriptor if it's stored in our cache, or NULL if not or if the
830  * descriptor was never decrypted. The later can happen if we are waiting for
831  * client authorization to be added. */
832 const hs_descriptor_t *
834 {
835  hs_cache_client_descriptor_t *cached_desc = NULL;
836 
837  tor_assert(key);
838 
839  cached_desc = lookup_v3_desc_as_client(key->pubkey);
840  if (cached_desc && entry_has_decrypted_descriptor(cached_desc)) {
841  return cached_desc->desc;
842  }
843 
844  return NULL;
845 }
846 
847 /** Public API: Given an encoded descriptor, store it in the client HS cache.
848  * Return a decode status which changes how we handle the SOCKS connection
849  * depending on its value:
850  *
851  * HS_DESC_DECODE_OK: Returned on success. Descriptor was properly decoded
852  * and is now stored.
853  *
854  * HS_DESC_DECODE_NEED_CLIENT_AUTH: Client authorization is needed but the
855  * descriptor was still stored.
856  *
857  * HS_DESC_DECODE_BAD_CLIENT_AUTH: Client authorization for this descriptor
858  * was not usable but the descriptor was
859  * still stored.
860  *
861  * Any other codes means indicate where the error occurred and the descriptor
862  * was not stored. */
864 hs_cache_store_as_client(const char *desc_str,
865  const ed25519_public_key_t *identity_pk)
866 {
868  hs_cache_client_descriptor_t *client_desc = NULL;
869 
870  tor_assert(desc_str);
871  tor_assert(identity_pk);
872 
873  /* Create client cache descriptor object */
874  client_desc = cache_client_desc_new(desc_str, identity_pk, &ret);
875  if (!client_desc) {
876  log_warn(LD_GENERAL, "HSDesc parsing failed!");
877  log_debug(LD_GENERAL, "Failed to parse HSDesc: %s.", escaped(desc_str));
878  goto err;
879  }
880 
881  /* Push it to the cache */
882  if (cache_store_as_client(client_desc) < 0) {
883  ret = HS_DESC_DECODE_GENERIC_ERROR;
884  goto err;
885  }
886 
887  return ret;
888 
889  err:
890  cache_client_desc_free(client_desc);
891  return ret;
892 }
893 
894 /** Remove and free a client cache descriptor entry for the given onion
895  * service ed25519 public key. If the descriptor is decoded, the intro
896  * circuits are closed if any.
897  *
898  * This does nothing if no descriptor exists for the given key. */
899 void
901 {
902  hs_cache_client_descriptor_t *cached_desc = NULL;
903 
904  tor_assert(key);
905 
906  cached_desc = lookup_v3_desc_as_client(key->pubkey);
907  if (!cached_desc) {
908  return;
909  }
910  /* If we have a decrypted/decoded descriptor, attempt to close its
911  * introduction circuit(s). We shouldn't have circuit(s) without a
912  * descriptor else it will lead to a failure. */
913  if (entry_has_decrypted_descriptor(cached_desc)) {
914  hs_client_close_intro_circuits_from_desc(cached_desc->desc);
915  }
916  /* Remove and free. */
917  remove_v3_desc_as_client(cached_desc);
918  cache_client_desc_free(cached_desc);
919 
920  /* Logging. */
921  {
922  char key_b64[BASE64_DIGEST256_LEN + 1];
923  digest256_to_base64(key_b64, (const char *) key);
924  log_info(LD_REND, "Onion service v3 descriptor '%s' removed "
925  "from client cache",
926  safe_str_client(key_b64));
927  }
928 }
929 
930 /** Clean all client caches using the current time now. */
931 void
933 {
934  /* Start with v2 cache cleaning. */
935  rend_cache_clean(now, REND_CACHE_TYPE_CLIENT);
936  /* Now, clean the v3 cache. Set the cutoff to 0 telling the cleanup function
937  * to compute the cutoff by itself using the lifetime value. */
939 }
940 
941 /** Purge the client descriptor cache. */
942 void
944 {
945  DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_client, key,
946  hs_cache_client_descriptor_t *, entry) {
947  size_t entry_size = cache_get_client_entry_size(entry);
948  MAP_DEL_CURRENT(key);
949  cache_client_desc_free(entry);
950  /* Update our OOM. We didn't use the remove() function because we are in
951  * a loop so we have to explicitly decrement. */
953  } DIGEST256MAP_FOREACH_END;
954 
955  log_info(LD_REND, "Hidden service client descriptor cache purged.");
956 }
957 
958 /** For a given service identity public key and an introduction authentication
959  * key, note the given failure in the client intro state cache. */
960 void
962  const ed25519_public_key_t *auth_key,
963  rend_intro_point_failure_t failure)
964 {
965  int found;
966  hs_cache_intro_state_t *entry;
967 
968  tor_assert(service_pk);
969  tor_assert(auth_key);
970 
971  found = cache_client_intro_state_lookup(service_pk, auth_key, &entry);
972  if (!found) {
973  /* Create a new entry and add it to the cache. */
974  cache_client_intro_state_add(service_pk, auth_key, &entry);
975  }
976  /* Note down the entry. */
977  cache_client_intro_state_note(entry, failure);
978 }
979 
980 /** For a given service identity public key and an introduction authentication
981  * key, return true iff it is present in the failure cache. */
984  const ed25519_public_key_t *auth_key)
985 {
986  hs_cache_intro_state_t *state = NULL;
987  cache_client_intro_state_lookup(service_pk, auth_key, &state);
988  return state;
989 }
990 
991 /** Cleanup the client introduction state cache. */
992 void
994 {
995  time_t cutoff = now - HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE;
996 
997  DIGEST256MAP_FOREACH_MODIFY(hs_cache_client_intro_state, key,
999  /* Cleanup intro points failure. */
1000  cache_client_intro_state_clean(cutoff, cache);
1001 
1002  /* Is this cache empty for this service key? If yes, remove it from the
1003  * cache. Else keep it. */
1004  if (cache_client_intro_state_is_empty(cache)) {
1005  cache_client_intro_state_free(cache);
1006  MAP_DEL_CURRENT(key);
1007  }
1008  } DIGEST256MAP_FOREACH_END;
1009 }
1010 
1011 /** Purge the client introduction state cache. */
1012 void
1014 {
1015  DIGEST256MAP_FOREACH_MODIFY(hs_cache_client_intro_state, key,
1016  hs_cache_client_intro_state_t *, cache) {
1017  MAP_DEL_CURRENT(key);
1018  cache_client_intro_state_free(cache);
1019  } DIGEST256MAP_FOREACH_END;
1020 
1021  log_info(LD_REND, "Hidden service client introduction point state "
1022  "cache purged.");
1023 }
1024 
1025 /* This is called when new client authorization was added to the global state.
1026  * It attempts to decode the descriptor of the given service identity key.
1027  *
1028  * Return true if decoding was successful else false. */
1029 bool
1030 hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk)
1031 {
1032  bool ret = false;
1033  hs_cache_client_descriptor_t *cached_desc = NULL;
1034 
1035  tor_assert(service_pk);
1036 
1037  if (!hs_cache_v3_client) {
1038  return false;
1039  }
1040 
1041  cached_desc = lookup_v3_desc_as_client(service_pk->pubkey);
1042  if (cached_desc == NULL || entry_has_decrypted_descriptor(cached_desc)) {
1043  /* No entry for that service or the descriptor is already decoded. */
1044  goto end;
1045  }
1046 
1047  /* Attempt a decode. If we are successful, inform the caller. */
1048  if (hs_client_decode_descriptor(cached_desc->encoded_desc, service_pk,
1049  &cached_desc->desc) == HS_DESC_DECODE_OK) {
1050  ret = true;
1051  }
1052 
1053  end:
1054  return ret;
1055 }
1056 
1057 /**************** Generics *********************************/
1058 
1059 /** Do a round of OOM cleanup on all directory caches. Return the amount of
1060  * removed bytes. It is possible that the returned value is lower than
1061  * min_remove_bytes if the caches get emptied out so the caller should be
1062  * aware of this. */
1063 size_t
1064 hs_cache_handle_oom(time_t now, size_t min_remove_bytes)
1065 {
1066  time_t k;
1067  size_t bytes_removed = 0;
1068 
1069  /* Our OOM handler called with 0 bytes to remove is a code flow error. */
1070  tor_assert(min_remove_bytes != 0);
1071 
1072  /* The algorithm is as follow. K is the oldest expected descriptor age.
1073  *
1074  * 1) Deallocate all entries from v2 cache that are older than K hours.
1075  * 1.1) If the amount of remove bytes has been reached, stop.
1076  * 2) Deallocate all entries from v3 cache that are older than K hours
1077  * 2.1) If the amount of remove bytes has been reached, stop.
1078  * 3) Set K = K - RendPostPeriod and repeat process until K is < 0.
1079  *
1080  * This ends up being O(Kn).
1081  */
1082 
1083  /* Set K to the oldest expected age in seconds which is the maximum
1084  * lifetime of a cache entry. We'll use the v2 lifetime because it's much
1085  * bigger than the v3 thus leading to cleaning older descriptors. */
1086  k = rend_cache_max_entry_lifetime();
1087 
1088  do {
1089  time_t cutoff;
1090 
1091  /* If K becomes negative, it means we've empty the caches so stop and
1092  * return what we were able to cleanup. */
1093  if (k < 0) {
1094  break;
1095  }
1096  /* Compute a cutoff value with K and the current time. */
1097  cutoff = now - k;
1098 
1099  /* Start by cleaning the v2 cache with that cutoff. */
1100  bytes_removed += rend_cache_clean_v2_descs_as_dir(cutoff);
1101 
1102  if (bytes_removed < min_remove_bytes) {
1103  /* We haven't remove enough bytes so clean v3 cache. */
1104  bytes_removed += cache_clean_v3_as_dir(now, cutoff);
1105  /* Decrement K by a post period to shorten the cutoff. */
1106  k -= get_options()->RendPostPeriod;
1107  }
1108  } while (bytes_removed < min_remove_bytes);
1109 
1110  return bytes_removed;
1111 }
1112 
1113 /** Return the maximum size of a v3 HS descriptor. */
1114 unsigned int
1116 {
1117  return (unsigned) networkstatus_get_param(NULL,
1118  "HSV3MaxDescriptorSize",
1119  HS_DESC_MAX_LEN, 1, INT32_MAX);
1120 }
1121 
1122 /** Initialize the hidden service cache subsystem. */
1123 void
1125 {
1126  /* Calling this twice is very wrong code flow. */
1128  hs_cache_v3_dir = digest256map_new();
1129 
1131  hs_cache_v3_client = digest256map_new();
1132 
1134  hs_cache_client_intro_state = digest256map_new();
1135 }
1136 
1137 /** Cleanup the hidden service cache subsystem. */
1138 void
1140 {
1141  digest256map_free(hs_cache_v3_dir, cache_dir_desc_free_void);
1142  hs_cache_v3_dir = NULL;
1143 
1144  digest256map_free(hs_cache_v3_client, cache_client_desc_free_void);
1145  hs_cache_v3_client = NULL;
1146 
1147  digest256map_free(hs_cache_client_intro_state,
1150 }
entry_has_decrypted_descriptor
static bool entry_has_decrypted_descriptor(const hs_cache_client_descriptor_t *entry)
Definition: hs_cache.c:40
hs_cache_dir_descriptor_t::key
const uint8_t * key
Definition: hs_cache.h:52
hs_cache_init
void hs_cache_init(void)
Definition: hs_cache.c:1124
tor_free
#define tor_free(p)
Definition: malloc.h:52
cache_get_client_entry_size
static size_t cache_get_client_entry_size(const hs_cache_client_descriptor_t *entry)
Definition: hs_cache.c:361
hs_cache_store_as_client
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:864
hs_cache_client_intro_state_note
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:961
hs_desc_decode_status_t
hs_desc_decode_status_t
Definition: hs_descriptor.h:74
hs_ident.h
Header file containing circuit and connection identifier data for the whole HS subsystem.
cache_client_intro_state_is_empty
static int cache_client_intro_state_is_empty(const hs_cache_client_intro_state_t *cache)
Definition: hs_cache.c:672
memwipe
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
approx_time
time_t approx_time(void)
Definition: approx_time.c:32
BASE64_DIGEST256_LEN
#define BASE64_DIGEST256_LEN
Definition: crypto_digest.h:29
cache_client_desc_new
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:431
hs_cache_v3_client
static digest256map_t * hs_cache_v3_client
Definition: hs_cache.c:352
tor_assert
#define tor_assert(expr)
Definition: util_bug.h:102
hs_cache_intro_state_t
Definition: hs_cache.h:26
cache_client_intro_state_free_
static void cache_client_intro_state_free_(hs_cache_client_intro_state_t *cache)
Definition: hs_cache.c:546
hs_cache_get_max_descriptor_size
unsigned int hs_cache_get_max_descriptor_size(void)
Definition: hs_cache.c:1115
LD_GENERAL
#define LD_GENERAL
Definition: log.h:62
or_options_t::RendPostPeriod
int RendPostPeriod
Definition: or_options_st.h:392
rend_cache_clean
void rend_cache_clean(time_t now, rend_cache_type_t cache_type)
Definition: rendcache.c:289
cache_store_v3_as_dir
static int cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc)
Definition: hs_cache.c:141
networkstatus_get_live_consensus
networkstatus_t * networkstatus_get_live_consensus(time_t now)
Definition: networkstatus.c:1416
hs_cache_client_intro_state
static digest256map_t * hs_cache_client_intro_state
Definition: hs_cache.c:357
hs_desc_plaintext_data_t::version
uint32_t version
Definition: hs_descriptor.h:196
ed25519_pubkey_copy
void ed25519_pubkey_copy(ed25519_public_key_t *dest, const ed25519_public_key_t *src)
Definition: crypto_ed25519.c:654
cache_client_desc_free_
static void cache_client_desc_free_(hs_cache_client_descriptor_t *desc)
Definition: hs_cache.c:484
cache_lookup_v3_as_dir
static int cache_lookup_v3_as_dir(const char *query, const char **desc_out)
Definition: hs_cache.c:195
hs_cache_client_intro_state_clean
void hs_cache_client_intro_state_clean(time_t now)
Definition: hs_cache.c:993
hs_desc_obj_size
size_t hs_desc_obj_size(const hs_descriptor_t *data)
Definition: hs_descriptor.c:2824
hs_desc_plaintext_obj_size
size_t hs_desc_plaintext_obj_size(const hs_desc_plaintext_data_t *data)
Definition: hs_descriptor.c:2794
cache_intro_state_free_
static void cache_intro_state_free_(hs_cache_intro_state_t *state)
Definition: hs_cache.c:518
cache_dir_desc_new
static hs_cache_dir_descriptor_t * cache_dir_desc_new(const char *desc)
Definition: hs_cache.c:102
hs_desc_is_supported_version
static int hs_desc_is_supported_version(uint32_t version)
Definition: hs_descriptor.h:247
networkstatus.h
Header file for networkstatus.c.
digest256_to_base64
void digest256_to_base64(char *d64, const char *digest)
Definition: crypto_format.c:304
hs_cache_dir_descriptor_t::plaintext_data
hs_desc_plaintext_data_t * plaintext_data
Definition: hs_cache.h:59
hs_client.h
Header file containing client data for the HS subsystem.
hs_desc_decode_plaintext
hs_desc_decode_status_t hs_desc_decode_plaintext(const char *encoded, hs_desc_plaintext_data_t *plaintext)
Definition: hs_descriptor.c:2494
crypto_util.h
Common functions for cryptographic routines.
hs_cache.h
Header file for hs_cache.c.
cache_intro_state_new
static hs_cache_intro_state_t * cache_intro_state_new(void)
Definition: hs_cache.c:506
hs_cache_purge_as_client
void hs_cache_purge_as_client(void)
Definition: hs_cache.c:943
store_v3_desc_as_client
static void store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
Definition: hs_cache.c:394
hs_desc_plaintext_data_t::revision_counter
uint64_t revision_counter
Definition: hs_descriptor.h:216
crypto_format.h
Header for crypto_format.c.
cache_client_intro_state_lookup
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:567
cache_store_as_client
static int cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
Definition: hs_cache.c:681
tor_assert_nonfatal_unreached
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:176
hs_cache_client_intro_state_purge
void hs_cache_client_intro_state_purge(void)
Definition: hs_cache.c:1013
hs_cache_client_intro_state_t::intro_points
digest256map_t * intro_points
Definition: hs_cache.h:43
ed25519_public_key_t
Definition: crypto_ed25519.h:23
hs_cache_lookup_as_client
const hs_descriptor_t * hs_cache_lookup_as_client(const ed25519_public_key_t *key)
Definition: hs_cache.c:833
LD_REND
#define LD_REND
Definition: log.h:84
escaped
const char * escaped(const char *s)
Definition: escape.c:126
hs_cache_remove_as_client
void hs_cache_remove_as_client(const ed25519_public_key_t *key)
Definition: hs_cache.c:900
hs_desc_plaintext_data_t::blinded_pubkey
ed25519_public_key_t blinded_pubkey
Definition: hs_descriptor.h:211
remove_v3_desc_as_client
static void remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
Definition: hs_cache.c:384
hs_cache_lookup_as_dir
int hs_cache_lookup_as_dir(uint32_t version, const char *query, const char **desc_out)
Definition: hs_cache.c:315
cache_client_desc_free_void
static void cache_client_desc_free_void(void *ptr)
Definition: hs_cache.c:498
hs_cache_handle_oom
size_t hs_cache_handle_oom(time_t now, size_t min_remove_bytes)
Definition: hs_cache.c:1064
hs_desc_plaintext_data_t
Definition: hs_descriptor.h:193
hs_cache_dir_descriptor_t
Definition: hs_cache.h:48
hs_descriptor_t
Definition: hs_descriptor.h:226
hs_client_close_intro_circuits_from_desc
void hs_client_close_intro_circuits_from_desc(const hs_descriptor_t *desc)
Definition: hs_client.c:2554
cache_client_intro_state_note
static void cache_client_intro_state_note(hs_cache_intro_state_t *state, rend_intro_point_failure_t failure)
Definition: hs_cache.c:599
cache_clean_v3_as_dir
STATIC size_t cache_clean_v3_as_dir(time_t now, time_t global_cutoff)
Definition: hs_cache.c:229
hs_cache_intro_state_t::timed_out
unsigned int timed_out
Definition: hs_cache.h:34
hs_cache_intro_state_t::error
unsigned int error
Definition: hs_cache.h:31
cache_client_intro_state_free_void
static void cache_client_intro_state_free_void(void *entry)
Definition: hs_cache.c:557
cache_intro_state_free_void
static void cache_intro_state_free_void(void *state)
Definition: hs_cache.c:525
rendcache.h
Header file for rendcache.c.
get_options
const or_options_t * get_options(void)
Definition: config.c:932
HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE
#define HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE
Definition: hs_cache.h:23
lookup_v3_desc_as_dir
static hs_cache_dir_descriptor_t * lookup_v3_desc_as_dir(const uint8_t *key)
Definition: hs_cache.c:69
hs_cache_store_as_dir
int hs_cache_store_as_dir(const char *desc)
Definition: hs_cache.c:278
HS_DESC_MAX_LEN
#define HS_DESC_MAX_LEN
Definition: hs_descriptor.h:49
remove_v3_desc_as_dir
static void remove_v3_desc_as_dir(const hs_cache_dir_descriptor_t *desc)
Definition: hs_cache.c:53
hs_common.h
Header file containing common data for the whole HS subsystem.
rep_hist_hsdir_stored_maybe_new_v3_onion
void rep_hist_hsdir_stored_maybe_new_v3_onion(const uint8_t *blinded_key)
Definition: rephist.c:1886
lookup_v3_desc_as_client
STATIC hs_cache_client_descriptor_t * lookup_v3_desc_as_client(const uint8_t *key)
Definition: hs_cache.c:404
networkstatus_t::valid_after
time_t valid_after
Definition: networkstatus_st.h:33
hs_client_decode_descriptor
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:1974
hs_cache_dir_descriptor_t::encoded_desc
char * encoded_desc
Definition: hs_cache.h:63
rend_cache_clean_v2_descs_as_dir
size_t rend_cache_clean_v2_descs_as_dir(time_t cutoff)
Definition: rendcache.c:487
hs_cache_client_intro_state_find
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:983
HS_VERSION_THREE
#define HS_VERSION_THREE
Definition: hs_common.h:26
MAP_DEL_CURRENT
#define MAP_DEL_CURRENT(keyvar)
Definition: map.h:140
rend_cache_increment_allocation
void rend_cache_increment_allocation(size_t n)
Definition: rendcache.c:113
cache_clean_v3_as_client
static size_t cache_clean_v3_as_client(time_t now)
Definition: hs_cache.c:763
hs_cache_intro_state_t::unreachable_count
uint32_t unreachable_count
Definition: hs_cache.h:37
ed25519_public_from_base64
int ed25519_public_from_base64(ed25519_public_key_t *pkey, const char *input)
Definition: crypto_format.c:212
rend_cache_decrement_allocation
void rend_cache_decrement_allocation(size_t n)
Definition: rendcache.c:96
config.h
Header file for config.c.
hs_cache_client_intro_state_t
Definition: hs_cache.h:40
hs_cache_clean_as_client
void hs_cache_clean_as_client(time_t now)
Definition: hs_cache.c:932
cache_dir_desc_free_
static void cache_dir_desc_free_(hs_cache_dir_descriptor_t *desc)
Definition: hs_cache.c:80
cache_client_intro_state_new
static hs_cache_client_intro_state_t * cache_client_intro_state_new(void)
Definition: hs_cache.c:533
store_v3_desc_as_dir
static void store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc)
Definition: hs_cache.c:61
STATIC
#define STATIC
Definition: testsupport.h:32
LD_DIR
#define LD_DIR
Definition: log.h:88
networkstatus_get_param
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)
Definition: networkstatus.c:2500
networkstatus_st.h
Networkstatus consensus/vote structure.
networkstatus_t
Definition: networkstatus_st.h:26
hs_cache_free_all
void hs_cache_free_all(void)
Definition: hs_cache.c:1139
hs_cache_clean_as_dir
void hs_cache_clean_as_dir(time_t now)
Definition: hs_cache.c:336
cache_get_dir_entry_size
static size_t cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry)
Definition: hs_cache.c:130
hs_descriptor.h
Header file for hs_descriptor.c.
hs_get_start_time_of_next_time_period
time_t hs_get_start_time_of_next_time_period(time_t now)
Definition: hs_common.c:323
cache_client_intro_state_add
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:624
hs_cache_v3_dir
static digest256map_t * hs_cache_v3_dir
Definition: hs_cache.c:49
hs_cache_dir_descriptor_t::created_ts
time_t created_ts
Definition: hs_cache.h:55
rephist.h
Header file for rephist.c.
cache_dir_desc_free_void
static void cache_dir_desc_free_void(void *ptr)
Definition: hs_cache.c:93
hs_cache_lookup_encoded_as_client
const char * hs_cache_lookup_encoded_as_client(const ed25519_public_key_t *key)
Definition: hs_cache.c:813
cache_client_intro_state_clean
static void cache_client_intro_state_clean(time_t cutoff, hs_cache_client_intro_state_t *cache)
Definition: hs_cache.c:656
cached_client_descriptor_has_expired
static int cached_client_descriptor_has_expired(time_t now, const hs_cache_client_descriptor_t *cached_desc)
Definition: hs_cache.c:740
or.h
Master header file for Tor-specific functionality.
hs_cache_intro_state_t::created_ts
time_t created_ts
Definition: hs_cache.h:28