hs_cache.c 35 KB

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