hs_cache.c 29 KB

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