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