dirserv.c 31 KB

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