dirserv.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. /* Copyright (c) 2001-2004, Roger Dingledine.
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #define DIRSERV_PRIVATE
  6. #include "core/or/or.h"
  7. #include "app/config/config.h"
  8. #include "core/mainloop/connection.h"
  9. #include "feature/dircache/conscache.h"
  10. #include "feature/dircache/consdiffmgr.h"
  11. #include "feature/dircommon/directory.h"
  12. #include "feature/dircache/dirserv.h"
  13. #include "feature/nodelist/microdesc.h"
  14. #include "feature/nodelist/routerlist.h"
  15. #include "feature/relay/router.h"
  16. #include "feature/relay/routermode.h"
  17. #include "feature/stats/predict_ports.h"
  18. #include "feature/dircache/cached_dir_st.h"
  19. #include "feature/dircommon/dir_connection_st.h"
  20. #include "feature/nodelist/extrainfo_st.h"
  21. #include "feature/nodelist/microdesc_st.h"
  22. #include "feature/nodelist/routerinfo_st.h"
  23. #include "feature/nodelist/routerlist_st.h"
  24. #include "lib/compress/compress.h"
  25. /**
  26. * \file dirserv.c
  27. * \brief Directory server core implementation. Manages directory
  28. * contents and generates directory documents.
  29. *
  30. * This module implements most of directory cache functionality, and some of
  31. * the directory authority functionality. The directory.c module delegates
  32. * here in order to handle incoming requests from clients, via
  33. * connection_dirserv_flushed_some() and its kin. In order to save RAM, this
  34. * module is responsible for spooling directory objects (in whole or in part)
  35. * onto buf_t instances, and then closing the dir_connection_t once the
  36. * objects are totally flushed.
  37. *
  38. * The directory.c module also delegates here for handling descriptor uploads
  39. * via dirserv_add_multiple_descriptors().
  40. *
  41. * Additionally, this module handles some aspects of voting, including:
  42. * deciding how to vote on individual flags (based on decisions reached in
  43. * rephist.c), of formatting routerstatus lines, and deciding what relays to
  44. * include in an authority's vote. (TODO: Those functions could profitably be
  45. * split off. They only live in this file because historically they were
  46. * shared among the v1, v2, and v3 directory code.)
  47. */
  48. static void clear_cached_dir(cached_dir_t *d);
  49. static const signed_descriptor_t *get_signed_descriptor_by_fp(
  50. const uint8_t *fp,
  51. int extrainfo);
  52. static int spooled_resource_lookup_body(const spooled_resource_t *spooled,
  53. int conn_is_encrypted,
  54. const uint8_t **body_out,
  55. size_t *size_out,
  56. time_t *published_out);
  57. static cached_dir_t *spooled_resource_lookup_cached_dir(
  58. const spooled_resource_t *spooled,
  59. time_t *published_out);
  60. static cached_dir_t *lookup_cached_dir_by_fp(const uint8_t *fp);
  61. /********************************************************************/
  62. /* A set of functions to answer questions about how we'd like to behave
  63. * as a directory mirror/client. */
  64. /** Return 1 if we fetch our directory material directly from the
  65. * authorities, rather than from a mirror. */
  66. int
  67. directory_fetches_from_authorities(const or_options_t *options)
  68. {
  69. const routerinfo_t *me;
  70. uint32_t addr;
  71. int refuseunknown;
  72. if (options->FetchDirInfoEarly)
  73. return 1;
  74. if (options->BridgeRelay == 1)
  75. return 0;
  76. if (server_mode(options) &&
  77. router_pick_published_address(options, &addr, 1) < 0)
  78. return 1; /* we don't know our IP address; ask an authority. */
  79. refuseunknown = ! router_my_exit_policy_is_reject_star() &&
  80. should_refuse_unknown_exits(options);
  81. if (!dir_server_mode(options) && !refuseunknown)
  82. return 0;
  83. if (!server_mode(options) || !advertised_server_mode())
  84. return 0;
  85. me = router_get_my_routerinfo();
  86. if (!me || (!me->supports_tunnelled_dir_requests && !refuseunknown))
  87. return 0; /* if we don't service directory requests, return 0 too */
  88. return 1;
  89. }
  90. /** Return 1 if we should fetch new networkstatuses, descriptors, etc
  91. * on the "mirror" schedule rather than the "client" schedule.
  92. */
  93. int
  94. directory_fetches_dir_info_early(const or_options_t *options)
  95. {
  96. return directory_fetches_from_authorities(options);
  97. }
  98. /** Return 1 if we should fetch new networkstatuses, descriptors, etc
  99. * on a very passive schedule -- waiting long enough for ordinary clients
  100. * to probably have the info we want. These would include bridge users,
  101. * and maybe others in the future e.g. if a Tor client uses another Tor
  102. * client as a directory guard.
  103. */
  104. int
  105. directory_fetches_dir_info_later(const or_options_t *options)
  106. {
  107. return options->UseBridges != 0;
  108. }
  109. /** Return true iff we want to serve certificates for authorities
  110. * that we don't acknowledge as authorities ourself.
  111. * Use we_want_to_fetch_unknown_auth_certs to check if we want to fetch
  112. * and keep these certificates.
  113. */
  114. int
  115. directory_caches_unknown_auth_certs(const or_options_t *options)
  116. {
  117. return dir_server_mode(options) || options->BridgeRelay;
  118. }
  119. /** Return 1 if we want to fetch and serve descriptors, networkstatuses, etc
  120. * Else return 0.
  121. * Check options->DirPort_set and directory_permits_begindir_requests()
  122. * to see if we are willing to serve these directory documents to others via
  123. * the DirPort and begindir-over-ORPort, respectively.
  124. *
  125. * To check if we should fetch documents, use we_want_to_fetch_flavor and
  126. * we_want_to_fetch_unknown_auth_certs instead of this function.
  127. */
  128. int
  129. directory_caches_dir_info(const or_options_t *options)
  130. {
  131. if (options->BridgeRelay || dir_server_mode(options))
  132. return 1;
  133. if (!server_mode(options) || !advertised_server_mode())
  134. return 0;
  135. /* We need an up-to-date view of network info if we're going to try to
  136. * block exit attempts from unknown relays. */
  137. return ! router_my_exit_policy_is_reject_star() &&
  138. should_refuse_unknown_exits(options);
  139. }
  140. /** Return 1 if we want to allow remote clients to ask us directory
  141. * requests via the "begin_dir" interface, which doesn't require
  142. * having any separate port open. */
  143. int
  144. directory_permits_begindir_requests(const or_options_t *options)
  145. {
  146. return options->BridgeRelay != 0 || dir_server_mode(options);
  147. }
  148. /** Return 1 if we have no need to fetch new descriptors. This generally
  149. * happens when we're not a dir cache and we haven't built any circuits
  150. * lately.
  151. */
  152. int
  153. directory_too_idle_to_fetch_descriptors(const or_options_t *options,
  154. time_t now)
  155. {
  156. return !directory_caches_dir_info(options) &&
  157. !options->FetchUselessDescriptors &&
  158. rep_hist_circbuilding_dormant(now);
  159. }
  160. /********************************************************************/
  161. /** Map from flavor name to the cached_dir_t for the v3 consensuses that we're
  162. * currently serving. */
  163. static strmap_t *cached_consensuses = NULL;
  164. /** Decrement the reference count on <b>d</b>, and free it if it no longer has
  165. * any references. */
  166. void
  167. cached_dir_decref(cached_dir_t *d)
  168. {
  169. if (!d || --d->refcnt > 0)
  170. return;
  171. clear_cached_dir(d);
  172. tor_free(d);
  173. }
  174. /** Allocate and return a new cached_dir_t containing the string <b>s</b>,
  175. * published at <b>published</b>. */
  176. cached_dir_t *
  177. new_cached_dir(char *s, time_t published)
  178. {
  179. cached_dir_t *d = tor_malloc_zero(sizeof(cached_dir_t));
  180. d->refcnt = 1;
  181. d->dir = s;
  182. d->dir_len = strlen(s);
  183. d->published = published;
  184. if (tor_compress(&(d->dir_compressed), &(d->dir_compressed_len),
  185. d->dir, d->dir_len, ZLIB_METHOD)) {
  186. log_warn(LD_BUG, "Error compressing directory");
  187. }
  188. return d;
  189. }
  190. /** Remove all storage held in <b>d</b>, but do not free <b>d</b> itself. */
  191. static void
  192. clear_cached_dir(cached_dir_t *d)
  193. {
  194. tor_free(d->dir);
  195. tor_free(d->dir_compressed);
  196. memset(d, 0, sizeof(cached_dir_t));
  197. }
  198. /** Free all storage held by the cached_dir_t in <b>d</b>. */
  199. static void
  200. free_cached_dir_(void *_d)
  201. {
  202. cached_dir_t *d;
  203. if (!_d)
  204. return;
  205. d = (cached_dir_t *)_d;
  206. cached_dir_decref(d);
  207. }
  208. /** Replace the v3 consensus networkstatus of type <b>flavor_name</b> that
  209. * we're serving with <b>networkstatus</b>, published at <b>published</b>. No
  210. * validation is performed. */
  211. void
  212. dirserv_set_cached_consensus_networkstatus(const char *networkstatus,
  213. size_t networkstatus_len,
  214. const char *flavor_name,
  215. const common_digests_t *digests,
  216. const uint8_t *sha3_as_signed,
  217. time_t published)
  218. {
  219. cached_dir_t *new_networkstatus;
  220. cached_dir_t *old_networkstatus;
  221. if (!cached_consensuses)
  222. cached_consensuses = strmap_new();
  223. new_networkstatus =
  224. new_cached_dir(tor_memdup_nulterm(networkstatus, networkstatus_len),
  225. published);
  226. memcpy(&new_networkstatus->digests, digests, sizeof(common_digests_t));
  227. memcpy(&new_networkstatus->digest_sha3_as_signed, sha3_as_signed,
  228. DIGEST256_LEN);
  229. old_networkstatus = strmap_set(cached_consensuses, flavor_name,
  230. new_networkstatus);
  231. if (old_networkstatus)
  232. cached_dir_decref(old_networkstatus);
  233. }
  234. /** Return the latest downloaded consensus networkstatus in encoded, signed,
  235. * optionally compressed format, suitable for sending to clients. */
  236. cached_dir_t *
  237. dirserv_get_consensus(const char *flavor_name)
  238. {
  239. if (!cached_consensuses)
  240. return NULL;
  241. return strmap_get(cached_consensuses, flavor_name);
  242. }
  243. /** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t
  244. * pointers, adds copies of digests to fps_out, and doesn't use the
  245. * /tor/server/ prefix. For a /d/ request, adds descriptor digests; for other
  246. * requests, adds identity digests.
  247. */
  248. int
  249. dirserv_get_routerdesc_spool(smartlist_t *spool_out,
  250. const char *key,
  251. dir_spool_source_t source,
  252. int conn_is_encrypted,
  253. const char **msg_out)
  254. {
  255. *msg_out = NULL;
  256. if (!strcmp(key, "all")) {
  257. const routerlist_t *rl = router_get_routerlist();
  258. SMARTLIST_FOREACH_BEGIN(rl->routers, const routerinfo_t *, r) {
  259. spooled_resource_t *spooled;
  260. spooled = spooled_resource_new(source,
  261. (const uint8_t *)r->cache_info.identity_digest,
  262. DIGEST_LEN);
  263. /* Treat "all" requests as if they were unencrypted */
  264. conn_is_encrypted = 0;
  265. smartlist_add(spool_out, spooled);
  266. } SMARTLIST_FOREACH_END(r);
  267. } else if (!strcmp(key, "authority")) {
  268. const routerinfo_t *ri = router_get_my_routerinfo();
  269. if (ri)
  270. smartlist_add(spool_out,
  271. spooled_resource_new(source,
  272. (const uint8_t *)ri->cache_info.identity_digest,
  273. DIGEST_LEN));
  274. } else if (!strcmpstart(key, "d/")) {
  275. key += strlen("d/");
  276. dir_split_resource_into_spoolable(key, source, spool_out, NULL,
  277. DSR_HEX|DSR_SORT_UNIQ);
  278. } else if (!strcmpstart(key, "fp/")) {
  279. key += strlen("fp/");
  280. dir_split_resource_into_spoolable(key, source, spool_out, NULL,
  281. DSR_HEX|DSR_SORT_UNIQ);
  282. } else {
  283. *msg_out = "Not found";
  284. return -1;
  285. }
  286. if (! conn_is_encrypted) {
  287. /* Remove anything that insists it not be sent unencrypted. */
  288. SMARTLIST_FOREACH_BEGIN(spool_out, spooled_resource_t *, spooled) {
  289. const uint8_t *body = NULL;
  290. size_t bodylen = 0;
  291. int r = spooled_resource_lookup_body(spooled, conn_is_encrypted,
  292. &body, &bodylen, NULL);
  293. if (r < 0 || body == NULL || bodylen == 0) {
  294. SMARTLIST_DEL_CURRENT(spool_out, spooled);
  295. spooled_resource_free(spooled);
  296. }
  297. } SMARTLIST_FOREACH_END(spooled);
  298. }
  299. if (!smartlist_len(spool_out)) {
  300. *msg_out = "Servers unavailable";
  301. return -1;
  302. }
  303. return 0;
  304. }
  305. /** Add a signed_descriptor_t to <b>descs_out</b> for each router matching
  306. * <b>key</b>. The key should be either
  307. * - "/tor/server/authority" for our own routerinfo;
  308. * - "/tor/server/all" for all the routerinfos we have, concatenated;
  309. * - "/tor/server/fp/FP" where FP is a plus-separated sequence of
  310. * hex identity digests; or
  311. * - "/tor/server/d/D" where D is a plus-separated sequence
  312. * of server descriptor digests, in hex.
  313. *
  314. * Return 0 if we found some matching descriptors, or -1 if we do not
  315. * have any descriptors, no matching descriptors, or if we did not
  316. * recognize the key (URL).
  317. * If -1 is returned *<b>msg</b> will be set to an appropriate error
  318. * message.
  319. *
  320. * XXXX rename this function. It's only called from the controller.
  321. * XXXX in fact, refactor this function, merging as much as possible.
  322. */
  323. int
  324. dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
  325. const char **msg)
  326. {
  327. *msg = NULL;
  328. if (!strcmp(key, "/tor/server/all")) {
  329. routerlist_t *rl = router_get_routerlist();
  330. SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
  331. smartlist_add(descs_out, &(r->cache_info)));
  332. } else if (!strcmp(key, "/tor/server/authority")) {
  333. const routerinfo_t *ri = router_get_my_routerinfo();
  334. if (ri)
  335. smartlist_add(descs_out, (void*) &(ri->cache_info));
  336. } else if (!strcmpstart(key, "/tor/server/d/")) {
  337. smartlist_t *digests = smartlist_new();
  338. key += strlen("/tor/server/d/");
  339. dir_split_resource_into_fingerprints(key, digests, NULL,
  340. DSR_HEX|DSR_SORT_UNIQ);
  341. SMARTLIST_FOREACH(digests, const char *, d,
  342. {
  343. signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
  344. if (sd)
  345. smartlist_add(descs_out,sd);
  346. });
  347. SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
  348. smartlist_free(digests);
  349. } else if (!strcmpstart(key, "/tor/server/fp/")) {
  350. smartlist_t *digests = smartlist_new();
  351. time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
  352. key += strlen("/tor/server/fp/");
  353. dir_split_resource_into_fingerprints(key, digests, NULL,
  354. DSR_HEX|DSR_SORT_UNIQ);
  355. SMARTLIST_FOREACH_BEGIN(digests, const char *, d) {
  356. if (router_digest_is_me(d)) {
  357. /* calling router_get_my_routerinfo() to make sure it exists */
  358. const routerinfo_t *ri = router_get_my_routerinfo();
  359. if (ri)
  360. smartlist_add(descs_out, (void*) &(ri->cache_info));
  361. } else {
  362. const routerinfo_t *ri = router_get_by_id_digest(d);
  363. /* Don't actually serve a descriptor that everyone will think is
  364. * expired. This is an (ugly) workaround to keep buggy 0.1.1.10
  365. * Tors from downloading descriptors that they will throw away.
  366. */
  367. if (ri && ri->cache_info.published_on > cutoff)
  368. smartlist_add(descs_out, (void*) &(ri->cache_info));
  369. }
  370. } SMARTLIST_FOREACH_END(d);
  371. SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
  372. smartlist_free(digests);
  373. } else {
  374. *msg = "Key not recognized";
  375. return -1;
  376. }
  377. if (!smartlist_len(descs_out)) {
  378. *msg = "Servers unavailable";
  379. return -1;
  380. }
  381. return 0;
  382. }
  383. /* ==========
  384. * Spooling code.
  385. * ========== */
  386. spooled_resource_t *
  387. spooled_resource_new(dir_spool_source_t source,
  388. const uint8_t *digest, size_t digestlen)
  389. {
  390. spooled_resource_t *spooled = tor_malloc_zero(sizeof(spooled_resource_t));
  391. spooled->spool_source = source;
  392. switch (source) {
  393. case DIR_SPOOL_NETWORKSTATUS:
  394. spooled->spool_eagerly = 0;
  395. break;
  396. case DIR_SPOOL_SERVER_BY_DIGEST:
  397. case DIR_SPOOL_SERVER_BY_FP:
  398. case DIR_SPOOL_EXTRA_BY_DIGEST:
  399. case DIR_SPOOL_EXTRA_BY_FP:
  400. case DIR_SPOOL_MICRODESC:
  401. default:
  402. spooled->spool_eagerly = 1;
  403. break;
  404. case DIR_SPOOL_CONSENSUS_CACHE_ENTRY:
  405. tor_assert_unreached();
  406. break;
  407. }
  408. tor_assert(digestlen <= sizeof(spooled->digest));
  409. if (digest)
  410. memcpy(spooled->digest, digest, digestlen);
  411. return spooled;
  412. }
  413. /**
  414. * Create a new spooled_resource_t to spool the contents of <b>entry</b> to
  415. * the user. Return the spooled object on success, or NULL on failure (which
  416. * is probably caused by a failure to map the body of the item from disk).
  417. *
  418. * Adds a reference to entry's reference counter.
  419. */
  420. spooled_resource_t *
  421. spooled_resource_new_from_cache_entry(consensus_cache_entry_t *entry)
  422. {
  423. spooled_resource_t *spooled = tor_malloc_zero(sizeof(spooled_resource_t));
  424. spooled->spool_source = DIR_SPOOL_CONSENSUS_CACHE_ENTRY;
  425. spooled->spool_eagerly = 0;
  426. consensus_cache_entry_incref(entry);
  427. spooled->consensus_cache_entry = entry;
  428. int r = consensus_cache_entry_get_body(entry,
  429. &spooled->cce_body,
  430. &spooled->cce_len);
  431. if (r == 0) {
  432. return spooled;
  433. } else {
  434. spooled_resource_free(spooled);
  435. return NULL;
  436. }
  437. }
  438. /** Release all storage held by <b>spooled</b>. */
  439. void
  440. spooled_resource_free_(spooled_resource_t *spooled)
  441. {
  442. if (spooled == NULL)
  443. return;
  444. if (spooled->cached_dir_ref) {
  445. cached_dir_decref(spooled->cached_dir_ref);
  446. }
  447. if (spooled->consensus_cache_entry) {
  448. consensus_cache_entry_decref(spooled->consensus_cache_entry);
  449. }
  450. tor_free(spooled);
  451. }
  452. /** When spooling data from a cached_dir_t object, we always add
  453. * at least this much. */
  454. #define DIRSERV_CACHED_DIR_CHUNK_SIZE 8192
  455. /** Return an compression ratio for compressing objects from <b>source</b>.
  456. */
  457. static double
  458. estimate_compression_ratio(dir_spool_source_t source)
  459. {
  460. /* We should put in better estimates here, depending on the number of
  461. objects and their type */
  462. (void) source;
  463. return 0.5;
  464. }
  465. /** Return an estimated number of bytes needed for transmitting the
  466. * resource in <b>spooled</b> on <b>conn</b>
  467. *
  468. * As a convenient side-effect, set *<b>published_out</b> to the resource's
  469. * publication time.
  470. */
  471. static size_t
  472. spooled_resource_estimate_size(const spooled_resource_t *spooled,
  473. dir_connection_t *conn,
  474. int compressed,
  475. time_t *published_out)
  476. {
  477. if (spooled->spool_eagerly) {
  478. const uint8_t *body = NULL;
  479. size_t bodylen = 0;
  480. int r = spooled_resource_lookup_body(spooled,
  481. connection_dir_is_encrypted(conn),
  482. &body, &bodylen,
  483. published_out);
  484. if (r == -1 || body == NULL || bodylen == 0)
  485. return 0;
  486. if (compressed) {
  487. double ratio = estimate_compression_ratio(spooled->spool_source);
  488. bodylen = (size_t)(bodylen * ratio);
  489. }
  490. return bodylen;
  491. } else {
  492. cached_dir_t *cached;
  493. if (spooled->consensus_cache_entry) {
  494. if (published_out) {
  495. consensus_cache_entry_get_valid_after(
  496. spooled->consensus_cache_entry, published_out);
  497. }
  498. return spooled->cce_len;
  499. }
  500. if (spooled->cached_dir_ref) {
  501. cached = spooled->cached_dir_ref;
  502. } else {
  503. cached = spooled_resource_lookup_cached_dir(spooled,
  504. published_out);
  505. }
  506. if (cached == NULL) {
  507. return 0;
  508. }
  509. size_t result = compressed ? cached->dir_compressed_len : cached->dir_len;
  510. return result;
  511. }
  512. }
  513. /** Return code for spooled_resource_flush_some */
  514. typedef enum {
  515. SRFS_ERR = -1,
  516. SRFS_MORE = 0,
  517. SRFS_DONE
  518. } spooled_resource_flush_status_t;
  519. /** Flush some or all of the bytes from <b>spooled</b> onto <b>conn</b>.
  520. * Return SRFS_ERR on error, SRFS_MORE if there are more bytes to flush from
  521. * this spooled resource, or SRFS_DONE if we are done flushing this spooled
  522. * resource.
  523. */
  524. static spooled_resource_flush_status_t
  525. spooled_resource_flush_some(spooled_resource_t *spooled,
  526. dir_connection_t *conn)
  527. {
  528. if (spooled->spool_eagerly) {
  529. /* Spool_eagerly resources are sent all-at-once. */
  530. const uint8_t *body = NULL;
  531. size_t bodylen = 0;
  532. int r = spooled_resource_lookup_body(spooled,
  533. connection_dir_is_encrypted(conn),
  534. &body, &bodylen, NULL);
  535. if (r == -1 || body == NULL || bodylen == 0) {
  536. /* Absent objects count as "done". */
  537. return SRFS_DONE;
  538. }
  539. connection_dir_buf_add((const char*)body, bodylen, conn, 0);
  540. return SRFS_DONE;
  541. } else {
  542. cached_dir_t *cached = spooled->cached_dir_ref;
  543. consensus_cache_entry_t *cce = spooled->consensus_cache_entry;
  544. if (cached == NULL && cce == NULL) {
  545. /* The cached_dir_t hasn't been materialized yet. So let's look it up. */
  546. cached = spooled->cached_dir_ref =
  547. spooled_resource_lookup_cached_dir(spooled, NULL);
  548. if (!cached) {
  549. /* Absent objects count as done. */
  550. return SRFS_DONE;
  551. }
  552. ++cached->refcnt;
  553. tor_assert_nonfatal(spooled->cached_dir_offset == 0);
  554. }
  555. if (BUG(!cached && !cce))
  556. return SRFS_DONE;
  557. int64_t total_len;
  558. const char *ptr;
  559. if (cached) {
  560. total_len = cached->dir_compressed_len;
  561. ptr = cached->dir_compressed;
  562. } else {
  563. total_len = spooled->cce_len;
  564. ptr = (const char *)spooled->cce_body;
  565. }
  566. /* How many bytes left to flush? */
  567. int64_t remaining;
  568. remaining = total_len - spooled->cached_dir_offset;
  569. if (BUG(remaining < 0))
  570. return SRFS_ERR;
  571. ssize_t bytes = (ssize_t) MIN(DIRSERV_CACHED_DIR_CHUNK_SIZE, remaining);
  572. connection_dir_buf_add(ptr + spooled->cached_dir_offset,
  573. bytes, conn, 0);
  574. spooled->cached_dir_offset += bytes;
  575. if (spooled->cached_dir_offset >= (off_t)total_len) {
  576. return SRFS_DONE;
  577. } else {
  578. return SRFS_MORE;
  579. }
  580. }
  581. }
  582. /** Helper: find the cached_dir_t for a spooled_resource_t, for
  583. * sending it to <b>conn</b>. Set *<b>published_out</b>, if provided,
  584. * to the published time of the cached_dir_t.
  585. *
  586. * DOES NOT increase the reference count on the result. Callers must do that
  587. * themselves if they mean to hang on to it.
  588. */
  589. static cached_dir_t *
  590. spooled_resource_lookup_cached_dir(const spooled_resource_t *spooled,
  591. time_t *published_out)
  592. {
  593. tor_assert(spooled->spool_eagerly == 0);
  594. cached_dir_t *d = lookup_cached_dir_by_fp(spooled->digest);
  595. if (d != NULL) {
  596. if (published_out)
  597. *published_out = d->published;
  598. }
  599. return d;
  600. }
  601. /** Helper: Look up the body for an eagerly-served spooled_resource. If
  602. * <b>conn_is_encrypted</b> is false, don't look up any resource that
  603. * shouldn't be sent over an unencrypted connection. On success, set
  604. * <b>body_out</b>, <b>size_out</b>, and <b>published_out</b> to refer
  605. * to the resource's body, size, and publication date, and return 0.
  606. * On failure return -1. */
  607. static int
  608. spooled_resource_lookup_body(const spooled_resource_t *spooled,
  609. int conn_is_encrypted,
  610. const uint8_t **body_out,
  611. size_t *size_out,
  612. time_t *published_out)
  613. {
  614. tor_assert(spooled->spool_eagerly == 1);
  615. const signed_descriptor_t *sd = NULL;
  616. switch (spooled->spool_source) {
  617. case DIR_SPOOL_EXTRA_BY_FP: {
  618. sd = get_signed_descriptor_by_fp(spooled->digest, 1);
  619. break;
  620. }
  621. case DIR_SPOOL_SERVER_BY_FP: {
  622. sd = get_signed_descriptor_by_fp(spooled->digest, 0);
  623. break;
  624. }
  625. case DIR_SPOOL_SERVER_BY_DIGEST: {
  626. sd = router_get_by_descriptor_digest((const char *)spooled->digest);
  627. break;
  628. }
  629. case DIR_SPOOL_EXTRA_BY_DIGEST: {
  630. sd = extrainfo_get_by_descriptor_digest((const char *)spooled->digest);
  631. break;
  632. }
  633. case DIR_SPOOL_MICRODESC: {
  634. microdesc_t *md = microdesc_cache_lookup_by_digest256(
  635. get_microdesc_cache(),
  636. (const char *)spooled->digest);
  637. if (! md || ! md->body) {
  638. return -1;
  639. }
  640. *body_out = (const uint8_t *)md->body;
  641. *size_out = md->bodylen;
  642. if (published_out)
  643. *published_out = TIME_MAX;
  644. return 0;
  645. }
  646. case DIR_SPOOL_NETWORKSTATUS:
  647. case DIR_SPOOL_CONSENSUS_CACHE_ENTRY:
  648. default:
  649. /* LCOV_EXCL_START */
  650. tor_assert_nonfatal_unreached();
  651. return -1;
  652. /* LCOV_EXCL_STOP */
  653. }
  654. /* If we get here, then we tried to set "sd" to a signed_descriptor_t. */
  655. if (sd == NULL) {
  656. return -1;
  657. }
  658. if (sd->send_unencrypted == 0 && ! conn_is_encrypted) {
  659. /* we did this check once before (so we could have an accurate size
  660. * estimate and maybe send a 404 if somebody asked for only bridges on
  661. * a connection), but we need to do it again in case a previously
  662. * unknown bridge descriptor has shown up between then and now. */
  663. return -1;
  664. }
  665. *body_out = (const uint8_t *) signed_descriptor_get_body(sd);
  666. *size_out = sd->signed_descriptor_len;
  667. if (published_out)
  668. *published_out = sd->published_on;
  669. return 0;
  670. }
  671. /** Given a fingerprint <b>fp</b> which is either set if we're looking for a
  672. * v2 status, or zeroes if we're looking for a v3 status, or a NUL-padded
  673. * flavor name if we want a flavored v3 status, return a pointer to the
  674. * appropriate cached dir object, or NULL if there isn't one available. */
  675. static cached_dir_t *
  676. lookup_cached_dir_by_fp(const uint8_t *fp)
  677. {
  678. cached_dir_t *d = NULL;
  679. if (tor_digest_is_zero((const char *)fp) && cached_consensuses) {
  680. d = strmap_get(cached_consensuses, "ns");
  681. } else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses) {
  682. /* this here interface is a nasty hack: we're shoving a flavor into
  683. * a digest field. */
  684. d = strmap_get(cached_consensuses, (const char *)fp);
  685. }
  686. return d;
  687. }
  688. /** Try to guess the number of bytes that will be needed to send the
  689. * spooled objects for <b>conn</b>'s outgoing spool. In the process,
  690. * remove every element of the spool that refers to an absent object, or
  691. * which was published earlier than <b>cutoff</b>. Set *<b>size_out</b>
  692. * to the number of bytes, and *<b>n_expired_out</b> to the number of
  693. * objects removed for being too old. */
  694. void
  695. dirserv_spool_remove_missing_and_guess_size(dir_connection_t *conn,
  696. time_t cutoff,
  697. int compression,
  698. size_t *size_out,
  699. int *n_expired_out)
  700. {
  701. if (BUG(!conn))
  702. return;
  703. smartlist_t *spool = conn->spool;
  704. if (!spool) {
  705. if (size_out)
  706. *size_out = 0;
  707. if (n_expired_out)
  708. *n_expired_out = 0;
  709. return;
  710. }
  711. int n_expired = 0;
  712. uint64_t total = 0;
  713. SMARTLIST_FOREACH_BEGIN(spool, spooled_resource_t *, spooled) {
  714. time_t published = TIME_MAX;
  715. size_t sz = spooled_resource_estimate_size(spooled, conn,
  716. compression, &published);
  717. if (published < cutoff) {
  718. ++n_expired;
  719. SMARTLIST_DEL_CURRENT(spool, spooled);
  720. spooled_resource_free(spooled);
  721. } else if (sz == 0) {
  722. SMARTLIST_DEL_CURRENT(spool, spooled);
  723. spooled_resource_free(spooled);
  724. } else {
  725. total += sz;
  726. }
  727. } SMARTLIST_FOREACH_END(spooled);
  728. if (size_out) {
  729. *size_out = (total > SIZE_MAX) ? SIZE_MAX : (size_t)total;
  730. }
  731. if (n_expired_out)
  732. *n_expired_out = n_expired;
  733. }
  734. /** Helper: used to sort a connection's spool. */
  735. static int
  736. dirserv_spool_sort_comparison_(const void **a_, const void **b_)
  737. {
  738. const spooled_resource_t *a = *a_;
  739. const spooled_resource_t *b = *b_;
  740. return fast_memcmp(a->digest, b->digest, sizeof(a->digest));
  741. }
  742. /** Sort all the entries in <b>conn</b> by digest. */
  743. void
  744. dirserv_spool_sort(dir_connection_t *conn)
  745. {
  746. if (conn->spool == NULL)
  747. return;
  748. smartlist_sort(conn->spool, dirserv_spool_sort_comparison_);
  749. }
  750. /** Return the cache-info for identity fingerprint <b>fp</b>, or
  751. * its extra-info document if <b>extrainfo</b> is true. Return
  752. * NULL if not found or if the descriptor is older than
  753. * <b>publish_cutoff</b>. */
  754. static const signed_descriptor_t *
  755. get_signed_descriptor_by_fp(const uint8_t *fp, int extrainfo)
  756. {
  757. if (router_digest_is_me((const char *)fp)) {
  758. if (extrainfo)
  759. return &(router_get_my_extrainfo()->cache_info);
  760. else
  761. return &(router_get_my_routerinfo()->cache_info);
  762. } else {
  763. const routerinfo_t *ri = router_get_by_id_digest((const char *)fp);
  764. if (ri) {
  765. if (extrainfo)
  766. return extrainfo_get_by_descriptor_digest(
  767. ri->cache_info.extra_info_digest);
  768. else
  769. return &ri->cache_info;
  770. }
  771. }
  772. return NULL;
  773. }
  774. /** When we're spooling data onto our outbuf, add more whenever we dip
  775. * below this threshold. */
  776. #define DIRSERV_BUFFER_MIN 16384
  777. /**
  778. * Called whenever we have flushed some directory data in state
  779. * SERVER_WRITING, or whenever we want to fill the buffer with initial
  780. * directory data (so that subsequent writes will occur, and trigger this
  781. * function again.)
  782. *
  783. * Return 0 on success, and -1 on failure.
  784. */
  785. int
  786. connection_dirserv_flushed_some(dir_connection_t *conn)
  787. {
  788. tor_assert(conn->base_.state == DIR_CONN_STATE_SERVER_WRITING);
  789. if (conn->spool == NULL)
  790. return 0;
  791. while (connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN &&
  792. smartlist_len(conn->spool)) {
  793. spooled_resource_t *spooled =
  794. smartlist_get(conn->spool, smartlist_len(conn->spool)-1);
  795. spooled_resource_flush_status_t status;
  796. status = spooled_resource_flush_some(spooled, conn);
  797. if (status == SRFS_ERR) {
  798. return -1;
  799. } else if (status == SRFS_MORE) {
  800. return 0;
  801. }
  802. tor_assert(status == SRFS_DONE);
  803. /* If we're here, we're done flushing this resource. */
  804. tor_assert(smartlist_pop_last(conn->spool) == spooled);
  805. spooled_resource_free(spooled);
  806. }
  807. if (smartlist_len(conn->spool) > 0) {
  808. /* We're still spooling something. */
  809. return 0;
  810. }
  811. /* If we get here, we're done. */
  812. smartlist_free(conn->spool);
  813. conn->spool = NULL;
  814. if (conn->compress_state) {
  815. /* Flush the compression state: there could be more bytes pending in there,
  816. * and we don't want to omit bytes. */
  817. connection_buf_add_compress("", 0, conn, 1);
  818. tor_compress_free(conn->compress_state);
  819. conn->compress_state = NULL;
  820. }
  821. return 0;
  822. }
  823. /** Remove every element from <b>conn</b>'s outgoing spool, and delete
  824. * the spool. */
  825. void
  826. dir_conn_clear_spool(dir_connection_t *conn)
  827. {
  828. if (!conn || ! conn->spool)
  829. return;
  830. SMARTLIST_FOREACH(conn->spool, spooled_resource_t *, s,
  831. spooled_resource_free(s));
  832. smartlist_free(conn->spool);
  833. conn->spool = NULL;
  834. }
  835. /** Release all storage used by the directory server. */
  836. void
  837. dirserv_free_all(void)
  838. {
  839. strmap_free(cached_consensuses, free_cached_dir_);
  840. cached_consensuses = NULL;
  841. }