dircache.c 60 KB

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