dirserv.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  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. const char *flavor_name,
  214. const common_digests_t *digests,
  215. const uint8_t *sha3_as_signed,
  216. time_t published)
  217. {
  218. cached_dir_t *new_networkstatus;
  219. cached_dir_t *old_networkstatus;
  220. if (!cached_consensuses)
  221. cached_consensuses = strmap_new();
  222. new_networkstatus = new_cached_dir(tor_strdup(networkstatus), published);
  223. memcpy(&new_networkstatus->digests, digests, sizeof(common_digests_t));
  224. memcpy(&new_networkstatus->digest_sha3_as_signed, sha3_as_signed,
  225. DIGEST256_LEN);
  226. old_networkstatus = strmap_set(cached_consensuses, flavor_name,
  227. new_networkstatus);
  228. if (old_networkstatus)
  229. cached_dir_decref(old_networkstatus);
  230. }
  231. /** Return the latest downloaded consensus networkstatus in encoded, signed,
  232. * optionally compressed format, suitable for sending to clients. */
  233. cached_dir_t *
  234. dirserv_get_consensus(const char *flavor_name)
  235. {
  236. if (!cached_consensuses)
  237. return NULL;
  238. return strmap_get(cached_consensuses, flavor_name);
  239. }
  240. /** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t
  241. * pointers, adds copies of digests to fps_out, and doesn't use the
  242. * /tor/server/ prefix. For a /d/ request, adds descriptor digests; for other
  243. * requests, adds identity digests.
  244. */
  245. int
  246. dirserv_get_routerdesc_spool(smartlist_t *spool_out,
  247. const char *key,
  248. dir_spool_source_t source,
  249. int conn_is_encrypted,
  250. const char **msg_out)
  251. {
  252. *msg_out = NULL;
  253. if (!strcmp(key, "all")) {
  254. const routerlist_t *rl = router_get_routerlist();
  255. SMARTLIST_FOREACH_BEGIN(rl->routers, const routerinfo_t *, r) {
  256. spooled_resource_t *spooled;
  257. spooled = spooled_resource_new(source,
  258. (const uint8_t *)r->cache_info.identity_digest,
  259. DIGEST_LEN);
  260. /* Treat "all" requests as if they were unencrypted */
  261. conn_is_encrypted = 0;
  262. smartlist_add(spool_out, spooled);
  263. } SMARTLIST_FOREACH_END(r);
  264. } else if (!strcmp(key, "authority")) {
  265. const routerinfo_t *ri = router_get_my_routerinfo();
  266. if (ri)
  267. smartlist_add(spool_out,
  268. spooled_resource_new(source,
  269. (const uint8_t *)ri->cache_info.identity_digest,
  270. DIGEST_LEN));
  271. } else if (!strcmpstart(key, "d/")) {
  272. key += strlen("d/");
  273. dir_split_resource_into_spoolable(key, source, spool_out, NULL,
  274. DSR_HEX|DSR_SORT_UNIQ);
  275. } else if (!strcmpstart(key, "fp/")) {
  276. key += strlen("fp/");
  277. dir_split_resource_into_spoolable(key, source, spool_out, NULL,
  278. DSR_HEX|DSR_SORT_UNIQ);
  279. } else {
  280. *msg_out = "Not found";
  281. return -1;
  282. }
  283. if (! conn_is_encrypted) {
  284. /* Remove anything that insists it not be sent unencrypted. */
  285. SMARTLIST_FOREACH_BEGIN(spool_out, spooled_resource_t *, spooled) {
  286. const uint8_t *body = NULL;
  287. size_t bodylen = 0;
  288. int r = spooled_resource_lookup_body(spooled, conn_is_encrypted,
  289. &body, &bodylen, NULL);
  290. if (r < 0 || body == NULL || bodylen == 0) {
  291. SMARTLIST_DEL_CURRENT(spool_out, spooled);
  292. spooled_resource_free(spooled);
  293. }
  294. } SMARTLIST_FOREACH_END(spooled);
  295. }
  296. if (!smartlist_len(spool_out)) {
  297. *msg_out = "Servers unavailable";
  298. return -1;
  299. }
  300. return 0;
  301. }
  302. /** Add a signed_descriptor_t to <b>descs_out</b> for each router matching
  303. * <b>key</b>. The key should be either
  304. * - "/tor/server/authority" for our own routerinfo;
  305. * - "/tor/server/all" for all the routerinfos we have, concatenated;
  306. * - "/tor/server/fp/FP" where FP is a plus-separated sequence of
  307. * hex identity digests; or
  308. * - "/tor/server/d/D" where D is a plus-separated sequence
  309. * of server descriptor digests, in hex.
  310. *
  311. * Return 0 if we found some matching descriptors, or -1 if we do not
  312. * have any descriptors, no matching descriptors, or if we did not
  313. * recognize the key (URL).
  314. * If -1 is returned *<b>msg</b> will be set to an appropriate error
  315. * message.
  316. *
  317. * XXXX rename this function. It's only called from the controller.
  318. * XXXX in fact, refactor this function, merging as much as possible.
  319. */
  320. int
  321. dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
  322. const char **msg)
  323. {
  324. *msg = NULL;
  325. if (!strcmp(key, "/tor/server/all")) {
  326. routerlist_t *rl = router_get_routerlist();
  327. SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
  328. smartlist_add(descs_out, &(r->cache_info)));
  329. } else if (!strcmp(key, "/tor/server/authority")) {
  330. const routerinfo_t *ri = router_get_my_routerinfo();
  331. if (ri)
  332. smartlist_add(descs_out, (void*) &(ri->cache_info));
  333. } else if (!strcmpstart(key, "/tor/server/d/")) {
  334. smartlist_t *digests = smartlist_new();
  335. key += strlen("/tor/server/d/");
  336. dir_split_resource_into_fingerprints(key, digests, NULL,
  337. DSR_HEX|DSR_SORT_UNIQ);
  338. SMARTLIST_FOREACH(digests, const char *, d,
  339. {
  340. signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
  341. if (sd)
  342. smartlist_add(descs_out,sd);
  343. });
  344. SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
  345. smartlist_free(digests);
  346. } else if (!strcmpstart(key, "/tor/server/fp/")) {
  347. smartlist_t *digests = smartlist_new();
  348. time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
  349. key += strlen("/tor/server/fp/");
  350. dir_split_resource_into_fingerprints(key, digests, NULL,
  351. DSR_HEX|DSR_SORT_UNIQ);
  352. SMARTLIST_FOREACH_BEGIN(digests, const char *, d) {
  353. if (router_digest_is_me(d)) {
  354. /* calling router_get_my_routerinfo() to make sure it exists */
  355. const routerinfo_t *ri = router_get_my_routerinfo();
  356. if (ri)
  357. smartlist_add(descs_out, (void*) &(ri->cache_info));
  358. } else {
  359. const routerinfo_t *ri = router_get_by_id_digest(d);
  360. /* Don't actually serve a descriptor that everyone will think is
  361. * expired. This is an (ugly) workaround to keep buggy 0.1.1.10
  362. * Tors from downloading descriptors that they will throw away.
  363. */
  364. if (ri && ri->cache_info.published_on > cutoff)
  365. smartlist_add(descs_out, (void*) &(ri->cache_info));
  366. }
  367. } SMARTLIST_FOREACH_END(d);
  368. SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
  369. smartlist_free(digests);
  370. } else {
  371. *msg = "Key not recognized";
  372. return -1;
  373. }
  374. if (!smartlist_len(descs_out)) {
  375. *msg = "Servers unavailable";
  376. return -1;
  377. }
  378. return 0;
  379. }
  380. /* ==========
  381. * Spooling code.
  382. * ========== */
  383. spooled_resource_t *
  384. spooled_resource_new(dir_spool_source_t source,
  385. const uint8_t *digest, size_t digestlen)
  386. {
  387. spooled_resource_t *spooled = tor_malloc_zero(sizeof(spooled_resource_t));
  388. spooled->spool_source = source;
  389. switch (source) {
  390. case DIR_SPOOL_NETWORKSTATUS:
  391. spooled->spool_eagerly = 0;
  392. break;
  393. case DIR_SPOOL_SERVER_BY_DIGEST:
  394. case DIR_SPOOL_SERVER_BY_FP:
  395. case DIR_SPOOL_EXTRA_BY_DIGEST:
  396. case DIR_SPOOL_EXTRA_BY_FP:
  397. case DIR_SPOOL_MICRODESC:
  398. default:
  399. spooled->spool_eagerly = 1;
  400. break;
  401. case DIR_SPOOL_CONSENSUS_CACHE_ENTRY:
  402. tor_assert_unreached();
  403. break;
  404. }
  405. tor_assert(digestlen <= sizeof(spooled->digest));
  406. if (digest)
  407. memcpy(spooled->digest, digest, digestlen);
  408. return spooled;
  409. }
  410. /**
  411. * Create a new spooled_resource_t to spool the contents of <b>entry</b> to
  412. * the user. Return the spooled object on success, or NULL on failure (which
  413. * is probably caused by a failure to map the body of the item from disk).
  414. *
  415. * Adds a reference to entry's reference counter.
  416. */
  417. spooled_resource_t *
  418. spooled_resource_new_from_cache_entry(consensus_cache_entry_t *entry)
  419. {
  420. spooled_resource_t *spooled = tor_malloc_zero(sizeof(spooled_resource_t));
  421. spooled->spool_source = DIR_SPOOL_CONSENSUS_CACHE_ENTRY;
  422. spooled->spool_eagerly = 0;
  423. consensus_cache_entry_incref(entry);
  424. spooled->consensus_cache_entry = entry;
  425. int r = consensus_cache_entry_get_body(entry,
  426. &spooled->cce_body,
  427. &spooled->cce_len);
  428. if (r == 0) {
  429. return spooled;
  430. } else {
  431. spooled_resource_free(spooled);
  432. return NULL;
  433. }
  434. }
  435. /** Release all storage held by <b>spooled</b>. */
  436. void
  437. spooled_resource_free_(spooled_resource_t *spooled)
  438. {
  439. if (spooled == NULL)
  440. return;
  441. if (spooled->cached_dir_ref) {
  442. cached_dir_decref(spooled->cached_dir_ref);
  443. }
  444. if (spooled->consensus_cache_entry) {
  445. consensus_cache_entry_decref(spooled->consensus_cache_entry);
  446. }
  447. tor_free(spooled);
  448. }
  449. /** When spooling data from a cached_dir_t object, we always add
  450. * at least this much. */
  451. #define DIRSERV_CACHED_DIR_CHUNK_SIZE 8192
  452. /** Return an compression ratio for compressing objects from <b>source</b>.
  453. */
  454. static double
  455. estimate_compression_ratio(dir_spool_source_t source)
  456. {
  457. /* We should put in better estimates here, depending on the number of
  458. objects and their type */
  459. (void) source;
  460. return 0.5;
  461. }
  462. /** Return an estimated number of bytes needed for transmitting the
  463. * resource in <b>spooled</b> on <b>conn</b>
  464. *
  465. * As a convenient side-effect, set *<b>published_out</b> to the resource's
  466. * publication time.
  467. */
  468. static size_t
  469. spooled_resource_estimate_size(const spooled_resource_t *spooled,
  470. dir_connection_t *conn,
  471. int compressed,
  472. time_t *published_out)
  473. {
  474. if (spooled->spool_eagerly) {
  475. const uint8_t *body = NULL;
  476. size_t bodylen = 0;
  477. int r = spooled_resource_lookup_body(spooled,
  478. connection_dir_is_encrypted(conn),
  479. &body, &bodylen,
  480. published_out);
  481. if (r == -1 || body == NULL || bodylen == 0)
  482. return 0;
  483. if (compressed) {
  484. double ratio = estimate_compression_ratio(spooled->spool_source);
  485. bodylen = (size_t)(bodylen * ratio);
  486. }
  487. return bodylen;
  488. } else {
  489. cached_dir_t *cached;
  490. if (spooled->consensus_cache_entry) {
  491. if (published_out) {
  492. consensus_cache_entry_get_valid_after(
  493. spooled->consensus_cache_entry, published_out);
  494. }
  495. return spooled->cce_len;
  496. }
  497. if (spooled->cached_dir_ref) {
  498. cached = spooled->cached_dir_ref;
  499. } else {
  500. cached = spooled_resource_lookup_cached_dir(spooled,
  501. published_out);
  502. }
  503. if (cached == NULL) {
  504. return 0;
  505. }
  506. size_t result = compressed ? cached->dir_compressed_len : cached->dir_len;
  507. return result;
  508. }
  509. }
  510. /** Return code for spooled_resource_flush_some */
  511. typedef enum {
  512. SRFS_ERR = -1,
  513. SRFS_MORE = 0,
  514. SRFS_DONE
  515. } spooled_resource_flush_status_t;
  516. /** Flush some or all of the bytes from <b>spooled</b> onto <b>conn</b>.
  517. * Return SRFS_ERR on error, SRFS_MORE if there are more bytes to flush from
  518. * this spooled resource, or SRFS_DONE if we are done flushing this spooled
  519. * resource.
  520. */
  521. static spooled_resource_flush_status_t
  522. spooled_resource_flush_some(spooled_resource_t *spooled,
  523. dir_connection_t *conn)
  524. {
  525. if (spooled->spool_eagerly) {
  526. /* Spool_eagerly resources are sent all-at-once. */
  527. const uint8_t *body = NULL;
  528. size_t bodylen = 0;
  529. int r = spooled_resource_lookup_body(spooled,
  530. connection_dir_is_encrypted(conn),
  531. &body, &bodylen, NULL);
  532. if (r == -1 || body == NULL || bodylen == 0) {
  533. /* Absent objects count as "done". */
  534. return SRFS_DONE;
  535. }
  536. if (conn->compress_state) {
  537. connection_buf_add_compress((const char*)body, bodylen, conn, 0);
  538. } else {
  539. connection_buf_add((const char*)body, bodylen, TO_CONN(conn));
  540. }
  541. return SRFS_DONE;
  542. } else {
  543. cached_dir_t *cached = spooled->cached_dir_ref;
  544. consensus_cache_entry_t *cce = spooled->consensus_cache_entry;
  545. if (cached == NULL && cce == NULL) {
  546. /* The cached_dir_t hasn't been materialized yet. So let's look it up. */
  547. cached = spooled->cached_dir_ref =
  548. spooled_resource_lookup_cached_dir(spooled, NULL);
  549. if (!cached) {
  550. /* Absent objects count as done. */
  551. return SRFS_DONE;
  552. }
  553. ++cached->refcnt;
  554. tor_assert_nonfatal(spooled->cached_dir_offset == 0);
  555. }
  556. if (BUG(!cached && !cce))
  557. return SRFS_DONE;
  558. int64_t total_len;
  559. const char *ptr;
  560. if (cached) {
  561. total_len = cached->dir_compressed_len;
  562. ptr = cached->dir_compressed;
  563. } else {
  564. total_len = spooled->cce_len;
  565. ptr = (const char *)spooled->cce_body;
  566. }
  567. /* How many bytes left to flush? */
  568. int64_t remaining;
  569. remaining = total_len - spooled->cached_dir_offset;
  570. if (BUG(remaining < 0))
  571. return SRFS_ERR;
  572. ssize_t bytes = (ssize_t) MIN(DIRSERV_CACHED_DIR_CHUNK_SIZE, remaining);
  573. if (conn->compress_state) {
  574. connection_buf_add_compress(
  575. ptr + spooled->cached_dir_offset,
  576. bytes, conn, 0);
  577. } else {
  578. connection_buf_add(ptr + spooled->cached_dir_offset,
  579. bytes, TO_CONN(conn));
  580. }
  581. spooled->cached_dir_offset += bytes;
  582. if (spooled->cached_dir_offset >= (off_t)total_len) {
  583. return SRFS_DONE;
  584. } else {
  585. return SRFS_MORE;
  586. }
  587. }
  588. }
  589. /** Helper: find the cached_dir_t for a spooled_resource_t, for
  590. * sending it to <b>conn</b>. Set *<b>published_out</b>, if provided,
  591. * to the published time of the cached_dir_t.
  592. *
  593. * DOES NOT increase the reference count on the result. Callers must do that
  594. * themselves if they mean to hang on to it.
  595. */
  596. static cached_dir_t *
  597. spooled_resource_lookup_cached_dir(const spooled_resource_t *spooled,
  598. time_t *published_out)
  599. {
  600. tor_assert(spooled->spool_eagerly == 0);
  601. cached_dir_t *d = lookup_cached_dir_by_fp(spooled->digest);
  602. if (d != NULL) {
  603. if (published_out)
  604. *published_out = d->published;
  605. }
  606. return d;
  607. }
  608. /** Helper: Look up the body for an eagerly-served spooled_resource. If
  609. * <b>conn_is_encrypted</b> is false, don't look up any resource that
  610. * shouldn't be sent over an unencrypted connection. On success, set
  611. * <b>body_out</b>, <b>size_out</b>, and <b>published_out</b> to refer
  612. * to the resource's body, size, and publication date, and return 0.
  613. * On failure return -1. */
  614. static int
  615. spooled_resource_lookup_body(const spooled_resource_t *spooled,
  616. int conn_is_encrypted,
  617. const uint8_t **body_out,
  618. size_t *size_out,
  619. time_t *published_out)
  620. {
  621. tor_assert(spooled->spool_eagerly == 1);
  622. const signed_descriptor_t *sd = NULL;
  623. switch (spooled->spool_source) {
  624. case DIR_SPOOL_EXTRA_BY_FP: {
  625. sd = get_signed_descriptor_by_fp(spooled->digest, 1);
  626. break;
  627. }
  628. case DIR_SPOOL_SERVER_BY_FP: {
  629. sd = get_signed_descriptor_by_fp(spooled->digest, 0);
  630. break;
  631. }
  632. case DIR_SPOOL_SERVER_BY_DIGEST: {
  633. sd = router_get_by_descriptor_digest((const char *)spooled->digest);
  634. break;
  635. }
  636. case DIR_SPOOL_EXTRA_BY_DIGEST: {
  637. sd = extrainfo_get_by_descriptor_digest((const char *)spooled->digest);
  638. break;
  639. }
  640. case DIR_SPOOL_MICRODESC: {
  641. microdesc_t *md = microdesc_cache_lookup_by_digest256(
  642. get_microdesc_cache(),
  643. (const char *)spooled->digest);
  644. if (! md || ! md->body) {
  645. return -1;
  646. }
  647. *body_out = (const uint8_t *)md->body;
  648. *size_out = md->bodylen;
  649. if (published_out)
  650. *published_out = TIME_MAX;
  651. return 0;
  652. }
  653. case DIR_SPOOL_NETWORKSTATUS:
  654. case DIR_SPOOL_CONSENSUS_CACHE_ENTRY:
  655. default:
  656. /* LCOV_EXCL_START */
  657. tor_assert_nonfatal_unreached();
  658. return -1;
  659. /* LCOV_EXCL_STOP */
  660. }
  661. /* If we get here, then we tried to set "sd" to a signed_descriptor_t. */
  662. if (sd == NULL) {
  663. return -1;
  664. }
  665. if (sd->send_unencrypted == 0 && ! conn_is_encrypted) {
  666. /* we did this check once before (so we could have an accurate size
  667. * estimate and maybe send a 404 if somebody asked for only bridges on
  668. * a connection), but we need to do it again in case a previously
  669. * unknown bridge descriptor has shown up between then and now. */
  670. return -1;
  671. }
  672. *body_out = (const uint8_t *) signed_descriptor_get_body(sd);
  673. *size_out = sd->signed_descriptor_len;
  674. if (published_out)
  675. *published_out = sd->published_on;
  676. return 0;
  677. }
  678. /** Given a fingerprint <b>fp</b> which is either set if we're looking for a
  679. * v2 status, or zeroes if we're looking for a v3 status, or a NUL-padded
  680. * flavor name if we want a flavored v3 status, return a pointer to the
  681. * appropriate cached dir object, or NULL if there isn't one available. */
  682. static cached_dir_t *
  683. lookup_cached_dir_by_fp(const uint8_t *fp)
  684. {
  685. cached_dir_t *d = NULL;
  686. if (tor_digest_is_zero((const char *)fp) && cached_consensuses) {
  687. d = strmap_get(cached_consensuses, "ns");
  688. } else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses) {
  689. /* this here interface is a nasty hack: we're shoving a flavor into
  690. * a digest field. */
  691. d = strmap_get(cached_consensuses, (const char *)fp);
  692. }
  693. return d;
  694. }
  695. /** Try to guess the number of bytes that will be needed to send the
  696. * spooled objects for <b>conn</b>'s outgoing spool. In the process,
  697. * remove every element of the spool that refers to an absent object, or
  698. * which was published earlier than <b>cutoff</b>. Set *<b>size_out</b>
  699. * to the number of bytes, and *<b>n_expired_out</b> to the number of
  700. * objects removed for being too old. */
  701. void
  702. dirserv_spool_remove_missing_and_guess_size(dir_connection_t *conn,
  703. time_t cutoff,
  704. int compression,
  705. size_t *size_out,
  706. int *n_expired_out)
  707. {
  708. if (BUG(!conn))
  709. return;
  710. smartlist_t *spool = conn->spool;
  711. if (!spool) {
  712. if (size_out)
  713. *size_out = 0;
  714. if (n_expired_out)
  715. *n_expired_out = 0;
  716. return;
  717. }
  718. int n_expired = 0;
  719. uint64_t total = 0;
  720. SMARTLIST_FOREACH_BEGIN(spool, spooled_resource_t *, spooled) {
  721. time_t published = TIME_MAX;
  722. size_t sz = spooled_resource_estimate_size(spooled, conn,
  723. compression, &published);
  724. if (published < cutoff) {
  725. ++n_expired;
  726. SMARTLIST_DEL_CURRENT(spool, spooled);
  727. spooled_resource_free(spooled);
  728. } else if (sz == 0) {
  729. SMARTLIST_DEL_CURRENT(spool, spooled);
  730. spooled_resource_free(spooled);
  731. } else {
  732. total += sz;
  733. }
  734. } SMARTLIST_FOREACH_END(spooled);
  735. if (size_out) {
  736. *size_out = (total > SIZE_MAX) ? SIZE_MAX : (size_t)total;
  737. }
  738. if (n_expired_out)
  739. *n_expired_out = n_expired;
  740. }
  741. /** Helper: used to sort a connection's spool. */
  742. static int
  743. dirserv_spool_sort_comparison_(const void **a_, const void **b_)
  744. {
  745. const spooled_resource_t *a = *a_;
  746. const spooled_resource_t *b = *b_;
  747. return fast_memcmp(a->digest, b->digest, sizeof(a->digest));
  748. }
  749. /** Sort all the entries in <b>conn</b> by digest. */
  750. void
  751. dirserv_spool_sort(dir_connection_t *conn)
  752. {
  753. if (conn->spool == NULL)
  754. return;
  755. smartlist_sort(conn->spool, dirserv_spool_sort_comparison_);
  756. }
  757. /** Return the cache-info for identity fingerprint <b>fp</b>, or
  758. * its extra-info document if <b>extrainfo</b> is true. Return
  759. * NULL if not found or if the descriptor is older than
  760. * <b>publish_cutoff</b>. */
  761. static const signed_descriptor_t *
  762. get_signed_descriptor_by_fp(const uint8_t *fp, int extrainfo)
  763. {
  764. if (router_digest_is_me((const char *)fp)) {
  765. if (extrainfo)
  766. return &(router_get_my_extrainfo()->cache_info);
  767. else
  768. return &(router_get_my_routerinfo()->cache_info);
  769. } else {
  770. const routerinfo_t *ri = router_get_by_id_digest((const char *)fp);
  771. if (ri) {
  772. if (extrainfo)
  773. return extrainfo_get_by_descriptor_digest(
  774. ri->cache_info.extra_info_digest);
  775. else
  776. return &ri->cache_info;
  777. }
  778. }
  779. return NULL;
  780. }
  781. /** When we're spooling data onto our outbuf, add more whenever we dip
  782. * below this threshold. */
  783. #define DIRSERV_BUFFER_MIN 16384
  784. /**
  785. * Called whenever we have flushed some directory data in state
  786. * SERVER_WRITING, or whenever we want to fill the buffer with initial
  787. * directory data (so that subsequent writes will occur, and trigger this
  788. * function again.)
  789. *
  790. * Return 0 on success, and -1 on failure.
  791. */
  792. int
  793. connection_dirserv_flushed_some(dir_connection_t *conn)
  794. {
  795. tor_assert(conn->base_.state == DIR_CONN_STATE_SERVER_WRITING);
  796. if (conn->spool == NULL)
  797. return 0;
  798. while (connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN &&
  799. smartlist_len(conn->spool)) {
  800. spooled_resource_t *spooled =
  801. smartlist_get(conn->spool, smartlist_len(conn->spool)-1);
  802. spooled_resource_flush_status_t status;
  803. status = spooled_resource_flush_some(spooled, conn);
  804. if (status == SRFS_ERR) {
  805. return -1;
  806. } else if (status == SRFS_MORE) {
  807. return 0;
  808. }
  809. tor_assert(status == SRFS_DONE);
  810. /* If we're here, we're done flushing this resource. */
  811. tor_assert(smartlist_pop_last(conn->spool) == spooled);
  812. spooled_resource_free(spooled);
  813. }
  814. if (smartlist_len(conn->spool) > 0) {
  815. /* We're still spooling something. */
  816. return 0;
  817. }
  818. /* If we get here, we're done. */
  819. smartlist_free(conn->spool);
  820. conn->spool = NULL;
  821. if (conn->compress_state) {
  822. /* Flush the compression state: there could be more bytes pending in there,
  823. * and we don't want to omit bytes. */
  824. connection_buf_add_compress("", 0, conn, 1);
  825. tor_compress_free(conn->compress_state);
  826. conn->compress_state = NULL;
  827. }
  828. return 0;
  829. }
  830. /** Remove every element from <b>conn</b>'s outgoing spool, and delete
  831. * the spool. */
  832. void
  833. dir_conn_clear_spool(dir_connection_t *conn)
  834. {
  835. if (!conn || ! conn->spool)
  836. return;
  837. SMARTLIST_FOREACH(conn->spool, spooled_resource_t *, s,
  838. spooled_resource_free(s));
  839. smartlist_free(conn->spool);
  840. conn->spool = NULL;
  841. }
  842. /** Release all storage used by the directory server. */
  843. void
  844. dirserv_free_all(void)
  845. {
  846. strmap_free(cached_consensuses, free_cached_dir_);
  847. cached_consensuses = NULL;
  848. }