hs_cache.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. /* Copyright (c) 2016-2017, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file hs_cache.c
  5. * \brief Handle hidden service descriptor caches.
  6. **/
  7. /* For unit tests.*/
  8. #define HS_CACHE_PRIVATE
  9. #include "or.h"
  10. #include "config.h"
  11. #include "hs_ident.h"
  12. #include "hs_common.h"
  13. #include "hs_client.h"
  14. #include "hs_descriptor.h"
  15. #include "networkstatus.h"
  16. #include "rendcache.h"
  17. #include "hs_cache.h"
  18. /********************** Directory HS cache ******************/
  19. /* Directory descriptor cache. Map indexed by blinded key. */
  20. static digest256map_t *hs_cache_v3_dir;
  21. /* Remove a given descriptor from our cache. */
  22. static void
  23. remove_v3_desc_as_dir(const hs_cache_dir_descriptor_t *desc)
  24. {
  25. tor_assert(desc);
  26. digest256map_remove(hs_cache_v3_dir, desc->key);
  27. }
  28. /* Store a given descriptor in our cache. */
  29. static void
  30. store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc)
  31. {
  32. tor_assert(desc);
  33. digest256map_set(hs_cache_v3_dir, desc->key, desc);
  34. }
  35. /* Query our cache and return the entry or NULL if not found. */
  36. static hs_cache_dir_descriptor_t *
  37. lookup_v3_desc_as_dir(const uint8_t *key)
  38. {
  39. tor_assert(key);
  40. return digest256map_get(hs_cache_v3_dir, key);
  41. }
  42. /* Free a directory descriptor object. */
  43. static void
  44. cache_dir_desc_free(hs_cache_dir_descriptor_t *desc)
  45. {
  46. if (desc == NULL) {
  47. return;
  48. }
  49. hs_desc_plaintext_data_free(desc->plaintext_data);
  50. tor_free(desc->encoded_desc);
  51. tor_free(desc);
  52. }
  53. /* Helper function: Use by the free all function using the digest256map
  54. * interface to cache entries. */
  55. static void
  56. cache_dir_desc_free_(void *ptr)
  57. {
  58. hs_cache_dir_descriptor_t *desc = ptr;
  59. cache_dir_desc_free(desc);
  60. }
  61. /* Create a new directory cache descriptor object from a encoded descriptor.
  62. * On success, return the heap-allocated cache object, otherwise return NULL if
  63. * we can't decode the descriptor. */
  64. static hs_cache_dir_descriptor_t *
  65. cache_dir_desc_new(const char *desc)
  66. {
  67. hs_cache_dir_descriptor_t *dir_desc;
  68. tor_assert(desc);
  69. dir_desc = tor_malloc_zero(sizeof(hs_cache_dir_descriptor_t));
  70. dir_desc->plaintext_data =
  71. tor_malloc_zero(sizeof(hs_desc_plaintext_data_t));
  72. dir_desc->encoded_desc = tor_strdup(desc);
  73. if (hs_desc_decode_plaintext(desc, dir_desc->plaintext_data) < 0) {
  74. log_debug(LD_DIR, "Unable to decode descriptor. Rejecting.");
  75. goto err;
  76. }
  77. /* The blinded pubkey is the indexed key. */
  78. dir_desc->key = dir_desc->plaintext_data->blinded_pubkey.pubkey;
  79. dir_desc->created_ts = time(NULL);
  80. return dir_desc;
  81. err:
  82. cache_dir_desc_free(dir_desc);
  83. return NULL;
  84. }
  85. /* Return the size of a cache entry in bytes. */
  86. static size_t
  87. cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry)
  88. {
  89. return (sizeof(*entry) + hs_desc_plaintext_obj_size(entry->plaintext_data)
  90. + strlen(entry->encoded_desc));
  91. }
  92. /* Try to store a valid version 3 descriptor in the directory cache. Return 0
  93. * on success else a negative value is returned indicating that we have a
  94. * newer version in our cache. On error, caller is responsible to free the
  95. * given descriptor desc. */
  96. static int
  97. cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc)
  98. {
  99. hs_cache_dir_descriptor_t *cache_entry;
  100. tor_assert(desc);
  101. /* Verify if we have an entry in the cache for that key and if yes, check
  102. * if we should replace it? */
  103. cache_entry = lookup_v3_desc_as_dir(desc->key);
  104. if (cache_entry != NULL) {
  105. /* Only replace descriptor if revision-counter is greater than the one
  106. * in our cache */
  107. if (cache_entry->plaintext_data->revision_counter >=
  108. desc->plaintext_data->revision_counter) {
  109. log_info(LD_REND, "Descriptor revision counter in our cache is "
  110. "greater or equal than the one we received (%d/%d). "
  111. "Rejecting!",
  112. (int)cache_entry->plaintext_data->revision_counter,
  113. (int)desc->plaintext_data->revision_counter);
  114. goto err;
  115. }
  116. /* We now know that the descriptor we just received is a new one so
  117. * remove the entry we currently have from our cache so we can then
  118. * store the new one. */
  119. remove_v3_desc_as_dir(cache_entry);
  120. rend_cache_decrement_allocation(cache_get_dir_entry_size(cache_entry));
  121. cache_dir_desc_free(cache_entry);
  122. }
  123. /* Store the descriptor we just got. We are sure here that either we
  124. * don't have the entry or we have a newer descriptor and the old one
  125. * has been removed from the cache. */
  126. store_v3_desc_as_dir(desc);
  127. /* Update our total cache size with this entry for the OOM. This uses the
  128. * old HS protocol cache subsystem for which we are tied with. */
  129. rend_cache_increment_allocation(cache_get_dir_entry_size(desc));
  130. /* XXX: Update HS statistics. We should have specific stats for v3. */
  131. return 0;
  132. err:
  133. return -1;
  134. }
  135. /* Using the query which is the base64 encoded blinded key of a version 3
  136. * descriptor, lookup in our directory cache the entry. If found, 1 is
  137. * returned and desc_out is populated with a newly allocated string being the
  138. * encoded descriptor. If not found, 0 is returned and desc_out is untouched.
  139. * On error, a negative value is returned and desc_out is untouched. */
  140. static int
  141. cache_lookup_v3_as_dir(const char *query, const char **desc_out)
  142. {
  143. int found = 0;
  144. ed25519_public_key_t blinded_key;
  145. const hs_cache_dir_descriptor_t *entry;
  146. tor_assert(query);
  147. /* Decode blinded key using the given query value. */
  148. if (ed25519_public_from_base64(&blinded_key, query) < 0) {
  149. log_info(LD_REND, "Unable to decode the v3 HSDir query %s.",
  150. safe_str_client(query));
  151. goto err;
  152. }
  153. entry = lookup_v3_desc_as_dir(blinded_key.pubkey);
  154. if (entry != NULL) {
  155. found = 1;
  156. if (desc_out) {
  157. *desc_out = entry->encoded_desc;
  158. }
  159. }
  160. return found;
  161. err:
  162. return -1;
  163. }
  164. /* Clean the v3 cache by removing any entry that has expired using the
  165. * <b>global_cutoff</b> value. If <b>global_cutoff</b> is 0, the cleaning
  166. * process will use the lifetime found in the plaintext data section. Return
  167. * the number of bytes cleaned. */
  168. STATIC size_t
  169. cache_clean_v3_as_dir(time_t now, time_t global_cutoff)
  170. {
  171. size_t bytes_removed = 0;
  172. /* Code flow error if this ever happens. */
  173. tor_assert(global_cutoff >= 0);
  174. if (!hs_cache_v3_dir) { /* No cache to clean. Just return. */
  175. return 0;
  176. }
  177. DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_dir, key,
  178. hs_cache_dir_descriptor_t *, entry) {
  179. size_t entry_size;
  180. time_t cutoff = global_cutoff;
  181. if (!cutoff) {
  182. /* Cutoff is the lifetime of the entry found in the descriptor. */
  183. cutoff = now - entry->plaintext_data->lifetime_sec;
  184. }
  185. /* If the entry has been created _after_ the cutoff, not expired so
  186. * continue to the next entry in our v3 cache. */
  187. if (entry->created_ts > cutoff) {
  188. continue;
  189. }
  190. /* Here, our entry has expired, remove and free. */
  191. MAP_DEL_CURRENT(key);
  192. entry_size = cache_get_dir_entry_size(entry);
  193. bytes_removed += entry_size;
  194. /* Entry is not in the cache anymore, destroy it. */
  195. cache_dir_desc_free(entry);
  196. /* Update our cache entry allocation size for the OOM. */
  197. rend_cache_decrement_allocation(entry_size);
  198. /* Logging. */
  199. {
  200. char key_b64[BASE64_DIGEST256_LEN + 1];
  201. digest256_to_base64(key_b64, (const char *) key);
  202. log_info(LD_REND, "Removing v3 descriptor '%s' from HSDir cache",
  203. safe_str_client(key_b64));
  204. }
  205. } DIGEST256MAP_FOREACH_END;
  206. return bytes_removed;
  207. }
  208. /* Given an encoded descriptor, store it in the directory cache depending on
  209. * which version it is. Return a negative value on error. On success, 0 is
  210. * returned. */
  211. int
  212. hs_cache_store_as_dir(const char *desc)
  213. {
  214. hs_cache_dir_descriptor_t *dir_desc = NULL;
  215. tor_assert(desc);
  216. /* Create a new cache object. This can fail if the descriptor plaintext data
  217. * is unparseable which in this case a log message will be triggered. */
  218. dir_desc = cache_dir_desc_new(desc);
  219. if (dir_desc == NULL) {
  220. goto err;
  221. }
  222. /* Call the right function against the descriptor version. At this point,
  223. * we are sure that the descriptor's version is supported else the
  224. * decoding would have failed. */
  225. switch (dir_desc->plaintext_data->version) {
  226. case HS_VERSION_THREE:
  227. default:
  228. if (cache_store_v3_as_dir(dir_desc) < 0) {
  229. goto err;
  230. }
  231. break;
  232. }
  233. return 0;
  234. err:
  235. cache_dir_desc_free(dir_desc);
  236. return -1;
  237. }
  238. /* Using the query, lookup in our directory cache the entry. If found, 1 is
  239. * returned and desc_out is populated with a newly allocated string being
  240. * the encoded descriptor. If not found, 0 is returned and desc_out is
  241. * untouched. On error, a negative value is returned and desc_out is
  242. * untouched. */
  243. int
  244. hs_cache_lookup_as_dir(uint32_t version, const char *query,
  245. const char **desc_out)
  246. {
  247. int found;
  248. tor_assert(query);
  249. /* This should never be called with an unsupported version. */
  250. tor_assert(hs_desc_is_supported_version(version));
  251. switch (version) {
  252. case HS_VERSION_THREE:
  253. default:
  254. found = cache_lookup_v3_as_dir(query, desc_out);
  255. break;
  256. }
  257. return found;
  258. }
  259. /* Clean all directory caches using the current time now. */
  260. void
  261. hs_cache_clean_as_dir(time_t now)
  262. {
  263. time_t cutoff;
  264. /* Start with v2 cache cleaning. */
  265. cutoff = now - rend_cache_max_entry_lifetime();
  266. rend_cache_clean_v2_descs_as_dir(cutoff);
  267. /* Now, clean the v3 cache. Set the cutoff to 0 telling the cleanup function
  268. * to compute the cutoff by itself using the lifetime value. */
  269. cache_clean_v3_as_dir(now, 0);
  270. }
  271. /********************** Client-side HS cache ******************/
  272. /* Client-side HS descriptor cache. Map indexed by service identity key. */
  273. static digest256map_t *hs_cache_v3_client;
  274. /* Client-side introduction point state cache. Map indexed by service public
  275. * identity key (onion address). It contains hs_cache_client_intro_state_t
  276. * objects all related to a specific service. */
  277. static digest256map_t *hs_cache_client_intro_state;
  278. /* Return the size of a client cache entry in bytes. */
  279. static size_t
  280. cache_get_client_entry_size(const hs_cache_client_descriptor_t *entry)
  281. {
  282. return sizeof(*entry) +
  283. strlen(entry->encoded_desc) + hs_desc_obj_size(entry->desc);
  284. }
  285. /* Remove a given descriptor from our cache. */
  286. static void
  287. remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
  288. {
  289. tor_assert(desc);
  290. digest256map_remove(hs_cache_v3_client, desc->key.pubkey);
  291. /* Update cache size with this entry for the OOM handler. */
  292. rend_cache_decrement_allocation(cache_get_client_entry_size(desc));
  293. }
  294. /* Store a given descriptor in our cache. */
  295. static void
  296. store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
  297. {
  298. tor_assert(desc);
  299. digest256map_set(hs_cache_v3_client, desc->key.pubkey, desc);
  300. /* Update cache size with this entry for the OOM handler. */
  301. rend_cache_increment_allocation(cache_get_client_entry_size(desc));
  302. }
  303. /* Query our cache and return the entry or NULL if not found. */
  304. STATIC hs_cache_client_descriptor_t *
  305. lookup_v3_desc_as_client(const uint8_t *key)
  306. {
  307. tor_assert(key);
  308. return digest256map_get(hs_cache_v3_client, key);
  309. }
  310. /* Parse the encoded descriptor in <b>desc_str</b> using
  311. * <b>service_identity_pk<b> to decrypt it first.
  312. *
  313. * If everything goes well, allocate and return a new
  314. * hs_cache_client_descriptor_t object. In case of error, return NULL. */
  315. static hs_cache_client_descriptor_t *
  316. cache_client_desc_new(const char *desc_str,
  317. const ed25519_public_key_t *service_identity_pk)
  318. {
  319. hs_descriptor_t *desc = NULL;
  320. hs_cache_client_descriptor_t *client_desc = NULL;
  321. tor_assert(desc_str);
  322. tor_assert(service_identity_pk);
  323. /* Decode the descriptor we just fetched. */
  324. if (hs_client_decode_descriptor(desc_str, service_identity_pk, &desc) < 0) {
  325. goto end;
  326. }
  327. tor_assert(desc);
  328. /* All is good: make a cache object for this descriptor */
  329. client_desc = tor_malloc_zero(sizeof(hs_cache_client_descriptor_t));
  330. ed25519_pubkey_copy(&client_desc->key, service_identity_pk);
  331. client_desc->created_ts = approx_time();
  332. client_desc->desc = desc;
  333. client_desc->encoded_desc = tor_strdup(desc_str);
  334. end:
  335. return client_desc;
  336. }
  337. /** Free memory allocated by <b>desc</b>. */
  338. static void
  339. cache_client_desc_free(hs_cache_client_descriptor_t *desc)
  340. {
  341. if (desc == NULL) {
  342. return;
  343. }
  344. hs_descriptor_free(desc->desc);
  345. memwipe(&desc->key, 0, sizeof(desc->key));
  346. memwipe(desc->encoded_desc, 0, strlen(desc->encoded_desc));
  347. tor_free(desc->encoded_desc);
  348. tor_free(desc);
  349. }
  350. /** Helper function: Use by the free all function to clear the client cache */
  351. static void
  352. cache_client_desc_free_(void *ptr)
  353. {
  354. hs_cache_client_descriptor_t *desc = ptr;
  355. cache_client_desc_free(desc);
  356. }
  357. /* Return a newly allocated and initialized hs_cache_intro_state_t object. */
  358. static hs_cache_intro_state_t *
  359. cache_intro_state_new(void)
  360. {
  361. hs_cache_intro_state_t *state = tor_malloc_zero(sizeof(*state));
  362. state->created_ts = approx_time();
  363. return state;
  364. }
  365. /* Free an hs_cache_intro_state_t object. */
  366. static void
  367. cache_intro_state_free(hs_cache_intro_state_t *state)
  368. {
  369. tor_free(state);
  370. }
  371. /* Helper function: use by the free all function. */
  372. static void
  373. cache_intro_state_free_(void *state)
  374. {
  375. cache_intro_state_free(state);
  376. }
  377. /* Return a newly allocated and initialized hs_cache_client_intro_state_t
  378. * object. */
  379. static hs_cache_client_intro_state_t *
  380. cache_client_intro_state_new(void)
  381. {
  382. hs_cache_client_intro_state_t *cache = tor_malloc_zero(sizeof(*cache));
  383. cache->intro_points = digest256map_new();
  384. return cache;
  385. }
  386. /* Free a cache client intro state object. */
  387. static void
  388. cache_client_intro_state_free(hs_cache_client_intro_state_t *cache)
  389. {
  390. if (cache == NULL) {
  391. return;
  392. }
  393. digest256map_free(cache->intro_points, cache_intro_state_free_);
  394. tor_free(cache);
  395. }
  396. /* Helper function: use by the free all function. */
  397. static void
  398. cache_client_intro_state_free_(void *entry)
  399. {
  400. cache_client_intro_state_free(entry);
  401. }
  402. /* For the given service identity key service_pk and an introduction
  403. * authentication key auth_key, lookup the intro state object. Return 1 if
  404. * found and put it in entry if not NULL. Return 0 if not found and entry is
  405. * untouched. */
  406. static int
  407. cache_client_intro_state_lookup(const ed25519_public_key_t *service_pk,
  408. const ed25519_public_key_t *auth_key,
  409. hs_cache_intro_state_t **entry)
  410. {
  411. hs_cache_intro_state_t *state;
  412. hs_cache_client_intro_state_t *cache;
  413. tor_assert(service_pk);
  414. tor_assert(auth_key);
  415. /* Lookup the intro state cache for this service key. */
  416. cache = digest256map_get(hs_cache_client_intro_state, service_pk->pubkey);
  417. if (cache == NULL) {
  418. goto not_found;
  419. }
  420. /* From the cache we just found for the service, lookup in the introduction
  421. * points map for the given authentication key. */
  422. state = digest256map_get(cache->intro_points, auth_key->pubkey);
  423. if (state == NULL) {
  424. goto not_found;
  425. }
  426. if (entry) {
  427. *entry = state;
  428. }
  429. return 1;
  430. not_found:
  431. return 0;
  432. }
  433. /* Note the given failure in state. */
  434. static void
  435. cache_client_intro_state_note(hs_cache_intro_state_t *state,
  436. rend_intro_point_failure_t failure)
  437. {
  438. tor_assert(state);
  439. switch (failure) {
  440. case INTRO_POINT_FAILURE_GENERIC:
  441. state->error = 1;
  442. break;
  443. case INTRO_POINT_FAILURE_TIMEOUT:
  444. state->timed_out = 1;
  445. break;
  446. case INTRO_POINT_FAILURE_UNREACHABLE:
  447. state->unreachable_count++;
  448. break;
  449. default:
  450. tor_assert_nonfatal_unreached();
  451. return;
  452. }
  453. }
  454. /* For the given service identity key service_pk and an introduction
  455. * authentication key auth_key, add an entry in the client intro state cache
  456. * If no entry exists for the service, it will create one. If state is non
  457. * NULL, it will point to the new intro state entry. */
  458. static void
  459. cache_client_intro_state_add(const ed25519_public_key_t *service_pk,
  460. const ed25519_public_key_t *auth_key,
  461. hs_cache_intro_state_t **state)
  462. {
  463. hs_cache_intro_state_t *entry, *old_entry;
  464. hs_cache_client_intro_state_t *cache;
  465. tor_assert(service_pk);
  466. tor_assert(auth_key);
  467. /* Lookup the state cache for this service key. */
  468. cache = digest256map_get(hs_cache_client_intro_state, service_pk->pubkey);
  469. if (cache == NULL) {
  470. cache = cache_client_intro_state_new();
  471. digest256map_set(hs_cache_client_intro_state, service_pk->pubkey, cache);
  472. }
  473. entry = cache_intro_state_new();
  474. old_entry = digest256map_set(cache->intro_points, auth_key->pubkey, entry);
  475. /* This should never happened because the code flow is to lookup the entry
  476. * before adding it. But, just in case, non fatal assert and free it. */
  477. tor_assert_nonfatal(old_entry == NULL);
  478. tor_free(old_entry);
  479. if (state) {
  480. *state = entry;
  481. }
  482. }
  483. /* Remove every intro point state entry from cache that has been created
  484. * before or at the cutoff. */
  485. static void
  486. cache_client_intro_state_clean(time_t cutoff,
  487. hs_cache_client_intro_state_t *cache)
  488. {
  489. tor_assert(cache);
  490. DIGEST256MAP_FOREACH_MODIFY(cache->intro_points, key,
  491. hs_cache_intro_state_t *, entry) {
  492. if (entry->created_ts <= cutoff) {
  493. cache_intro_state_free(entry);
  494. MAP_DEL_CURRENT(key);
  495. }
  496. } DIGEST256MAP_FOREACH_END;
  497. }
  498. /* Return true iff no intro points are in this cache. */
  499. static int
  500. cache_client_intro_state_is_empty(const hs_cache_client_intro_state_t *cache)
  501. {
  502. return digest256map_isempty(cache->intro_points);
  503. }
  504. /** Check whether <b>client_desc</b> is useful for us, and store it in the
  505. * client-side HS cache if so. The client_desc is freed if we already have a
  506. * fresher (higher revision counter count) in the cache. */
  507. static int
  508. cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
  509. {
  510. hs_cache_client_descriptor_t *cache_entry;
  511. /* TODO: Heavy code duplication with cache_store_as_dir(). Consider
  512. * refactoring and uniting! */
  513. tor_assert(client_desc);
  514. /* Check if we already have a descriptor from this HS in cache. If we do,
  515. * check if this descriptor is newer than the cached one */
  516. cache_entry = lookup_v3_desc_as_client(client_desc->key.pubkey);
  517. if (cache_entry != NULL) {
  518. /* If we have an entry in our cache that has a revision counter greater
  519. * than the one we just fetched, discard the one we fetched. */
  520. if (cache_entry->desc->plaintext_data.revision_counter >
  521. client_desc->desc->plaintext_data.revision_counter) {
  522. log_info(LD_REND, "We already have fresher descriptor. Ignoring.");
  523. cache_client_desc_free(client_desc);
  524. goto done;
  525. }
  526. /* Remove old entry. Make space for the new one! */
  527. remove_v3_desc_as_client(cache_entry);
  528. cache_client_desc_free(cache_entry);
  529. }
  530. /* Store descriptor in cache */
  531. store_v3_desc_as_client(client_desc);
  532. done:
  533. return 0;
  534. }
  535. /* Clean the client cache using now as the current time. Return the total size
  536. * of removed bytes from the cache. */
  537. static size_t
  538. cache_clean_v3_as_client(time_t now)
  539. {
  540. size_t bytes_removed = 0;
  541. if (!hs_cache_v3_client) { /* No cache to clean. Just return. */
  542. return 0;
  543. }
  544. DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_client, key,
  545. hs_cache_client_descriptor_t *, entry) {
  546. size_t entry_size;
  547. time_t cutoff = now - rend_cache_max_entry_lifetime();
  548. /* If the entry has been created _after_ the cutoff, not expired so
  549. * continue to the next entry in our v3 cache. */
  550. if (entry->created_ts > cutoff) {
  551. continue;
  552. }
  553. /* Here, our entry has expired, remove and free. */
  554. MAP_DEL_CURRENT(key);
  555. entry_size = cache_get_client_entry_size(entry);
  556. bytes_removed += entry_size;
  557. /* Entry is not in the cache anymore, destroy it. */
  558. cache_client_desc_free(entry);
  559. /* Update our OOM. We didn't use the remove() function because we are in
  560. * a loop so we have to explicitely decrement. */
  561. rend_cache_decrement_allocation(entry_size);
  562. /* Logging. */
  563. {
  564. char key_b64[BASE64_DIGEST256_LEN + 1];
  565. digest256_to_base64(key_b64, (const char *) key);
  566. log_info(LD_REND, "Removing hidden service v3 descriptor '%s' "
  567. "from client cache",
  568. safe_str_client(key_b64));
  569. }
  570. } DIGEST256MAP_FOREACH_END;
  571. return bytes_removed;
  572. }
  573. /** Public API: Given the HS ed25519 identity public key in <b>key</b>, return
  574. * its HS descriptor if it's stored in our cache, or NULL if not. */
  575. const hs_descriptor_t *
  576. hs_cache_lookup_as_client(const ed25519_public_key_t *key)
  577. {
  578. hs_cache_client_descriptor_t *cached_desc = NULL;
  579. tor_assert(key);
  580. cached_desc = lookup_v3_desc_as_client(key->pubkey);
  581. if (cached_desc) {
  582. tor_assert(cached_desc->desc);
  583. return cached_desc->desc;
  584. }
  585. return NULL;
  586. }
  587. /** Public API: Given an encoded descriptor, store it in the client HS
  588. * cache. Return -1 on error, 0 on success .*/
  589. int
  590. hs_cache_store_as_client(const char *desc_str,
  591. const ed25519_public_key_t *identity_pk)
  592. {
  593. hs_cache_client_descriptor_t *client_desc = NULL;
  594. tor_assert(desc_str);
  595. tor_assert(identity_pk);
  596. /* Create client cache descriptor object */
  597. client_desc = cache_client_desc_new(desc_str, identity_pk);
  598. if (!client_desc) {
  599. log_warn(LD_GENERAL, "Failed to parse received descriptor %s.",
  600. escaped(desc_str));
  601. goto err;
  602. }
  603. /* Push it to the cache */
  604. if (cache_store_as_client(client_desc) < 0) {
  605. goto err;
  606. }
  607. return 0;
  608. err:
  609. cache_client_desc_free(client_desc);
  610. return -1;
  611. }
  612. /* Clean all client caches using the current time now. */
  613. void
  614. hs_cache_clean_as_client(time_t now)
  615. {
  616. /* Start with v2 cache cleaning. */
  617. rend_cache_clean(now, REND_CACHE_TYPE_CLIENT);
  618. /* Now, clean the v3 cache. Set the cutoff to 0 telling the cleanup function
  619. * to compute the cutoff by itself using the lifetime value. */
  620. cache_clean_v3_as_client(now);
  621. }
  622. /* Purge the client descriptor cache. */
  623. void
  624. hs_cache_purge_as_client(void)
  625. {
  626. DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_client, key,
  627. hs_cache_client_descriptor_t *, entry) {
  628. size_t entry_size = cache_get_client_entry_size(entry);
  629. MAP_DEL_CURRENT(key);
  630. cache_client_desc_free(entry);
  631. /* Update our OOM. We didn't use the remove() function because we are in
  632. * a loop so we have to explicitely decrement. */
  633. rend_cache_decrement_allocation(entry_size);
  634. } DIGEST256MAP_FOREACH_END;
  635. log_info(LD_REND, "Hidden service client descriptor cache purged.");
  636. }
  637. /* For a given service identity public key and an introduction authentication
  638. * key, note the given failure in the client intro state cache. */
  639. void
  640. hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk,
  641. const ed25519_public_key_t *auth_key,
  642. rend_intro_point_failure_t failure)
  643. {
  644. int found;
  645. hs_cache_intro_state_t *entry;
  646. tor_assert(service_pk);
  647. tor_assert(auth_key);
  648. found = cache_client_intro_state_lookup(service_pk, auth_key, &entry);
  649. if (!found) {
  650. /* Create a new entry and add it to the cache. */
  651. cache_client_intro_state_add(service_pk, auth_key, &entry);
  652. }
  653. /* Note down the entry. */
  654. cache_client_intro_state_note(entry, failure);
  655. }
  656. /* For a given service identity public key and an introduction authentication
  657. * key, return true iff it is present in the failure cache. */
  658. const hs_cache_intro_state_t *
  659. hs_cache_client_intro_state_find(const ed25519_public_key_t *service_pk,
  660. const ed25519_public_key_t *auth_key)
  661. {
  662. hs_cache_intro_state_t *state = NULL;
  663. cache_client_intro_state_lookup(service_pk, auth_key, &state);
  664. return state;
  665. }
  666. /* Cleanup the client introduction state cache. */
  667. void
  668. hs_cache_client_intro_state_clean(time_t now)
  669. {
  670. time_t cutoff = now - HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE;
  671. DIGEST256MAP_FOREACH_MODIFY(hs_cache_client_intro_state, key,
  672. hs_cache_client_intro_state_t *, cache) {
  673. /* Cleanup intro points failure. */
  674. cache_client_intro_state_clean(cutoff, cache);
  675. /* Is this cache empty for this service key? If yes, remove it from the
  676. * cache. Else keep it. */
  677. if (cache_client_intro_state_is_empty(cache)) {
  678. cache_client_intro_state_free(cache);
  679. MAP_DEL_CURRENT(key);
  680. }
  681. } DIGEST256MAP_FOREACH_END;
  682. }
  683. /* Purge the client introduction state cache. */
  684. void
  685. hs_cache_client_intro_state_purge(void)
  686. {
  687. DIGEST256MAP_FOREACH_MODIFY(hs_cache_client_intro_state, key,
  688. hs_cache_client_intro_state_t *, cache) {
  689. MAP_DEL_CURRENT(key);
  690. cache_client_intro_state_free(cache);
  691. } DIGEST256MAP_FOREACH_END;
  692. log_info(LD_REND, "Hidden service client introduction point state "
  693. "cache purged.");
  694. }
  695. /**************** Generics *********************************/
  696. /* Do a round of OOM cleanup on all directory caches. Return the amount of
  697. * removed bytes. It is possible that the returned value is lower than
  698. * min_remove_bytes if the caches get emptied out so the caller should be
  699. * aware of this. */
  700. size_t
  701. hs_cache_handle_oom(time_t now, size_t min_remove_bytes)
  702. {
  703. time_t k;
  704. size_t bytes_removed = 0;
  705. /* Our OOM handler called with 0 bytes to remove is a code flow error. */
  706. tor_assert(min_remove_bytes != 0);
  707. /* The algorithm is as follow. K is the oldest expected descriptor age.
  708. *
  709. * 1) Deallocate all entries from v2 cache that are older than K hours.
  710. * 1.1) If the amount of remove bytes has been reached, stop.
  711. * 2) Deallocate all entries from v3 cache that are older than K hours
  712. * 2.1) If the amount of remove bytes has been reached, stop.
  713. * 3) Set K = K - RendPostPeriod and repeat process until K is < 0.
  714. *
  715. * This ends up being O(Kn).
  716. */
  717. /* Set K to the oldest expected age in seconds which is the maximum
  718. * lifetime of a cache entry. We'll use the v2 lifetime because it's much
  719. * bigger than the v3 thus leading to cleaning older descriptors. */
  720. k = rend_cache_max_entry_lifetime();
  721. do {
  722. time_t cutoff;
  723. /* If K becomes negative, it means we've empty the caches so stop and
  724. * return what we were able to cleanup. */
  725. if (k < 0) {
  726. break;
  727. }
  728. /* Compute a cutoff value with K and the current time. */
  729. cutoff = now - k;
  730. /* Start by cleaning the v2 cache with that cutoff. */
  731. bytes_removed += rend_cache_clean_v2_descs_as_dir(cutoff);
  732. if (bytes_removed < min_remove_bytes) {
  733. /* We haven't remove enough bytes so clean v3 cache. */
  734. bytes_removed += cache_clean_v3_as_dir(now, cutoff);
  735. /* Decrement K by a post period to shorten the cutoff. */
  736. k -= get_options()->RendPostPeriod;
  737. }
  738. } while (bytes_removed < min_remove_bytes);
  739. return bytes_removed;
  740. }
  741. /* Return the maximum size of a v3 HS descriptor. */
  742. unsigned int
  743. hs_cache_get_max_descriptor_size(void)
  744. {
  745. return (unsigned) networkstatus_get_param(NULL,
  746. "HSV3MaxDescriptorSize",
  747. HS_DESC_MAX_LEN, 1, INT32_MAX);
  748. }
  749. /* Initialize the hidden service cache subsystem. */
  750. void
  751. hs_cache_init(void)
  752. {
  753. /* Calling this twice is very wrong code flow. */
  754. tor_assert(!hs_cache_v3_dir);
  755. hs_cache_v3_dir = digest256map_new();
  756. tor_assert(!hs_cache_v3_client);
  757. hs_cache_v3_client = digest256map_new();
  758. tor_assert(!hs_cache_client_intro_state);
  759. hs_cache_client_intro_state = digest256map_new();
  760. }
  761. /* Cleanup the hidden service cache subsystem. */
  762. void
  763. hs_cache_free_all(void)
  764. {
  765. digest256map_free(hs_cache_v3_dir, cache_dir_desc_free_);
  766. hs_cache_v3_dir = NULL;
  767. digest256map_free(hs_cache_v3_client, cache_client_desc_free_);
  768. hs_cache_v3_client = NULL;
  769. digest256map_free(hs_cache_client_intro_state,
  770. cache_client_intro_state_free_);
  771. hs_cache_client_intro_state = NULL;
  772. }