dircache.c 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800
  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 DIRCACHE_PRIVATE
  6. #include "core/or/or.h"
  7. #include "app/config/config.h"
  8. #include "core/mainloop/connection.h"
  9. #include "core/or/relay.h"
  10. #include "feature/dirauth/dirvote.h"
  11. #include "feature/dirauth/authmode.h"
  12. #include "feature/dirauth/process_descs.h"
  13. #include "feature/dircache/conscache.h"
  14. #include "feature/dircache/consdiffmgr.h"
  15. #include "feature/dircache/dircache.h"
  16. #include "feature/dircache/dirserv.h"
  17. #include "feature/dircommon/directory.h"
  18. #include "feature/dircommon/fp_pair.h"
  19. #include "feature/hs/hs_cache.h"
  20. #include "feature/nodelist/authcert.h"
  21. #include "feature/nodelist/networkstatus.h"
  22. #include "feature/nodelist/routerlist.h"
  23. #include "feature/relay/routermode.h"
  24. #include "feature/rend/rendcache.h"
  25. #include "feature/stats/geoip_stats.h"
  26. #include "feature/stats/rephist.h"
  27. #include "lib/compress/compress.h"
  28. #include "feature/dircache/cached_dir_st.h"
  29. #include "feature/dircommon/dir_connection_st.h"
  30. #include "feature/nodelist/authority_cert_st.h"
  31. #include "feature/nodelist/networkstatus_st.h"
  32. #include "feature/nodelist/routerinfo_st.h"
  33. /** Maximum size, in bytes, for any directory object that we're accepting
  34. * as an upload. */
  35. #define MAX_DIR_UL_SIZE ((1<<24)-1) /* 16MB-1 */
  36. /** HTTP cache control: how long do we tell proxies they can cache each
  37. * kind of document we serve? */
  38. #define FULL_DIR_CACHE_LIFETIME (60*60)
  39. #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
  40. #define DIRPORTFRONTPAGE_CACHE_LIFETIME (20*60)
  41. #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
  42. #define ROUTERDESC_CACHE_LIFETIME (30*60)
  43. #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
  44. #define ROBOTS_CACHE_LIFETIME (24*60*60)
  45. #define MICRODESC_CACHE_LIFETIME (48*60*60)
  46. /* Bandwidth files change every hour. */
  47. #define BANDWIDTH_CACHE_LIFETIME (30*60)
  48. /** Parse an HTTP request string <b>headers</b> of the form
  49. * \verbatim
  50. * "\%s [http[s]://]\%s HTTP/1..."
  51. * \endverbatim
  52. * If it's well-formed, strdup the second \%s into *<b>url</b>, and
  53. * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
  54. * so it does. Return 0.
  55. * Otherwise, return -1.
  56. */
  57. STATIC int
  58. parse_http_url(const char *headers, char **url)
  59. {
  60. char *command = NULL;
  61. if (parse_http_command(headers, &command, url) < 0) {
  62. return -1;
  63. }
  64. if (strcmpstart(*url, "/tor/")) {
  65. char *new_url = NULL;
  66. tor_asprintf(&new_url, "/tor%s%s",
  67. *url[0] == '/' ? "" : "/",
  68. *url);
  69. tor_free(*url);
  70. *url = new_url;
  71. }
  72. tor_free(command);
  73. return 0;
  74. }
  75. /** Create an http response for the client <b>conn</b> out of
  76. * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
  77. */
  78. static void
  79. write_short_http_response(dir_connection_t *conn, int status,
  80. const char *reason_phrase)
  81. {
  82. char *buf = NULL;
  83. char *datestring = NULL;
  84. IF_BUG_ONCE(!reason_phrase) { /* bullet-proofing */
  85. reason_phrase = "unspecified";
  86. }
  87. if (server_mode(get_options())) {
  88. /* include the Date: header, but only if we're a relay or bridge */
  89. char datebuf[RFC1123_TIME_LEN+1];
  90. format_rfc1123_time(datebuf, time(NULL));
  91. tor_asprintf(&datestring, "Date: %s\r\n", datebuf);
  92. }
  93. tor_asprintf(&buf, "HTTP/1.0 %d %s\r\n%s\r\n",
  94. status, reason_phrase, datestring?datestring:"");
  95. log_debug(LD_DIRSERV,"Wrote status 'HTTP/1.0 %d %s'", status, reason_phrase);
  96. connection_buf_add(buf, strlen(buf), TO_CONN(conn));
  97. tor_free(datestring);
  98. tor_free(buf);
  99. }
  100. /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
  101. * with <b>type</b> as the Content-Type.
  102. *
  103. * If <b>length</b> is nonnegative, it is the Content-Length.
  104. * If <b>encoding</b> is provided, it is the Content-Encoding.
  105. * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
  106. * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
  107. static void
  108. write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
  109. const char *type, const char *encoding,
  110. const char *extra_headers,
  111. long cache_lifetime)
  112. {
  113. char date[RFC1123_TIME_LEN+1];
  114. time_t now = approx_time();
  115. buf_t *buf = buf_new_with_capacity(1024);
  116. tor_assert(conn);
  117. format_rfc1123_time(date, now);
  118. buf_add_printf(buf, "HTTP/1.0 200 OK\r\nDate: %s\r\n", date);
  119. if (type) {
  120. buf_add_printf(buf, "Content-Type: %s\r\n", type);
  121. }
  122. if (!is_local_addr(&conn->base_.addr)) {
  123. /* Don't report the source address for a nearby/private connection.
  124. * Otherwise we tend to mis-report in cases where incoming ports are
  125. * being forwarded to a Tor server running behind the firewall. */
  126. buf_add_printf(buf, X_ADDRESS_HEADER "%s\r\n", conn->base_.address);
  127. }
  128. if (encoding) {
  129. buf_add_printf(buf, "Content-Encoding: %s\r\n", encoding);
  130. }
  131. if (length >= 0) {
  132. buf_add_printf(buf, "Content-Length: %ld\r\n", (long)length);
  133. }
  134. if (cache_lifetime > 0) {
  135. char expbuf[RFC1123_TIME_LEN+1];
  136. format_rfc1123_time(expbuf, (time_t)(now + cache_lifetime));
  137. /* We could say 'Cache-control: max-age=%d' here if we start doing
  138. * http/1.1 */
  139. buf_add_printf(buf, "Expires: %s\r\n", expbuf);
  140. } else if (cache_lifetime == 0) {
  141. /* We could say 'Cache-control: no-cache' here if we start doing
  142. * http/1.1 */
  143. buf_add_string(buf, "Pragma: no-cache\r\n");
  144. }
  145. if (extra_headers) {
  146. buf_add_string(buf, extra_headers);
  147. }
  148. buf_add_string(buf, "\r\n");
  149. connection_buf_add_buf(TO_CONN(conn), buf);
  150. buf_free(buf);
  151. }
  152. /** As write_http_response_header_impl, but translates method into
  153. * encoding */
  154. static void
  155. write_http_response_headers(dir_connection_t *conn, ssize_t length,
  156. compress_method_t method,
  157. const char *extra_headers, long cache_lifetime)
  158. {
  159. write_http_response_header_impl(conn, length,
  160. "text/plain",
  161. compression_method_get_name(method),
  162. extra_headers,
  163. cache_lifetime);
  164. }
  165. /** As write_http_response_headers, but assumes extra_headers is NULL */
  166. static void
  167. write_http_response_header(dir_connection_t *conn, ssize_t length,
  168. compress_method_t method,
  169. long cache_lifetime)
  170. {
  171. write_http_response_headers(conn, length, method, NULL, cache_lifetime);
  172. }
  173. /** Array of compression methods to use (if supported) for serving
  174. * precompressed data, ordered from best to worst. */
  175. static compress_method_t srv_meth_pref_precompressed[] = {
  176. LZMA_METHOD,
  177. ZSTD_METHOD,
  178. ZLIB_METHOD,
  179. GZIP_METHOD,
  180. NO_METHOD
  181. };
  182. /** Array of compression methods to use (if supported) for serving
  183. * streamed data, ordered from best to worst. */
  184. static compress_method_t srv_meth_pref_streaming_compression[] = {
  185. ZSTD_METHOD,
  186. ZLIB_METHOD,
  187. GZIP_METHOD,
  188. NO_METHOD
  189. };
  190. /** Parse the compression methods listed in an Accept-Encoding header <b>h</b>,
  191. * and convert them to a bitfield where compression method x is supported if
  192. * and only if 1 &lt;&lt; x is set in the bitfield. */
  193. STATIC unsigned
  194. parse_accept_encoding_header(const char *h)
  195. {
  196. unsigned result = (1u << NO_METHOD);
  197. smartlist_t *methods = smartlist_new();
  198. smartlist_split_string(methods, h, ",",
  199. SPLIT_SKIP_SPACE|SPLIT_STRIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  200. SMARTLIST_FOREACH_BEGIN(methods, const char *, m) {
  201. compress_method_t method = compression_method_get_by_name(m);
  202. if (method != UNKNOWN_METHOD) {
  203. tor_assert(((unsigned)method) < 8*sizeof(unsigned));
  204. result |= (1u << method);
  205. }
  206. } SMARTLIST_FOREACH_END(m);
  207. SMARTLIST_FOREACH_BEGIN(methods, char *, m) {
  208. tor_free(m);
  209. } SMARTLIST_FOREACH_END(m);
  210. smartlist_free(methods);
  211. return result;
  212. }
  213. /** Decide whether a client would accept the consensus we have.
  214. *
  215. * Clients can say they only want a consensus if it's signed by more
  216. * than half the authorities in a list. They pass this list in
  217. * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
  218. *
  219. * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
  220. * of the full authority identity digest. (Only strings of even length,
  221. * i.e. encodings of full bytes, are handled correctly. In the case
  222. * of an odd number of hex digits the last one is silently ignored.)
  223. *
  224. * Returns 1 if more than half of the requested authorities signed the
  225. * consensus, 0 otherwise.
  226. */
  227. static int
  228. client_likes_consensus(const struct consensus_cache_entry_t *ent,
  229. const char *want_url)
  230. {
  231. smartlist_t *voters = smartlist_new();
  232. int need_at_least;
  233. int have = 0;
  234. if (consensus_cache_entry_get_voter_id_digests(ent, voters) != 0) {
  235. smartlist_free(voters);
  236. return 1; // We don't know the voters; assume the client won't mind. */
  237. }
  238. smartlist_t *want_authorities = smartlist_new();
  239. dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0);
  240. need_at_least = smartlist_len(want_authorities)/2+1;
  241. SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, want_digest) {
  242. SMARTLIST_FOREACH_BEGIN(voters, const char *, digest) {
  243. if (!strcasecmpstart(digest, want_digest)) {
  244. have++;
  245. break;
  246. };
  247. } SMARTLIST_FOREACH_END(digest);
  248. /* early exit, if we already have enough */
  249. if (have >= need_at_least)
  250. break;
  251. } SMARTLIST_FOREACH_END(want_digest);
  252. SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
  253. smartlist_free(want_authorities);
  254. SMARTLIST_FOREACH(voters, char *, cp, tor_free(cp));
  255. smartlist_free(voters);
  256. return (have >= need_at_least);
  257. }
  258. /** Return the compression level we should use for sending a compressed
  259. * response of size <b>n_bytes</b>. */
  260. STATIC compression_level_t
  261. choose_compression_level(ssize_t n_bytes)
  262. {
  263. if (! have_been_under_memory_pressure()) {
  264. return HIGH_COMPRESSION; /* we have plenty of RAM. */
  265. } else if (n_bytes < 0) {
  266. return HIGH_COMPRESSION; /* unknown; might be big. */
  267. } else if (n_bytes < 1024) {
  268. return LOW_COMPRESSION;
  269. } else if (n_bytes < 2048) {
  270. return MEDIUM_COMPRESSION;
  271. } else {
  272. return HIGH_COMPRESSION;
  273. }
  274. }
  275. /** Information passed to handle a GET request. */
  276. typedef struct get_handler_args_t {
  277. /** Bitmask of compression methods that the client said (or implied) it
  278. * supported. */
  279. unsigned compression_supported;
  280. /** If nonzero, the time included an if-modified-since header with this
  281. * value. */
  282. time_t if_modified_since;
  283. /** String containing the requested URL or resource. */
  284. const char *url;
  285. /** String containing the HTTP headers */
  286. const char *headers;
  287. } get_handler_args_t;
  288. /** Entry for handling an HTTP GET request.
  289. *
  290. * This entry matches a request if "string" is equal to the requested
  291. * resource, or if "is_prefix" is true and "string" is a prefix of the
  292. * requested resource.
  293. *
  294. * The 'handler' function is called to handle the request. It receives
  295. * an arguments structure, and must return 0 on success or -1 if we should
  296. * close the connection.
  297. **/
  298. typedef struct url_table_ent_s {
  299. const char *string;
  300. int is_prefix;
  301. int (*handler)(dir_connection_t *conn, const get_handler_args_t *args);
  302. } url_table_ent_t;
  303. static int handle_get_frontpage(dir_connection_t *conn,
  304. const get_handler_args_t *args);
  305. static int handle_get_current_consensus(dir_connection_t *conn,
  306. const get_handler_args_t *args);
  307. static int handle_get_status_vote(dir_connection_t *conn,
  308. const get_handler_args_t *args);
  309. static int handle_get_microdesc(dir_connection_t *conn,
  310. const get_handler_args_t *args);
  311. static int handle_get_descriptor(dir_connection_t *conn,
  312. const get_handler_args_t *args);
  313. static int handle_get_keys(dir_connection_t *conn,
  314. const get_handler_args_t *args);
  315. static int handle_get_hs_descriptor_v2(dir_connection_t *conn,
  316. const get_handler_args_t *args);
  317. static int handle_get_robots(dir_connection_t *conn,
  318. const get_handler_args_t *args);
  319. static int handle_get_networkstatus_bridges(dir_connection_t *conn,
  320. const get_handler_args_t *args);
  321. static int handle_get_next_bandwidth(dir_connection_t *conn,
  322. const get_handler_args_t *args);
  323. /** Table for handling GET requests. */
  324. static const url_table_ent_t url_table[] = {
  325. { "/tor/", 0, handle_get_frontpage },
  326. { "/tor/status-vote/current/consensus", 1, handle_get_current_consensus },
  327. { "/tor/status-vote/current/", 1, handle_get_status_vote },
  328. { "/tor/status-vote/next/bandwidth", 0, handle_get_next_bandwidth },
  329. { "/tor/status-vote/next/", 1, handle_get_status_vote },
  330. { "/tor/micro/d/", 1, handle_get_microdesc },
  331. { "/tor/server/", 1, handle_get_descriptor },
  332. { "/tor/extra/", 1, handle_get_descriptor },
  333. { "/tor/keys/", 1, handle_get_keys },
  334. { "/tor/rendezvous2/", 1, handle_get_hs_descriptor_v2 },
  335. { "/tor/hs/3/", 1, handle_get_hs_descriptor_v3 },
  336. { "/tor/robots.txt", 0, handle_get_robots },
  337. { "/tor/networkstatus-bridges", 0, handle_get_networkstatus_bridges },
  338. { NULL, 0, NULL },
  339. };
  340. /** Helper function: called when a dirserver gets a complete HTTP GET
  341. * request. Look for a request for a directory or for a rendezvous
  342. * service descriptor. On finding one, write a response into
  343. * conn-\>outbuf. If the request is unrecognized, send a 404.
  344. * Return 0 if we handled this successfully, or -1 if we need to close
  345. * the connection. */
  346. MOCK_IMPL(STATIC int,
  347. directory_handle_command_get,(dir_connection_t *conn, const char *headers,
  348. const char *req_body, size_t req_body_len))
  349. {
  350. char *url, *url_mem, *header;
  351. time_t if_modified_since = 0;
  352. int zlib_compressed_in_url;
  353. unsigned compression_methods_supported;
  354. /* We ignore the body of a GET request. */
  355. (void)req_body;
  356. (void)req_body_len;
  357. log_debug(LD_DIRSERV,"Received GET command.");
  358. conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
  359. if (parse_http_url(headers, &url) < 0) {
  360. write_short_http_response(conn, 400, "Bad request");
  361. return 0;
  362. }
  363. if ((header = http_get_header(headers, "If-Modified-Since: "))) {
  364. struct tm tm;
  365. if (parse_http_time(header, &tm) == 0) {
  366. if (tor_timegm(&tm, &if_modified_since)<0) {
  367. if_modified_since = 0;
  368. } else {
  369. log_debug(LD_DIRSERV, "If-Modified-Since is '%s'.", escaped(header));
  370. }
  371. }
  372. /* The correct behavior on a malformed If-Modified-Since header is to
  373. * act as if no If-Modified-Since header had been given. */
  374. tor_free(header);
  375. }
  376. log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
  377. url_mem = url;
  378. {
  379. size_t url_len = strlen(url);
  380. zlib_compressed_in_url = url_len > 2 && !strcmp(url+url_len-2, ".z");
  381. if (zlib_compressed_in_url) {
  382. url[url_len-2] = '\0';
  383. }
  384. }
  385. if ((header = http_get_header(headers, "Accept-Encoding: "))) {
  386. compression_methods_supported = parse_accept_encoding_header(header);
  387. tor_free(header);
  388. } else {
  389. compression_methods_supported = (1u << NO_METHOD);
  390. }
  391. if (zlib_compressed_in_url) {
  392. compression_methods_supported |= (1u << ZLIB_METHOD);
  393. }
  394. /* Remove all methods that we don't both support. */
  395. compression_methods_supported &= tor_compress_get_supported_method_bitmask();
  396. get_handler_args_t args;
  397. args.url = url;
  398. args.headers = headers;
  399. args.if_modified_since = if_modified_since;
  400. args.compression_supported = compression_methods_supported;
  401. int i, result = -1;
  402. for (i = 0; url_table[i].string; ++i) {
  403. int match;
  404. if (url_table[i].is_prefix) {
  405. match = !strcmpstart(url, url_table[i].string);
  406. } else {
  407. match = !strcmp(url, url_table[i].string);
  408. }
  409. if (match) {
  410. result = url_table[i].handler(conn, &args);
  411. goto done;
  412. }
  413. }
  414. /* we didn't recognize the url */
  415. write_short_http_response(conn, 404, "Not found");
  416. result = 0;
  417. done:
  418. tor_free(url_mem);
  419. return result;
  420. }
  421. /** Helper function for GET / or GET /tor/
  422. */
  423. static int
  424. handle_get_frontpage(dir_connection_t *conn, const get_handler_args_t *args)
  425. {
  426. (void) args; /* unused */
  427. const char *frontpage = get_dirportfrontpage();
  428. if (frontpage) {
  429. size_t dlen;
  430. dlen = strlen(frontpage);
  431. /* Let's return a disclaimer page (users shouldn't use V1 anymore,
  432. and caches don't fetch '/', so this is safe). */
  433. /* [We don't check for write_bucket_low here, since we want to serve
  434. * this page no matter what.] */
  435. write_http_response_header_impl(conn, dlen, "text/html", "identity",
  436. NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
  437. connection_buf_add(frontpage, dlen, TO_CONN(conn));
  438. } else {
  439. write_short_http_response(conn, 404, "Not found");
  440. }
  441. return 0;
  442. }
  443. /** Warn that the cached consensus <b>consensus</b> of type
  444. * <b>flavor</b> too new or too old, based on <b>is_too_new</b>,
  445. * and will not be served to clients. Rate-limit the warning to avoid logging
  446. * an entry on every request.
  447. */
  448. static void
  449. warn_consensus_is_not_reasonably_live(
  450. const struct consensus_cache_entry_t *consensus,
  451. const char *flavor, time_t now, bool is_too_new)
  452. {
  453. #define NOT_REASONABLY_LIVE_WARNING_INTERVAL (60*60)
  454. static ratelim_t warned[2] = { RATELIM_INIT(
  455. NOT_REASONABLY_LIVE_WARNING_INTERVAL),
  456. RATELIM_INIT(
  457. NOT_REASONABLY_LIVE_WARNING_INTERVAL) };
  458. char timestamp[ISO_TIME_LEN+1];
  459. /* valid_after if is_too_new, valid_until if !is_too_new */
  460. time_t valid_time = 0;
  461. char *dupes = NULL;
  462. if (is_too_new) {
  463. if (consensus_cache_entry_get_valid_after(consensus, &valid_time))
  464. return;
  465. dupes = rate_limit_log(&warned[1], now);
  466. } else {
  467. if (consensus_cache_entry_get_valid_until(consensus, &valid_time))
  468. return;
  469. dupes = rate_limit_log(&warned[0], now);
  470. }
  471. if (dupes) {
  472. format_local_iso_time(timestamp, valid_time);
  473. log_warn(LD_DIRSERV, "Our %s%sconsensus is too %s, so we will not "
  474. "serve it to clients. It was valid %s %s local time and we "
  475. "continued to serve it for up to 24 hours %s.%s",
  476. flavor ? flavor : "",
  477. flavor ? " " : "",
  478. is_too_new ? "new" : "old",
  479. is_too_new ? "after" : "until",
  480. timestamp,
  481. is_too_new ? "before it was valid" : "after it expired",
  482. dupes);
  483. tor_free(dupes);
  484. }
  485. }
  486. /**
  487. * Parse a single hex-encoded sha3-256 digest from <b>hex</b> into
  488. * <b>digest</b>. Return 0 on success. On failure, report that the hash came
  489. * from <b>location</b>, report that we are taking <b>action</b> with it, and
  490. * return -1.
  491. */
  492. static int
  493. parse_one_diff_hash(uint8_t *digest, const char *hex, const char *location,
  494. const char *action)
  495. {
  496. if (base16_decode((char*)digest, DIGEST256_LEN, hex, strlen(hex)) ==
  497. DIGEST256_LEN) {
  498. return 0;
  499. } else {
  500. log_fn(LOG_PROTOCOL_WARN, LD_DIR,
  501. "%s contained bogus digest %s; %s.",
  502. location, escaped(hex), action);
  503. return -1;
  504. }
  505. }
  506. /** If there is an X-Or-Diff-From-Consensus header included in <b>headers</b>,
  507. * set <b>digest_out<b> to a new smartlist containing every 256-bit
  508. * hex-encoded digest listed in that header and return 0. Otherwise return
  509. * -1. */
  510. static int
  511. parse_or_diff_from_header(smartlist_t **digests_out, const char *headers)
  512. {
  513. char *hdr = http_get_header(headers, X_OR_DIFF_FROM_CONSENSUS_HEADER);
  514. if (hdr == NULL) {
  515. return -1;
  516. }
  517. smartlist_t *hex_digests = smartlist_new();
  518. *digests_out = smartlist_new();
  519. smartlist_split_string(hex_digests, hdr, " ",
  520. SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
  521. SMARTLIST_FOREACH_BEGIN(hex_digests, const char *, hex) {
  522. uint8_t digest[DIGEST256_LEN];
  523. if (!parse_one_diff_hash(digest, hex, "X-Or-Diff-From-Consensus header",
  524. "ignoring")) {
  525. smartlist_add(*digests_out, tor_memdup(digest, sizeof(digest)));
  526. }
  527. } SMARTLIST_FOREACH_END(hex);
  528. SMARTLIST_FOREACH(hex_digests, char *, cp, tor_free(cp));
  529. smartlist_free(hex_digests);
  530. tor_free(hdr);
  531. return 0;
  532. }
  533. /** Fallback compression method. The fallback compression method is used in
  534. * case a client requests a non-compressed document. We only store compressed
  535. * documents, so we use this compression method to fetch the document and let
  536. * the spooling system do the streaming decompression.
  537. */
  538. #define FALLBACK_COMPRESS_METHOD ZLIB_METHOD
  539. /**
  540. * Try to find the best consensus diff possible in order to serve a client
  541. * request for a diff from one of the consensuses in <b>digests</b> to the
  542. * current consensus of flavor <b>flav</b>. The client supports the
  543. * compression methods listed in the <b>compression_methods</b> bitfield:
  544. * place the method chosen (if any) into <b>compression_used_out</b>.
  545. */
  546. static struct consensus_cache_entry_t *
  547. find_best_diff(const smartlist_t *digests, int flav,
  548. unsigned compression_methods,
  549. compress_method_t *compression_used_out)
  550. {
  551. struct consensus_cache_entry_t *result = NULL;
  552. SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, diff_from) {
  553. unsigned u;
  554. for (u = 0; u < ARRAY_LENGTH(srv_meth_pref_precompressed); ++u) {
  555. compress_method_t method = srv_meth_pref_precompressed[u];
  556. if (0 == (compression_methods & (1u<<method)))
  557. continue; // client doesn't like this one, or we don't have it.
  558. if (consdiffmgr_find_diff_from(&result, flav, DIGEST_SHA3_256,
  559. diff_from, DIGEST256_LEN,
  560. method) == CONSDIFF_AVAILABLE) {
  561. tor_assert_nonfatal(result);
  562. *compression_used_out = method;
  563. return result;
  564. }
  565. }
  566. } SMARTLIST_FOREACH_END(diff_from);
  567. SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, diff_from) {
  568. if (consdiffmgr_find_diff_from(&result, flav, DIGEST_SHA3_256, diff_from,
  569. DIGEST256_LEN, FALLBACK_COMPRESS_METHOD) == CONSDIFF_AVAILABLE) {
  570. tor_assert_nonfatal(result);
  571. *compression_used_out = FALLBACK_COMPRESS_METHOD;
  572. return result;
  573. }
  574. } SMARTLIST_FOREACH_END(diff_from);
  575. return NULL;
  576. }
  577. /** Lookup the cached consensus document by the flavor found in <b>flav</b>.
  578. * The preferred set of compression methods should be listed in the
  579. * <b>compression_methods</b> bitfield. The compression method chosen (if any)
  580. * is stored in <b>compression_used_out</b>. */
  581. static struct consensus_cache_entry_t *
  582. find_best_consensus(int flav,
  583. unsigned compression_methods,
  584. compress_method_t *compression_used_out)
  585. {
  586. struct consensus_cache_entry_t *result = NULL;
  587. unsigned u;
  588. for (u = 0; u < ARRAY_LENGTH(srv_meth_pref_precompressed); ++u) {
  589. compress_method_t method = srv_meth_pref_precompressed[u];
  590. if (0 == (compression_methods & (1u<<method)))
  591. continue;
  592. if (consdiffmgr_find_consensus(&result, flav,
  593. method) == CONSDIFF_AVAILABLE) {
  594. tor_assert_nonfatal(result);
  595. *compression_used_out = method;
  596. return result;
  597. }
  598. }
  599. if (consdiffmgr_find_consensus(&result, flav,
  600. FALLBACK_COMPRESS_METHOD) == CONSDIFF_AVAILABLE) {
  601. tor_assert_nonfatal(result);
  602. *compression_used_out = FALLBACK_COMPRESS_METHOD;
  603. return result;
  604. }
  605. return NULL;
  606. }
  607. /** Try to find the best supported compression method possible from a given
  608. * <b>compression_methods</b>. Return NO_METHOD if no mutually supported
  609. * compression method could be found. */
  610. static compress_method_t
  611. find_best_compression_method(unsigned compression_methods, int stream)
  612. {
  613. unsigned u;
  614. compress_method_t *methods;
  615. size_t length;
  616. if (stream) {
  617. methods = srv_meth_pref_streaming_compression;
  618. length = ARRAY_LENGTH(srv_meth_pref_streaming_compression);
  619. } else {
  620. methods = srv_meth_pref_precompressed;
  621. length = ARRAY_LENGTH(srv_meth_pref_precompressed);
  622. }
  623. for (u = 0; u < length; ++u) {
  624. compress_method_t method = methods[u];
  625. if (compression_methods & (1u<<method))
  626. return method;
  627. }
  628. return NO_METHOD;
  629. }
  630. /** Check if any of the digests in <b>digests</b> matches the latest consensus
  631. * flavor (given in <b>flavor</b>) that we have available. */
  632. static int
  633. digest_list_contains_best_consensus(consensus_flavor_t flavor,
  634. const smartlist_t *digests)
  635. {
  636. const networkstatus_t *ns = NULL;
  637. if (digests == NULL)
  638. return 0;
  639. ns = networkstatus_get_latest_consensus_by_flavor(flavor);
  640. if (ns == NULL)
  641. return 0;
  642. SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, digest) {
  643. if (tor_memeq(ns->digest_sha3_as_signed, digest, DIGEST256_LEN))
  644. return 1;
  645. } SMARTLIST_FOREACH_END(digest);
  646. return 0;
  647. }
  648. /** Encodes the results of parsing a consensus request to figure out what
  649. * consensus, and possibly what diffs, the user asked for. */
  650. typedef struct {
  651. /** name of the flavor to retrieve. */
  652. char *flavor;
  653. /** flavor to retrive, as enum. */
  654. consensus_flavor_t flav;
  655. /** plus-separated list of authority fingerprints; see
  656. * client_likes_consensus(). Aliases the URL in the request passed to
  657. * parse_consensus_request(). */
  658. const char *want_fps;
  659. /** Optionally, a smartlist of sha3 digests-as-signed of the consensuses
  660. * to return a diff from. */
  661. smartlist_t *diff_from_digests;
  662. /** If true, never send a full consensus. If there is no diff, send
  663. * a 404 instead. */
  664. int diff_only;
  665. } parsed_consensus_request_t;
  666. /** Remove all data held in <b>req</b>. Do not free <b>req</b> itself, since
  667. * it is stack-allocated. */
  668. static void
  669. parsed_consensus_request_clear(parsed_consensus_request_t *req)
  670. {
  671. if (!req)
  672. return;
  673. tor_free(req->flavor);
  674. if (req->diff_from_digests) {
  675. SMARTLIST_FOREACH(req->diff_from_digests, uint8_t *, d, tor_free(d));
  676. smartlist_free(req->diff_from_digests);
  677. }
  678. memset(req, 0, sizeof(parsed_consensus_request_t));
  679. }
  680. /**
  681. * Parse the URL and relevant headers of <b>args</b> for a current-consensus
  682. * request to learn what flavor of consensus we want, what keys it must be
  683. * signed with, and what diffs we would accept (or demand) instead. Return 0
  684. * on success and -1 on failure.
  685. */
  686. static int
  687. parse_consensus_request(parsed_consensus_request_t *out,
  688. const get_handler_args_t *args)
  689. {
  690. const char *url = args->url;
  691. memset(out, 0, sizeof(parsed_consensus_request_t));
  692. out->flav = FLAV_NS;
  693. const char CONSENSUS_URL_PREFIX[] = "/tor/status-vote/current/consensus/";
  694. const char CONSENSUS_FLAVORED_PREFIX[] =
  695. "/tor/status-vote/current/consensus-";
  696. /* figure out the flavor if any, and who we wanted to sign the thing */
  697. const char *after_flavor = NULL;
  698. if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) {
  699. const char *f, *cp;
  700. f = url + strlen(CONSENSUS_FLAVORED_PREFIX);
  701. cp = strchr(f, '/');
  702. if (cp) {
  703. after_flavor = cp+1;
  704. out->flavor = tor_strndup(f, cp-f);
  705. } else {
  706. out->flavor = tor_strdup(f);
  707. }
  708. int flav = networkstatus_parse_flavor_name(out->flavor);
  709. if (flav < 0)
  710. flav = FLAV_NS;
  711. out->flav = flav;
  712. } else {
  713. if (!strcmpstart(url, CONSENSUS_URL_PREFIX))
  714. after_flavor = url+strlen(CONSENSUS_URL_PREFIX);
  715. }
  716. /* see whether we've been asked explicitly for a diff from an older
  717. * consensus. (The user might also have said that a diff would be okay,
  718. * via X-Or-Diff-From-Consensus */
  719. const char DIFF_COMPONENT[] = "diff/";
  720. char *diff_hash_in_url = NULL;
  721. if (after_flavor && !strcmpstart(after_flavor, DIFF_COMPONENT)) {
  722. after_flavor += strlen(DIFF_COMPONENT);
  723. const char *cp = strchr(after_flavor, '/');
  724. if (cp) {
  725. diff_hash_in_url = tor_strndup(after_flavor, cp-after_flavor);
  726. out->want_fps = cp+1;
  727. } else {
  728. diff_hash_in_url = tor_strdup(after_flavor);
  729. out->want_fps = NULL;
  730. }
  731. } else {
  732. out->want_fps = after_flavor;
  733. }
  734. if (diff_hash_in_url) {
  735. uint8_t diff_from[DIGEST256_LEN];
  736. out->diff_from_digests = smartlist_new();
  737. out->diff_only = 1;
  738. int ok = !parse_one_diff_hash(diff_from, diff_hash_in_url, "URL",
  739. "rejecting");
  740. tor_free(diff_hash_in_url);
  741. if (ok) {
  742. smartlist_add(out->diff_from_digests,
  743. tor_memdup(diff_from, DIGEST256_LEN));
  744. } else {
  745. return -1;
  746. }
  747. } else {
  748. parse_or_diff_from_header(&out->diff_from_digests, args->headers);
  749. }
  750. return 0;
  751. }
  752. /** Helper function for GET /tor/status-vote/current/consensus
  753. */
  754. static int
  755. handle_get_current_consensus(dir_connection_t *conn,
  756. const get_handler_args_t *args)
  757. {
  758. const compress_method_t compress_method =
  759. find_best_compression_method(args->compression_supported, 0);
  760. const time_t if_modified_since = args->if_modified_since;
  761. int clear_spool = 0;
  762. /* v3 network status fetch. */
  763. long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
  764. time_t now = time(NULL);
  765. parsed_consensus_request_t req;
  766. if (parse_consensus_request(&req, args) < 0) {
  767. write_short_http_response(conn, 404, "Couldn't parse request");
  768. goto done;
  769. }
  770. if (digest_list_contains_best_consensus(req.flav,
  771. req.diff_from_digests)) {
  772. write_short_http_response(conn, 304, "Not modified");
  773. geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
  774. goto done;
  775. }
  776. struct consensus_cache_entry_t *cached_consensus = NULL;
  777. compress_method_t compression_used = NO_METHOD;
  778. if (req.diff_from_digests) {
  779. cached_consensus = find_best_diff(req.diff_from_digests, req.flav,
  780. args->compression_supported,
  781. &compression_used);
  782. }
  783. if (req.diff_only && !cached_consensus) {
  784. write_short_http_response(conn, 404, "No such diff available");
  785. geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
  786. goto done;
  787. }
  788. if (! cached_consensus) {
  789. cached_consensus = find_best_consensus(req.flav,
  790. args->compression_supported,
  791. &compression_used);
  792. }
  793. time_t valid_after, fresh_until, valid_until;
  794. int have_valid_after = 0, have_fresh_until = 0, have_valid_until = 0;
  795. if (cached_consensus) {
  796. have_valid_after =
  797. !consensus_cache_entry_get_valid_after(cached_consensus, &valid_after);
  798. have_fresh_until =
  799. !consensus_cache_entry_get_fresh_until(cached_consensus, &fresh_until);
  800. have_valid_until =
  801. !consensus_cache_entry_get_valid_until(cached_consensus, &valid_until);
  802. }
  803. if (cached_consensus && have_valid_after &&
  804. !networkstatus_valid_after_is_reasonably_live(valid_after, now)) {
  805. write_short_http_response(conn, 404, "Consensus is too new");
  806. warn_consensus_is_not_reasonably_live(cached_consensus, req.flavor, now,
  807. 1);
  808. geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
  809. goto done;
  810. } else if (
  811. cached_consensus && have_valid_until &&
  812. !networkstatus_valid_until_is_reasonably_live(valid_until, now)) {
  813. write_short_http_response(conn, 404, "Consensus is too old");
  814. warn_consensus_is_not_reasonably_live(cached_consensus, req.flavor, now,
  815. 0);
  816. geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
  817. goto done;
  818. }
  819. if (cached_consensus && req.want_fps &&
  820. !client_likes_consensus(cached_consensus, req.want_fps)) {
  821. write_short_http_response(conn, 404, "Consensus not signed by sufficient "
  822. "number of requested authorities");
  823. geoip_note_ns_response(GEOIP_REJECT_NOT_ENOUGH_SIGS);
  824. goto done;
  825. }
  826. conn->spool = smartlist_new();
  827. clear_spool = 1;
  828. {
  829. spooled_resource_t *spooled;
  830. if (cached_consensus) {
  831. spooled = spooled_resource_new_from_cache_entry(cached_consensus);
  832. smartlist_add(conn->spool, spooled);
  833. }
  834. }
  835. lifetime = (have_fresh_until && fresh_until > now) ? fresh_until - now : 0;
  836. size_t size_guess = 0;
  837. int n_expired = 0;
  838. dirserv_spool_remove_missing_and_guess_size(conn, if_modified_since,
  839. compress_method != NO_METHOD,
  840. &size_guess,
  841. &n_expired);
  842. if (!smartlist_len(conn->spool) && !n_expired) {
  843. write_short_http_response(conn, 404, "Not found");
  844. geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
  845. goto done;
  846. } else if (!smartlist_len(conn->spool)) {
  847. write_short_http_response(conn, 304, "Not modified");
  848. geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
  849. goto done;
  850. }
  851. if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
  852. log_debug(LD_DIRSERV,
  853. "Client asked for network status lists, but we've been "
  854. "writing too many bytes lately. Sending 503 Dir busy.");
  855. write_short_http_response(conn, 503, "Directory busy, try again later");
  856. geoip_note_ns_response(GEOIP_REJECT_BUSY);
  857. goto done;
  858. }
  859. tor_addr_t addr;
  860. if (tor_addr_parse(&addr, (TO_CONN(conn))->address) >= 0) {
  861. geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS,
  862. &addr, NULL,
  863. time(NULL));
  864. geoip_note_ns_response(GEOIP_SUCCESS);
  865. /* Note that a request for a network status has started, so that we
  866. * can measure the download time later on. */
  867. if (conn->dirreq_id)
  868. geoip_start_dirreq(conn->dirreq_id, size_guess, DIRREQ_TUNNELED);
  869. else
  870. geoip_start_dirreq(TO_CONN(conn)->global_identifier, size_guess,
  871. DIRREQ_DIRECT);
  872. }
  873. /* Use this header to tell caches that the response depends on the
  874. * X-Or-Diff-From-Consensus header (or lack thereof). */
  875. const char vary_header[] = "Vary: X-Or-Diff-From-Consensus\r\n";
  876. clear_spool = 0;
  877. // The compress_method might have been NO_METHOD, but we store the data
  878. // compressed. Decompress them using `compression_used`. See fallback code in
  879. // find_best_consensus() and find_best_diff().
  880. write_http_response_headers(conn, -1,
  881. compress_method == NO_METHOD ?
  882. NO_METHOD : compression_used,
  883. vary_header,
  884. smartlist_len(conn->spool) == 1 ? lifetime : 0);
  885. if (compress_method == NO_METHOD && smartlist_len(conn->spool))
  886. conn->compress_state = tor_compress_new(0, compression_used,
  887. HIGH_COMPRESSION);
  888. /* Prime the connection with some data. */
  889. const int initial_flush_result = connection_dirserv_flushed_some(conn);
  890. tor_assert_nonfatal(initial_flush_result == 0);
  891. goto done;
  892. done:
  893. parsed_consensus_request_clear(&req);
  894. if (clear_spool) {
  895. dir_conn_clear_spool(conn);
  896. }
  897. return 0;
  898. }
  899. /** Helper function for GET /tor/status-vote/{current,next}/...
  900. */
  901. static int
  902. handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
  903. {
  904. const char *url = args->url;
  905. {
  906. ssize_t body_len = 0;
  907. ssize_t estimated_len = 0;
  908. int lifetime = 60; /* XXXX?? should actually use vote intervals. */
  909. /* This smartlist holds strings that we can compress on the fly. */
  910. smartlist_t *items = smartlist_new();
  911. /* This smartlist holds cached_dir_t objects that have a precompressed
  912. * deflated version. */
  913. smartlist_t *dir_items = smartlist_new();
  914. dirvote_dirreq_get_status_vote(url, items, dir_items);
  915. if (!smartlist_len(dir_items) && !smartlist_len(items)) {
  916. write_short_http_response(conn, 404, "Not found");
  917. goto vote_done;
  918. }
  919. /* We're sending items from at most one kind of source */
  920. tor_assert_nonfatal(smartlist_len(items) == 0 ||
  921. smartlist_len(dir_items) == 0);
  922. int streaming;
  923. unsigned mask;
  924. if (smartlist_len(items)) {
  925. /* We're taking strings and compressing them on the fly. */
  926. streaming = 1;
  927. mask = ~0u;
  928. } else {
  929. /* We're taking cached_dir_t objects. We only have them uncompressed
  930. * or deflated. */
  931. streaming = 0;
  932. mask = (1u<<NO_METHOD) | (1u<<ZLIB_METHOD);
  933. }
  934. const compress_method_t compress_method = find_best_compression_method(
  935. args->compression_supported&mask, streaming);
  936. SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
  937. body_len += compress_method != NO_METHOD ?
  938. d->dir_compressed_len : d->dir_len);
  939. estimated_len += body_len;
  940. SMARTLIST_FOREACH(items, const char *, item, {
  941. size_t ln = strlen(item);
  942. if (compress_method != NO_METHOD) {
  943. estimated_len += ln/2;
  944. } else {
  945. body_len += ln; estimated_len += ln;
  946. }
  947. });
  948. if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
  949. write_short_http_response(conn, 503, "Directory busy, try again later");
  950. goto vote_done;
  951. }
  952. write_http_response_header(conn, body_len ? body_len : -1,
  953. compress_method,
  954. lifetime);
  955. if (smartlist_len(items)) {
  956. if (compress_method != NO_METHOD) {
  957. conn->compress_state = tor_compress_new(1, compress_method,
  958. choose_compression_level(estimated_len));
  959. SMARTLIST_FOREACH(items, const char *, c,
  960. connection_buf_add_compress(c, strlen(c), conn, 0));
  961. connection_buf_add_compress("", 0, conn, 1);
  962. } else {
  963. SMARTLIST_FOREACH(items, const char *, c,
  964. connection_buf_add(c, strlen(c), TO_CONN(conn)));
  965. }
  966. } else {
  967. SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
  968. connection_buf_add(compress_method != NO_METHOD ?
  969. d->dir_compressed : d->dir,
  970. compress_method != NO_METHOD ?
  971. d->dir_compressed_len : d->dir_len,
  972. TO_CONN(conn)));
  973. }
  974. vote_done:
  975. smartlist_free(items);
  976. smartlist_free(dir_items);
  977. goto done;
  978. }
  979. done:
  980. return 0;
  981. }
  982. /** Helper function for GET /tor/micro/d/...
  983. */
  984. static int
  985. handle_get_microdesc(dir_connection_t *conn, const get_handler_args_t *args)
  986. {
  987. const char *url = args->url;
  988. const compress_method_t compress_method =
  989. find_best_compression_method(args->compression_supported, 1);
  990. int clear_spool = 1;
  991. {
  992. conn->spool = smartlist_new();
  993. dir_split_resource_into_spoolable(url+strlen("/tor/micro/d/"),
  994. DIR_SPOOL_MICRODESC,
  995. conn->spool, NULL,
  996. DSR_DIGEST256|DSR_BASE64|DSR_SORT_UNIQ);
  997. size_t size_guess = 0;
  998. dirserv_spool_remove_missing_and_guess_size(conn, 0,
  999. compress_method != NO_METHOD,
  1000. &size_guess, NULL);
  1001. if (smartlist_len(conn->spool) == 0) {
  1002. write_short_http_response(conn, 404, "Not found");
  1003. goto done;
  1004. }
  1005. if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
  1006. log_info(LD_DIRSERV,
  1007. "Client asked for server descriptors, but we've been "
  1008. "writing too many bytes lately. Sending 503 Dir busy.");
  1009. write_short_http_response(conn, 503, "Directory busy, try again later");
  1010. goto done;
  1011. }
  1012. clear_spool = 0;
  1013. write_http_response_header(conn, -1,
  1014. compress_method,
  1015. MICRODESC_CACHE_LIFETIME);
  1016. if (compress_method != NO_METHOD)
  1017. conn->compress_state = tor_compress_new(1, compress_method,
  1018. choose_compression_level(size_guess));
  1019. const int initial_flush_result = connection_dirserv_flushed_some(conn);
  1020. tor_assert_nonfatal(initial_flush_result == 0);
  1021. goto done;
  1022. }
  1023. done:
  1024. if (clear_spool) {
  1025. dir_conn_clear_spool(conn);
  1026. }
  1027. return 0;
  1028. }
  1029. /** Helper function for GET /tor/{server,extra}/...
  1030. */
  1031. static int
  1032. handle_get_descriptor(dir_connection_t *conn, const get_handler_args_t *args)
  1033. {
  1034. const char *url = args->url;
  1035. const compress_method_t compress_method =
  1036. find_best_compression_method(args->compression_supported, 1);
  1037. const or_options_t *options = get_options();
  1038. int clear_spool = 1;
  1039. if (!strcmpstart(url,"/tor/server/") ||
  1040. (!options->BridgeAuthoritativeDir &&
  1041. !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
  1042. int res;
  1043. const char *msg = NULL;
  1044. int cache_lifetime = 0;
  1045. int is_extra = !strcmpstart(url,"/tor/extra/");
  1046. url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
  1047. dir_spool_source_t source;
  1048. time_t publish_cutoff = 0;
  1049. if (!strcmpstart(url, "d/")) {
  1050. source =
  1051. is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
  1052. } else {
  1053. source =
  1054. is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
  1055. /* We only want to apply a publish cutoff when we're requesting
  1056. * resources by fingerprint. */
  1057. publish_cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
  1058. }
  1059. conn->spool = smartlist_new();
  1060. res = dirserv_get_routerdesc_spool(conn->spool, url,
  1061. source,
  1062. connection_dir_is_encrypted(conn),
  1063. &msg);
  1064. if (!strcmpstart(url, "all")) {
  1065. cache_lifetime = FULL_DIR_CACHE_LIFETIME;
  1066. } else if (smartlist_len(conn->spool) == 1) {
  1067. cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
  1068. }
  1069. size_t size_guess = 0;
  1070. int n_expired = 0;
  1071. dirserv_spool_remove_missing_and_guess_size(conn, publish_cutoff,
  1072. compress_method != NO_METHOD,
  1073. &size_guess, &n_expired);
  1074. /* If we are the bridge authority and the descriptor is a bridge
  1075. * descriptor, remember that we served this descriptor for desc stats. */
  1076. /* XXXX it's a bit of a kludge to have this here. */
  1077. if (get_options()->BridgeAuthoritativeDir &&
  1078. source == DIR_SPOOL_SERVER_BY_FP) {
  1079. SMARTLIST_FOREACH_BEGIN(conn->spool, spooled_resource_t *, spooled) {
  1080. const routerinfo_t *router =
  1081. router_get_by_id_digest((const char *)spooled->digest);
  1082. /* router can be NULL here when the bridge auth is asked for its own
  1083. * descriptor. */
  1084. if (router && router->purpose == ROUTER_PURPOSE_BRIDGE)
  1085. rep_hist_note_desc_served(router->cache_info.identity_digest);
  1086. } SMARTLIST_FOREACH_END(spooled);
  1087. }
  1088. if (res < 0 || size_guess == 0 || smartlist_len(conn->spool) == 0) {
  1089. if (msg == NULL)
  1090. msg = "Not found";
  1091. write_short_http_response(conn, 404, msg);
  1092. } else {
  1093. if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
  1094. log_info(LD_DIRSERV,
  1095. "Client asked for server descriptors, but we've been "
  1096. "writing too many bytes lately. Sending 503 Dir busy.");
  1097. write_short_http_response(conn, 503,
  1098. "Directory busy, try again later");
  1099. dir_conn_clear_spool(conn);
  1100. goto done;
  1101. }
  1102. write_http_response_header(conn, -1, compress_method, cache_lifetime);
  1103. if (compress_method != NO_METHOD)
  1104. conn->compress_state = tor_compress_new(1, compress_method,
  1105. choose_compression_level(size_guess));
  1106. clear_spool = 0;
  1107. /* Prime the connection with some data. */
  1108. int initial_flush_result = connection_dirserv_flushed_some(conn);
  1109. tor_assert_nonfatal(initial_flush_result == 0);
  1110. }
  1111. goto done;
  1112. }
  1113. done:
  1114. if (clear_spool)
  1115. dir_conn_clear_spool(conn);
  1116. return 0;
  1117. }
  1118. /** Helper function for GET /tor/keys/...
  1119. */
  1120. static int
  1121. handle_get_keys(dir_connection_t *conn, const get_handler_args_t *args)
  1122. {
  1123. const char *url = args->url;
  1124. const compress_method_t compress_method =
  1125. find_best_compression_method(args->compression_supported, 1);
  1126. const time_t if_modified_since = args->if_modified_since;
  1127. {
  1128. smartlist_t *certs = smartlist_new();
  1129. ssize_t len = -1;
  1130. if (!strcmp(url, "/tor/keys/all")) {
  1131. authority_cert_get_all(certs);
  1132. } else if (!strcmp(url, "/tor/keys/authority")) {
  1133. authority_cert_t *cert = get_my_v3_authority_cert();
  1134. if (cert)
  1135. smartlist_add(certs, cert);
  1136. } else if (!strcmpstart(url, "/tor/keys/fp/")) {
  1137. smartlist_t *fps = smartlist_new();
  1138. dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
  1139. fps, NULL,
  1140. DSR_HEX|DSR_SORT_UNIQ);
  1141. SMARTLIST_FOREACH(fps, char *, d, {
  1142. authority_cert_t *c = authority_cert_get_newest_by_id(d);
  1143. if (c) smartlist_add(certs, c);
  1144. tor_free(d);
  1145. });
  1146. smartlist_free(fps);
  1147. } else if (!strcmpstart(url, "/tor/keys/sk/")) {
  1148. smartlist_t *fps = smartlist_new();
  1149. dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
  1150. fps, NULL,
  1151. DSR_HEX|DSR_SORT_UNIQ);
  1152. SMARTLIST_FOREACH(fps, char *, d, {
  1153. authority_cert_t *c = authority_cert_get_by_sk_digest(d);
  1154. if (c) smartlist_add(certs, c);
  1155. tor_free(d);
  1156. });
  1157. smartlist_free(fps);
  1158. } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
  1159. smartlist_t *fp_sks = smartlist_new();
  1160. dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
  1161. fp_sks);
  1162. SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
  1163. authority_cert_t *c = authority_cert_get_by_digests(pair->first,
  1164. pair->second);
  1165. if (c) smartlist_add(certs, c);
  1166. tor_free(pair);
  1167. });
  1168. smartlist_free(fp_sks);
  1169. } else {
  1170. write_short_http_response(conn, 400, "Bad request");
  1171. goto keys_done;
  1172. }
  1173. if (!smartlist_len(certs)) {
  1174. write_short_http_response(conn, 404, "Not found");
  1175. goto keys_done;
  1176. }
  1177. SMARTLIST_FOREACH(certs, authority_cert_t *, c,
  1178. if (c->cache_info.published_on < if_modified_since)
  1179. SMARTLIST_DEL_CURRENT(certs, c));
  1180. if (!smartlist_len(certs)) {
  1181. write_short_http_response(conn, 304, "Not modified");
  1182. goto keys_done;
  1183. }
  1184. len = 0;
  1185. SMARTLIST_FOREACH(certs, authority_cert_t *, c,
  1186. len += c->cache_info.signed_descriptor_len);
  1187. if (global_write_bucket_low(TO_CONN(conn),
  1188. compress_method != NO_METHOD ? len/2 : len,
  1189. 2)) {
  1190. write_short_http_response(conn, 503, "Directory busy, try again later");
  1191. goto keys_done;
  1192. }
  1193. write_http_response_header(conn,
  1194. compress_method != NO_METHOD ? -1 : len,
  1195. compress_method,
  1196. 60*60);
  1197. if (compress_method != NO_METHOD) {
  1198. conn->compress_state = tor_compress_new(1, compress_method,
  1199. choose_compression_level(len));
  1200. SMARTLIST_FOREACH(certs, authority_cert_t *, c,
  1201. connection_buf_add_compress(
  1202. c->cache_info.signed_descriptor_body,
  1203. c->cache_info.signed_descriptor_len,
  1204. conn, 0));
  1205. connection_buf_add_compress("", 0, conn, 1);
  1206. } else {
  1207. SMARTLIST_FOREACH(certs, authority_cert_t *, c,
  1208. connection_buf_add(c->cache_info.signed_descriptor_body,
  1209. c->cache_info.signed_descriptor_len,
  1210. TO_CONN(conn)));
  1211. }
  1212. keys_done:
  1213. smartlist_free(certs);
  1214. goto done;
  1215. }
  1216. done:
  1217. return 0;
  1218. }
  1219. /** Helper function for GET /tor/rendezvous2/
  1220. */
  1221. static int
  1222. handle_get_hs_descriptor_v2(dir_connection_t *conn,
  1223. const get_handler_args_t *args)
  1224. {
  1225. const char *url = args->url;
  1226. if (connection_dir_is_encrypted(conn)) {
  1227. /* Handle v2 rendezvous descriptor fetch request. */
  1228. const char *descp;
  1229. const char *query = url + strlen("/tor/rendezvous2/");
  1230. if (rend_valid_descriptor_id(query)) {
  1231. log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
  1232. safe_str(escaped(query)));
  1233. switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
  1234. case 1: /* valid */
  1235. write_http_response_header(conn, strlen(descp), NO_METHOD, 0);
  1236. connection_buf_add(descp, strlen(descp), TO_CONN(conn));
  1237. break;
  1238. case 0: /* well-formed but not present */
  1239. write_short_http_response(conn, 404, "Not found");
  1240. break;
  1241. case -1: /* not well-formed */
  1242. write_short_http_response(conn, 400, "Bad request");
  1243. break;
  1244. }
  1245. } else { /* not well-formed */
  1246. write_short_http_response(conn, 400, "Bad request");
  1247. }
  1248. goto done;
  1249. } else {
  1250. /* Not encrypted! */
  1251. write_short_http_response(conn, 404, "Not found");
  1252. }
  1253. done:
  1254. return 0;
  1255. }
  1256. /** Helper function for GET /tor/hs/3/<z>. Only for version 3.
  1257. */
  1258. STATIC int
  1259. handle_get_hs_descriptor_v3(dir_connection_t *conn,
  1260. const get_handler_args_t *args)
  1261. {
  1262. int retval;
  1263. const char *desc_str = NULL;
  1264. const char *pubkey_str = NULL;
  1265. const char *url = args->url;
  1266. /* Reject unencrypted dir connections */
  1267. if (!connection_dir_is_encrypted(conn)) {
  1268. write_short_http_response(conn, 404, "Not found");
  1269. goto done;
  1270. }
  1271. /* After the path prefix follows the base64 encoded blinded pubkey which we
  1272. * use to get the descriptor from the cache. Skip the prefix and get the
  1273. * pubkey. */
  1274. tor_assert(!strcmpstart(url, "/tor/hs/3/"));
  1275. pubkey_str = url + strlen("/tor/hs/3/");
  1276. retval = hs_cache_lookup_as_dir(HS_VERSION_THREE,
  1277. pubkey_str, &desc_str);
  1278. if (retval <= 0 || desc_str == NULL) {
  1279. write_short_http_response(conn, 404, "Not found");
  1280. goto done;
  1281. }
  1282. /* Found requested descriptor! Pass it to this nice client. */
  1283. write_http_response_header(conn, strlen(desc_str), NO_METHOD, 0);
  1284. connection_buf_add(desc_str, strlen(desc_str), TO_CONN(conn));
  1285. done:
  1286. return 0;
  1287. }
  1288. /** Helper function for GET /tor/networkstatus-bridges
  1289. */
  1290. static int
  1291. handle_get_networkstatus_bridges(dir_connection_t *conn,
  1292. const get_handler_args_t *args)
  1293. {
  1294. const char *headers = args->headers;
  1295. const or_options_t *options = get_options();
  1296. if (options->BridgeAuthoritativeDir &&
  1297. options->BridgePassword_AuthDigest_ &&
  1298. connection_dir_is_encrypted(conn)) {
  1299. char *status;
  1300. char digest[DIGEST256_LEN];
  1301. char *header = http_get_header(headers, "Authorization: Basic ");
  1302. if (header)
  1303. crypto_digest256(digest, header, strlen(header), DIGEST_SHA256);
  1304. /* now make sure the password is there and right */
  1305. if (!header ||
  1306. tor_memneq(digest,
  1307. options->BridgePassword_AuthDigest_, DIGEST256_LEN)) {
  1308. write_short_http_response(conn, 404, "Not found");
  1309. tor_free(header);
  1310. goto done;
  1311. }
  1312. tor_free(header);
  1313. /* all happy now. send an answer. */
  1314. status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
  1315. size_t dlen = strlen(status);
  1316. write_http_response_header(conn, dlen, NO_METHOD, 0);
  1317. connection_buf_add(status, dlen, TO_CONN(conn));
  1318. tor_free(status);
  1319. goto done;
  1320. }
  1321. done:
  1322. return 0;
  1323. }
  1324. /** Helper function for GET the bandwidth file used for the next vote */
  1325. static int
  1326. handle_get_next_bandwidth(dir_connection_t *conn,
  1327. const get_handler_args_t *args)
  1328. {
  1329. log_debug(LD_DIR, "Getting next bandwidth.");
  1330. const or_options_t *options = get_options();
  1331. const compress_method_t compress_method =
  1332. find_best_compression_method(args->compression_supported, 1);
  1333. if (options->V3BandwidthsFile) {
  1334. char *bandwidth = read_file_to_str(options->V3BandwidthsFile,
  1335. RFTS_IGNORE_MISSING, NULL);
  1336. if (bandwidth != NULL) {
  1337. ssize_t len = strlen(bandwidth);
  1338. write_http_response_header(conn, compress_method != NO_METHOD ? -1 : len,
  1339. compress_method, BANDWIDTH_CACHE_LIFETIME);
  1340. if (compress_method != NO_METHOD) {
  1341. conn->compress_state = tor_compress_new(1, compress_method,
  1342. choose_compression_level(len/2));
  1343. log_debug(LD_DIR, "Compressing bandwidth file.");
  1344. } else {
  1345. log_debug(LD_DIR, "Not compressing bandwidth file.");
  1346. }
  1347. connection_dir_buf_add((const char*)bandwidth, len, conn, 1);
  1348. tor_free(bandwidth);
  1349. return 0;
  1350. }
  1351. }
  1352. write_short_http_response(conn, 404, "Not found");
  1353. return 0;
  1354. }
  1355. /** Helper function for GET robots.txt or /tor/robots.txt */
  1356. static int
  1357. handle_get_robots(dir_connection_t *conn, const get_handler_args_t *args)
  1358. {
  1359. (void)args;
  1360. {
  1361. const char robots[] = "User-agent: *\r\nDisallow: /\r\n";
  1362. size_t len = strlen(robots);
  1363. write_http_response_header(conn, len, NO_METHOD, ROBOTS_CACHE_LIFETIME);
  1364. connection_buf_add(robots, len, TO_CONN(conn));
  1365. }
  1366. return 0;
  1367. }
  1368. /* Given the <b>url</b> from a POST request, try to extract the version number
  1369. * using the provided <b>prefix</b>. The version should be after the prefix and
  1370. * ending with the separator "/". For instance:
  1371. * /tor/hs/3/publish
  1372. *
  1373. * On success, <b>end_pos</b> points to the position right after the version
  1374. * was found. On error, it is set to NULL.
  1375. *
  1376. * Return version on success else negative value. */
  1377. STATIC int
  1378. parse_hs_version_from_post(const char *url, const char *prefix,
  1379. const char **end_pos)
  1380. {
  1381. int ok;
  1382. unsigned long version;
  1383. const char *start;
  1384. char *end = NULL;
  1385. tor_assert(url);
  1386. tor_assert(prefix);
  1387. tor_assert(end_pos);
  1388. /* Check if the prefix does start the url. */
  1389. if (strcmpstart(url, prefix)) {
  1390. goto err;
  1391. }
  1392. /* Move pointer to the end of the prefix string. */
  1393. start = url + strlen(prefix);
  1394. /* Try this to be the HS version and if we are still at the separator, next
  1395. * will be move to the right value. */
  1396. version = tor_parse_long(start, 10, 0, INT_MAX, &ok, &end);
  1397. if (!ok) {
  1398. goto err;
  1399. }
  1400. *end_pos = end;
  1401. return (int) version;
  1402. err:
  1403. *end_pos = NULL;
  1404. return -1;
  1405. }
  1406. /* Handle the POST request for a hidden service descripror. The request is in
  1407. * <b>url</b>, the body of the request is in <b>body</b>. Return 200 on success
  1408. * else return 400 indicating a bad request. */
  1409. STATIC int
  1410. handle_post_hs_descriptor(const char *url, const char *body)
  1411. {
  1412. int version;
  1413. const char *end_pos;
  1414. tor_assert(url);
  1415. tor_assert(body);
  1416. version = parse_hs_version_from_post(url, "/tor/hs/", &end_pos);
  1417. if (version < 0) {
  1418. goto err;
  1419. }
  1420. /* We have a valid version number, now make sure it's a publish request. Use
  1421. * the end position just after the version and check for the command. */
  1422. if (strcmpstart(end_pos, "/publish")) {
  1423. goto err;
  1424. }
  1425. switch (version) {
  1426. case HS_VERSION_THREE:
  1427. if (hs_cache_store_as_dir(body) < 0) {
  1428. goto err;
  1429. }
  1430. log_info(LD_REND, "Publish request for HS descriptor handled "
  1431. "successfully.");
  1432. break;
  1433. default:
  1434. /* Unsupported version, return a bad request. */
  1435. goto err;
  1436. }
  1437. return 200;
  1438. err:
  1439. /* Bad request. */
  1440. return 400;
  1441. }
  1442. /** Helper function: called when a dirserver gets a complete HTTP POST
  1443. * request. Look for an uploaded server descriptor or rendezvous
  1444. * service descriptor. On finding one, process it and write a
  1445. * response into conn-\>outbuf. If the request is unrecognized, send a
  1446. * 400. Always return 0. */
  1447. MOCK_IMPL(STATIC int,
  1448. directory_handle_command_post,(dir_connection_t *conn, const char *headers,
  1449. const char *body, size_t body_len))
  1450. {
  1451. char *url = NULL;
  1452. const or_options_t *options = get_options();
  1453. log_debug(LD_DIRSERV,"Received POST command.");
  1454. conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
  1455. if (!public_server_mode(options)) {
  1456. log_info(LD_DIR, "Rejected dir post request from %s "
  1457. "since we're not a public relay.", conn->base_.address);
  1458. write_short_http_response(conn, 503, "Not acting as a public relay");
  1459. goto done;
  1460. }
  1461. if (parse_http_url(headers, &url) < 0) {
  1462. write_short_http_response(conn, 400, "Bad request");
  1463. return 0;
  1464. }
  1465. log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
  1466. /* Handle v2 rendezvous service publish request. */
  1467. if (connection_dir_is_encrypted(conn) &&
  1468. !strcmpstart(url,"/tor/rendezvous2/publish")) {
  1469. if (rend_cache_store_v2_desc_as_dir(body) < 0) {
  1470. log_warn(LD_REND, "Rejected v2 rend descriptor (body size %d) from %s.",
  1471. (int)body_len, conn->base_.address);
  1472. write_short_http_response(conn, 400,
  1473. "Invalid v2 service descriptor rejected");
  1474. } else {
  1475. write_short_http_response(conn, 200, "Service descriptor (v2) stored");
  1476. log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
  1477. }
  1478. goto done;
  1479. }
  1480. /* Handle HS descriptor publish request. */
  1481. /* XXX: This should be disabled with a consensus param until we want to
  1482. * the prop224 be deployed and thus use. */
  1483. if (connection_dir_is_encrypted(conn) && !strcmpstart(url, "/tor/hs/")) {
  1484. const char *msg = "HS descriptor stored successfully.";
  1485. /* We most probably have a publish request for an HS descriptor. */
  1486. int code = handle_post_hs_descriptor(url, body);
  1487. if (code != 200) {
  1488. msg = "Invalid HS descriptor. Rejected.";
  1489. }
  1490. write_short_http_response(conn, code, msg);
  1491. goto done;
  1492. }
  1493. if (!authdir_mode(options)) {
  1494. /* we just provide cached directories; we don't want to
  1495. * receive anything. */
  1496. write_short_http_response(conn, 400, "Nonauthoritative directory does not "
  1497. "accept posted server descriptors");
  1498. goto done;
  1499. }
  1500. if (authdir_mode(options) &&
  1501. !strcmp(url,"/tor/")) { /* server descriptor post */
  1502. const char *msg = "[None]";
  1503. uint8_t purpose = authdir_mode_bridge(options) ?
  1504. ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
  1505. was_router_added_t r = dirserv_add_multiple_descriptors(body, body_len,
  1506. purpose, conn->base_.address, &msg);
  1507. tor_assert(msg);
  1508. if (r == ROUTER_ADDED_SUCCESSFULLY) {
  1509. write_short_http_response(conn, 200, msg);
  1510. } else if (WRA_WAS_OUTDATED(r)) {
  1511. write_http_response_header_impl(conn, -1, NULL, NULL,
  1512. "X-Descriptor-Not-New: Yes\r\n", -1);
  1513. } else {
  1514. log_info(LD_DIRSERV,
  1515. "Rejected router descriptor or extra-info from %s "
  1516. "(\"%s\").",
  1517. conn->base_.address, msg);
  1518. write_short_http_response(conn, 400, msg);
  1519. }
  1520. goto done;
  1521. }
  1522. if (authdir_mode_v3(options) &&
  1523. !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
  1524. const char *msg = "OK";
  1525. int status;
  1526. if (dirvote_add_vote(body, &msg, &status)) {
  1527. write_short_http_response(conn, status, "Vote stored");
  1528. } else {
  1529. tor_assert(msg);
  1530. log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").",
  1531. conn->base_.address, msg);
  1532. write_short_http_response(conn, status, msg);
  1533. }
  1534. goto done;
  1535. }
  1536. if (authdir_mode_v3(options) &&
  1537. !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
  1538. const char *msg = NULL;
  1539. if (dirvote_add_signatures(body, conn->base_.address, &msg)>=0) {
  1540. write_short_http_response(conn, 200, msg?msg:"Signatures stored");
  1541. } else {
  1542. log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
  1543. conn->base_.address, msg?msg:"???");
  1544. write_short_http_response(conn, 400,
  1545. msg?msg:"Unable to store signatures");
  1546. }
  1547. goto done;
  1548. }
  1549. /* we didn't recognize the url */
  1550. write_short_http_response(conn, 404, "Not found");
  1551. done:
  1552. tor_free(url);
  1553. return 0;
  1554. }
  1555. /** If <b>headers</b> indicates that a proxy was involved, then rewrite
  1556. * <b>conn</b>-\>address to describe our best guess of the address that
  1557. * originated this HTTP request. */
  1558. static void
  1559. http_set_address_origin(const char *headers, connection_t *conn)
  1560. {
  1561. char *fwd;
  1562. fwd = http_get_header(headers, "Forwarded-For: ");
  1563. if (!fwd)
  1564. fwd = http_get_header(headers, "X-Forwarded-For: ");
  1565. if (fwd) {
  1566. tor_addr_t toraddr;
  1567. if (tor_addr_parse(&toraddr,fwd) == -1 ||
  1568. tor_addr_is_internal(&toraddr,0)) {
  1569. log_debug(LD_DIR, "Ignoring local/internal IP %s", escaped(fwd));
  1570. tor_free(fwd);
  1571. return;
  1572. }
  1573. tor_free(conn->address);
  1574. conn->address = tor_strdup(fwd);
  1575. tor_free(fwd);
  1576. }
  1577. }
  1578. /** Called when a dirserver receives data on a directory connection;
  1579. * looks for an HTTP request. If the request is complete, remove it
  1580. * from the inbuf, try to process it; otherwise, leave it on the
  1581. * buffer. Return a 0 on success, or -1 on error.
  1582. */
  1583. int
  1584. directory_handle_command(dir_connection_t *conn)
  1585. {
  1586. char *headers=NULL, *body=NULL;
  1587. size_t body_len=0;
  1588. int r;
  1589. tor_assert(conn);
  1590. tor_assert(conn->base_.type == CONN_TYPE_DIR);
  1591. switch (connection_fetch_from_buf_http(TO_CONN(conn),
  1592. &headers, MAX_HEADERS_SIZE,
  1593. &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
  1594. case -1: /* overflow */
  1595. log_warn(LD_DIRSERV,
  1596. "Request too large from address '%s' to DirPort. Closing.",
  1597. safe_str(conn->base_.address));
  1598. return -1;
  1599. case 0:
  1600. log_debug(LD_DIRSERV,"command not all here yet.");
  1601. return 0;
  1602. /* case 1, fall through */
  1603. }
  1604. http_set_address_origin(headers, TO_CONN(conn));
  1605. // we should escape headers here as well,
  1606. // but we can't call escaped() twice, as it uses the same buffer
  1607. //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, escaped(body));
  1608. if (!strncasecmp(headers,"GET",3))
  1609. r = directory_handle_command_get(conn, headers, body, body_len);
  1610. else if (!strncasecmp(headers,"POST",4))
  1611. r = directory_handle_command_post(conn, headers, body, body_len);
  1612. else {
  1613. log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
  1614. "Got headers %s with unknown command. Closing.",
  1615. escaped(headers));
  1616. r = -1;
  1617. }
  1618. tor_free(headers); tor_free(body);
  1619. return r;
  1620. }