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