Fix an erroneous !
[tor.git] / src / or / directory.c
blob5bf544e67fc1cd7c11bd8189007bae75e0186e73
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2017, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #define DIRECTORY_PRIVATE
8 #include "or.h"
9 #include "backtrace.h"
10 #include "bridges.h"
11 #include "buffers.h"
12 #include "circuitbuild.h"
13 #include "config.h"
14 #include "connection.h"
15 #include "connection_edge.h"
16 #include "conscache.h"
17 #include "consdiff.h"
18 #include "consdiffmgr.h"
19 #include "control.h"
20 #include "compat.h"
21 #include "directory.h"
22 #include "dirserv.h"
23 #include "dirvote.h"
24 #include "entrynodes.h"
25 #include "geoip.h"
26 #include "hs_cache.h"
27 #include "hs_common.h"
28 #include "hs_client.h"
29 #include "main.h"
30 #include "microdesc.h"
31 #include "networkstatus.h"
32 #include "nodelist.h"
33 #include "policies.h"
34 #include "relay.h"
35 #include "rendclient.h"
36 #include "rendcommon.h"
37 #include "rendservice.h"
38 #include "rephist.h"
39 #include "router.h"
40 #include "routerlist.h"
41 #include "routerparse.h"
42 #include "routerset.h"
43 #include "shared_random.h"
45 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
46 #if !defined(OpenBSD)
47 #include <malloc.h>
48 #endif
49 #endif
51 /**
52 * \file directory.c
53 * \brief Code to send and fetch information from directory authorities and
54 * caches via HTTP.
56 * Directory caches and authorities use dirserv.c to generate the results of a
57 * query and stream them to the connection; clients use routerparse.c to parse
58 * them.
60 * Every directory request has a dir_connection_t on the client side and on
61 * the server side. In most cases, the dir_connection_t object is a linked
62 * connection, tunneled through an edge_connection_t so that it can be a
63 * stream on the Tor network. The only non-tunneled connections are those
64 * that are used to upload material (descriptors and votes) to authorities.
65 * Among tunneled connections, some use one-hop circuits, and others use
66 * multi-hop circuits for anonymity.
68 * Directory requests are launched by calling
69 * directory_initiate_request(). This
70 * launch the connection, will construct an HTTP request with
71 * directory_send_command(), send the and wait for a response. The client
72 * later handles the response with connection_dir_client_reached_eof(),
73 * which passes the information received to another part of Tor.
75 * On the server side, requests are read in directory_handle_command(),
76 * which dispatches first on the request type (GET or POST), and then on
77 * the URL requested. GET requests are processed with a table-based
78 * dispatcher in url_table[]. The process of handling larger GET requests
79 * is complicated because we need to avoid allocating a copy of all the
80 * data to be sent to the client in one huge buffer. Instead, we spool the
81 * data into the buffer using logic in connection_dirserv_flushed_some() in
82 * dirserv.c. (TODO: If we extended buf.c to have a zero-copy
83 * reference-based buffer type, we could remove most of that code, at the
84 * cost of a bit more reference counting.)
85 **/
87 /* In-points to directory.c:
89 * - directory_post_to_dirservers(), called from
90 * router_upload_dir_desc_to_dirservers() in router.c
91 * upload_service_descriptor() in rendservice.c
92 * - directory_get_from_dirserver(), called from
93 * rend_client_refetch_renddesc() in rendclient.c
94 * run_scheduled_events() in main.c
95 * do_hup() in main.c
96 * - connection_dir_process_inbuf(), called from
97 * connection_process_inbuf() in connection.c
98 * - connection_dir_finished_flushing(), called from
99 * connection_finished_flushing() in connection.c
100 * - connection_dir_finished_connecting(), called from
101 * connection_finished_connecting() in connection.c
103 static void directory_send_command(dir_connection_t *conn,
104 int direct,
105 const directory_request_t *request);
106 static int body_is_plausible(const char *body, size_t body_len, int purpose);
107 static void http_set_address_origin(const char *headers, connection_t *conn);
108 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
109 static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn);
110 static void connection_dir_download_cert_failed(
111 dir_connection_t *conn, int status_code);
112 static void connection_dir_retry_bridges(smartlist_t *descs);
113 static void dir_routerdesc_download_failed(smartlist_t *failed,
114 int status_code,
115 int router_purpose,
116 int was_extrainfo,
117 int was_descriptor_digests);
118 static void dir_microdesc_download_failed(smartlist_t *failed,
119 int status_code);
120 static int client_likes_consensus(const struct consensus_cache_entry_t *ent,
121 const char *want_url);
123 static void connection_dir_close_consensus_fetches(
124 dir_connection_t *except_this_one, const char *resource);
126 /********* START VARIABLES **********/
128 /** How far in the future do we allow a directory server to tell us it is
129 * before deciding that one of us has the wrong time? */
130 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
132 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
133 #define X_OR_DIFF_FROM_CONSENSUS_HEADER "X-Or-Diff-From-Consensus: "
135 /** HTTP cache control: how long do we tell proxies they can cache each
136 * kind of document we serve? */
137 #define FULL_DIR_CACHE_LIFETIME (60*60)
138 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
139 #define DIRPORTFRONTPAGE_CACHE_LIFETIME (20*60)
140 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
141 #define ROUTERDESC_CACHE_LIFETIME (30*60)
142 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
143 #define ROBOTS_CACHE_LIFETIME (24*60*60)
144 #define MICRODESC_CACHE_LIFETIME (48*60*60)
146 /********* END VARIABLES ************/
148 /** Return false if the directory purpose <b>dir_purpose</b>
149 * does not require an anonymous (three-hop) connection.
151 * Return true 1) by default, 2) if all directory actions have
152 * specifically been configured to be over an anonymous connection,
153 * or 3) if the router is a bridge */
155 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
156 const char *resource)
158 if (get_options()->AllDirActionsPrivate)
159 return 1;
161 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
162 if (dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC
163 && resource && !strcmp(resource, "authority.z")) {
164 /* We are asking a bridge for its own descriptor. That doesn't need
165 anonymity. */
166 return 0;
168 /* Assume all other bridge stuff needs anonymity. */
169 return 1; /* if no circuits yet, this might break bootstrapping, but it's
170 * needed to be safe. */
173 switch (dir_purpose)
175 case DIR_PURPOSE_UPLOAD_DIR:
176 case DIR_PURPOSE_UPLOAD_VOTE:
177 case DIR_PURPOSE_UPLOAD_SIGNATURES:
178 case DIR_PURPOSE_FETCH_STATUS_VOTE:
179 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
180 case DIR_PURPOSE_FETCH_CONSENSUS:
181 case DIR_PURPOSE_FETCH_CERTIFICATE:
182 case DIR_PURPOSE_FETCH_SERVERDESC:
183 case DIR_PURPOSE_FETCH_EXTRAINFO:
184 case DIR_PURPOSE_FETCH_MICRODESC:
185 return 0;
186 case DIR_PURPOSE_HAS_FETCHED_HSDESC:
187 case DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2:
188 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
189 case DIR_PURPOSE_FETCH_RENDDESC_V2:
190 case DIR_PURPOSE_FETCH_HSDESC:
191 case DIR_PURPOSE_UPLOAD_HSDESC:
192 return 1;
193 case DIR_PURPOSE_SERVER:
194 default:
195 log_warn(LD_BUG, "Called with dir_purpose=%d, router_purpose=%d",
196 dir_purpose, router_purpose);
197 tor_assert_nonfatal_unreached();
198 return 1; /* Assume it needs anonymity; better safe than sorry. */
202 /** Return a newly allocated string describing <b>auth</b>. Only describes
203 * authority features. */
204 STATIC char *
205 authdir_type_to_string(dirinfo_type_t auth)
207 char *result;
208 smartlist_t *lst = smartlist_new();
209 if (auth & V3_DIRINFO)
210 smartlist_add(lst, (void*)"V3");
211 if (auth & BRIDGE_DIRINFO)
212 smartlist_add(lst, (void*)"Bridge");
213 if (smartlist_len(lst)) {
214 result = smartlist_join_strings(lst, ", ", 0, NULL);
215 } else {
216 result = tor_strdup("[Not an authority]");
218 smartlist_free(lst);
219 return result;
222 /** Return a string describing a given directory connection purpose. */
223 STATIC const char *
224 dir_conn_purpose_to_string(int purpose)
226 switch (purpose)
228 case DIR_PURPOSE_UPLOAD_DIR:
229 return "server descriptor upload";
230 case DIR_PURPOSE_UPLOAD_VOTE:
231 return "server vote upload";
232 case DIR_PURPOSE_UPLOAD_SIGNATURES:
233 return "consensus signature upload";
234 case DIR_PURPOSE_FETCH_SERVERDESC:
235 return "server descriptor fetch";
236 case DIR_PURPOSE_FETCH_EXTRAINFO:
237 return "extra-info fetch";
238 case DIR_PURPOSE_FETCH_CONSENSUS:
239 return "consensus network-status fetch";
240 case DIR_PURPOSE_FETCH_CERTIFICATE:
241 return "authority cert fetch";
242 case DIR_PURPOSE_FETCH_STATUS_VOTE:
243 return "status vote fetch";
244 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
245 return "consensus signature fetch";
246 case DIR_PURPOSE_FETCH_RENDDESC_V2:
247 return "hidden-service v2 descriptor fetch";
248 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
249 return "hidden-service v2 descriptor upload";
250 case DIR_PURPOSE_FETCH_HSDESC:
251 return "hidden-service descriptor fetch";
252 case DIR_PURPOSE_UPLOAD_HSDESC:
253 return "hidden-service descriptor upload";
254 case DIR_PURPOSE_FETCH_MICRODESC:
255 return "microdescriptor fetch";
258 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
259 return "(unknown)";
262 /** Return the requisite directory information types. */
263 STATIC dirinfo_type_t
264 dir_fetch_type(int dir_purpose, int router_purpose, const char *resource)
266 dirinfo_type_t type;
267 switch (dir_purpose) {
268 case DIR_PURPOSE_FETCH_EXTRAINFO:
269 type = EXTRAINFO_DIRINFO;
270 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
271 type |= BRIDGE_DIRINFO;
272 else
273 type |= V3_DIRINFO;
274 break;
275 case DIR_PURPOSE_FETCH_SERVERDESC:
276 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
277 type = BRIDGE_DIRINFO;
278 else
279 type = V3_DIRINFO;
280 break;
281 case DIR_PURPOSE_FETCH_STATUS_VOTE:
282 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
283 case DIR_PURPOSE_FETCH_CERTIFICATE:
284 type = V3_DIRINFO;
285 break;
286 case DIR_PURPOSE_FETCH_CONSENSUS:
287 type = V3_DIRINFO;
288 if (resource && !strcmp(resource, "microdesc"))
289 type |= MICRODESC_DIRINFO;
290 break;
291 case DIR_PURPOSE_FETCH_MICRODESC:
292 type = MICRODESC_DIRINFO;
293 break;
294 default:
295 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
296 type = NO_DIRINFO;
297 break;
299 return type;
302 /** Return true iff <b>identity_digest</b> is the digest of a router which
303 * says that it caches extrainfos. (If <b>is_authority</b> we always
304 * believe that to be true.) */
306 router_supports_extrainfo(const char *identity_digest, int is_authority)
308 const node_t *node = node_get_by_id(identity_digest);
310 if (node && node->ri) {
311 if (node->ri->caches_extra_info)
312 return 1;
314 if (is_authority) {
315 return 1;
317 return 0;
320 /** Return true iff any trusted directory authority has accepted our
321 * server descriptor.
323 * We consider any authority sufficient because waiting for all of
324 * them means it never happens while any authority is down; we don't
325 * go for something more complex in the middle (like \>1/3 or \>1/2 or
326 * \>=1/2) because that doesn't seem necessary yet.
329 directories_have_accepted_server_descriptor(void)
331 const smartlist_t *servers = router_get_trusted_dir_servers();
332 const or_options_t *options = get_options();
333 SMARTLIST_FOREACH(servers, dir_server_t *, d, {
334 if ((d->type & options->PublishServerDescriptor_) &&
335 d->has_accepted_serverdesc) {
336 return 1;
339 return 0;
342 /** Start a connection to every suitable directory authority, using
343 * connection purpose <b>dir_purpose</b> and uploading <b>payload</b>
344 * (of length <b>payload_len</b>). The dir_purpose should be one of
345 * 'DIR_PURPOSE_UPLOAD_{DIR|VOTE|SIGNATURES}'.
347 * <b>router_purpose</b> describes the type of descriptor we're
348 * publishing, if we're publishing a descriptor -- e.g. general or bridge.
350 * <b>type</b> specifies what sort of dir authorities (V3,
351 * BRIDGE, etc) we should upload to.
353 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
354 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
355 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
356 * to all authorities, and the extra-info document to all authorities that
357 * support it.
359 void
360 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
361 dirinfo_type_t type,
362 const char *payload,
363 size_t payload_len, size_t extrainfo_len)
365 const or_options_t *options = get_options();
366 dir_indirection_t indirection;
367 const smartlist_t *dirservers = router_get_trusted_dir_servers();
368 int found = 0;
369 const int exclude_self = (dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
370 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES);
371 tor_assert(dirservers);
372 /* This tries dirservers which we believe to be down, but ultimately, that's
373 * harmless, and we may as well err on the side of getting things uploaded.
375 SMARTLIST_FOREACH_BEGIN(dirservers, dir_server_t *, ds) {
376 routerstatus_t *rs = &(ds->fake_status);
377 size_t upload_len = payload_len;
379 if ((type & ds->type) == 0)
380 continue;
382 if (exclude_self && router_digest_is_me(ds->digest)) {
383 /* we don't upload to ourselves, but at least there's now at least
384 * one authority of this type that has what we wanted to upload. */
385 found = 1;
386 continue;
389 if (options->StrictNodes &&
390 routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) {
391 log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
392 "it's in our ExcludedNodes list and StrictNodes is set. "
393 "Skipping.",
394 ds->nickname,
395 dir_conn_purpose_to_string(dir_purpose));
396 continue;
399 found = 1; /* at least one authority of this type was listed */
400 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
401 ds->has_accepted_serverdesc = 0;
403 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
404 upload_len += extrainfo_len;
405 log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
406 (int) extrainfo_len);
408 if (purpose_needs_anonymity(dir_purpose, router_purpose, NULL)) {
409 indirection = DIRIND_ANONYMOUS;
410 } else if (!fascist_firewall_allows_dir_server(ds,
411 FIREWALL_DIR_CONNECTION,
412 0)) {
413 if (fascist_firewall_allows_dir_server(ds, FIREWALL_OR_CONNECTION, 0))
414 indirection = DIRIND_ONEHOP;
415 else
416 indirection = DIRIND_ANONYMOUS;
417 } else {
418 indirection = DIRIND_DIRECT_CONN;
421 directory_request_t *req = directory_request_new(dir_purpose);
422 directory_request_set_routerstatus(req, rs);
423 directory_request_set_router_purpose(req, router_purpose);
424 directory_request_set_indirection(req, indirection);
425 directory_request_set_payload(req, payload, upload_len);
426 directory_initiate_request(req);
427 directory_request_free(req);
428 } SMARTLIST_FOREACH_END(ds);
429 if (!found) {
430 char *s = authdir_type_to_string(type);
431 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
432 "of type '%s', but no authorities of that type listed!", s);
433 tor_free(s);
437 /** Return true iff, according to the values in <b>options</b>, we should be
438 * using directory guards for direct downloads of directory information. */
439 STATIC int
440 should_use_directory_guards(const or_options_t *options)
442 /* Public (non-bridge) servers never use directory guards. */
443 if (public_server_mode(options))
444 return 0;
445 /* If guards are disabled, we can't use directory guards.
447 if (!options->UseEntryGuards)
448 return 0;
449 /* If we're configured to fetch directory info aggressively or of a
450 * nonstandard type, don't use directory guards. */
451 if (options->DownloadExtraInfo || options->FetchDirInfoEarly ||
452 options->FetchDirInfoExtraEarly || options->FetchUselessDescriptors)
453 return 0;
454 return 1;
457 /** Pick an unconstrained directory server from among our guards, the latest
458 * networkstatus, or the fallback dirservers, for use in downloading
459 * information of type <b>type</b>, and return its routerstatus. */
460 static const routerstatus_t *
461 directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags,
462 uint8_t dir_purpose,
463 circuit_guard_state_t **guard_state_out)
465 const routerstatus_t *rs = NULL;
466 const or_options_t *options = get_options();
468 if (options->UseBridges)
469 log_warn(LD_BUG, "Called when we have UseBridges set.");
471 if (should_use_directory_guards(options)) {
472 const node_t *node = guards_choose_dirguard(guard_state_out);
473 if (node)
474 rs = node->rs;
475 } else {
476 /* anybody with a non-zero dirport will do */
477 rs = router_pick_directory_server(type, pds_flags);
479 if (!rs) {
480 log_info(LD_DIR, "No router found for %s; falling back to "
481 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
482 rs = router_pick_fallback_dirserver(type, pds_flags);
485 return rs;
489 * Set the extra fields in <b>req</b> that are used when requesting a
490 * consensus of type <b>resource</b>.
492 * Right now, these fields are if-modified-since and x-or-diff-from-consensus.
494 static void
495 dir_consensus_request_set_additional_headers(directory_request_t *req,
496 const char *resource)
498 time_t if_modified_since = 0;
499 uint8_t or_diff_from[DIGEST256_LEN];
500 int or_diff_from_is_set = 0;
502 /* DEFAULT_IF_MODIFIED_SINCE_DELAY is 1/20 of the default consensus
503 * period of 1 hour.
505 const int DEFAULT_IF_MODIFIED_SINCE_DELAY = 180;
506 const int32_t DEFAULT_TRY_DIFF_FOR_CONSENSUS_NEWER = 72;
507 const int32_t MIN_TRY_DIFF_FOR_CONSENSUS_NEWER = 0;
508 const int32_t MAX_TRY_DIFF_FOR_CONSENSUS_NEWER = 8192;
509 const char TRY_DIFF_FOR_CONSENSUS_NEWER_NAME[] =
510 "try-diff-for-consensus-newer-than";
512 int flav = FLAV_NS;
513 if (resource)
514 flav = networkstatus_parse_flavor_name(resource);
516 int32_t max_age_for_diff = 3600 *
517 networkstatus_get_param(NULL,
518 TRY_DIFF_FOR_CONSENSUS_NEWER_NAME,
519 DEFAULT_TRY_DIFF_FOR_CONSENSUS_NEWER,
520 MIN_TRY_DIFF_FOR_CONSENSUS_NEWER,
521 MAX_TRY_DIFF_FOR_CONSENSUS_NEWER);
523 if (flav != -1) {
524 /* IF we have a parsed consensus of this type, we can do an
525 * if-modified-time based on it. */
526 networkstatus_t *v;
527 v = networkstatus_get_latest_consensus_by_flavor(flav);
528 if (v) {
529 /* In networks with particularly short V3AuthVotingIntervals,
530 * ask for the consensus if it's been modified since half the
531 * V3AuthVotingInterval of the most recent consensus. */
532 time_t ims_delay = DEFAULT_IF_MODIFIED_SINCE_DELAY;
533 if (v->fresh_until > v->valid_after
534 && ims_delay > (v->fresh_until - v->valid_after)/2) {
535 ims_delay = (v->fresh_until - v->valid_after)/2;
537 if_modified_since = v->valid_after + ims_delay;
538 if (v->valid_after >= approx_time() - max_age_for_diff) {
539 memcpy(or_diff_from, v->digest_sha3_as_signed, DIGEST256_LEN);
540 or_diff_from_is_set = 1;
543 } else {
544 /* Otherwise it might be a consensus we don't parse, but which we
545 * do cache. Look at the cached copy, perhaps. */
546 cached_dir_t *cd = dirserv_get_consensus(resource);
547 /* We have no method of determining the voting interval from an
548 * unparsed consensus, so we use the default. */
549 if (cd) {
550 if_modified_since = cd->published + DEFAULT_IF_MODIFIED_SINCE_DELAY;
551 if (cd->published >= approx_time() - max_age_for_diff) {
552 memcpy(or_diff_from, cd->digest_sha3_as_signed, DIGEST256_LEN);
553 or_diff_from_is_set = 1;
558 if (if_modified_since > 0)
559 directory_request_set_if_modified_since(req, if_modified_since);
560 if (or_diff_from_is_set) {
561 char hex[HEX_DIGEST256_LEN + 1];
562 base16_encode(hex, sizeof(hex),
563 (const char*)or_diff_from, sizeof(or_diff_from));
564 directory_request_add_header(req, X_OR_DIFF_FROM_CONSENSUS_HEADER, hex);
568 /** Start a connection to a random running directory server, using
569 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
570 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
571 * Use <b>pds_flags</b> as arguments to router_pick_directory_server()
572 * or router_pick_trusteddirserver().
574 MOCK_IMPL(void,
575 directory_get_from_dirserver,(
576 uint8_t dir_purpose,
577 uint8_t router_purpose,
578 const char *resource,
579 int pds_flags,
580 download_want_authority_t want_authority))
582 const routerstatus_t *rs = NULL;
583 const or_options_t *options = get_options();
584 int prefer_authority = (directory_fetches_from_authorities(options)
585 || want_authority == DL_WANT_AUTHORITY);
586 int require_authority = 0;
587 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose,
588 resource);
589 dirinfo_type_t type = dir_fetch_type(dir_purpose, router_purpose, resource);
591 if (type == NO_DIRINFO)
592 return;
594 if (!options->FetchServerDescriptors)
595 return;
597 circuit_guard_state_t *guard_state = NULL;
598 if (!get_via_tor) {
599 if (options->UseBridges && !(type & BRIDGE_DIRINFO)) {
600 /* We want to ask a running bridge for which we have a descriptor.
602 * When we ask choose_random_entry() for a bridge, we specify what
603 * sort of dir fetch we'll be doing, so it won't return a bridge
604 * that can't answer our question.
606 const node_t *node = guards_choose_dirguard(&guard_state);
607 if (node && node->ri) {
608 /* every bridge has a routerinfo. */
609 routerinfo_t *ri = node->ri;
610 /* clients always make OR connections to bridges */
611 tor_addr_port_t or_ap;
612 directory_request_t *req = directory_request_new(dir_purpose);
613 /* we are willing to use a non-preferred address if we need to */
614 fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0,
615 &or_ap);
616 directory_request_set_or_addr_port(req, &or_ap);
617 directory_request_set_directory_id_digest(req,
618 ri->cache_info.identity_digest);
619 directory_request_set_router_purpose(req, router_purpose);
620 directory_request_set_resource(req, resource);
621 if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS)
622 dir_consensus_request_set_additional_headers(req, resource);
623 directory_request_set_guard_state(req, guard_state);
624 directory_initiate_request(req);
625 directory_request_free(req);
626 } else {
627 if (guard_state) {
628 entry_guard_cancel(&guard_state);
630 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
631 "nodes are available yet.");
634 return;
635 } else {
636 if (prefer_authority || (type & BRIDGE_DIRINFO)) {
637 /* only ask authdirservers, and don't ask myself */
638 rs = router_pick_trusteddirserver(type, pds_flags);
639 if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
640 PDS_NO_EXISTING_MICRODESC_FETCH))) {
641 /* We don't want to fetch from any authorities that we're currently
642 * fetching server descriptors from, and we got no match. Did we
643 * get no match because all the authorities have connections
644 * fetching server descriptors (in which case we should just
645 * return,) or because all the authorities are down or on fire or
646 * unreachable or something (in which case we should go on with
647 * our fallback code)? */
648 pds_flags &= ~(PDS_NO_EXISTING_SERVERDESC_FETCH|
649 PDS_NO_EXISTING_MICRODESC_FETCH);
650 rs = router_pick_trusteddirserver(type, pds_flags);
651 if (rs) {
652 log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
653 "are in use.");
654 return;
657 if (rs == NULL && require_authority) {
658 log_info(LD_DIR, "No authorities were available for %s: will try "
659 "later.", dir_conn_purpose_to_string(dir_purpose));
660 return;
663 if (!rs && !(type & BRIDGE_DIRINFO)) {
664 rs = directory_pick_generic_dirserver(type, pds_flags,
665 dir_purpose,
666 &guard_state);
667 if (!rs)
668 get_via_tor = 1; /* last resort: try routing it via Tor */
673 if (get_via_tor) {
674 /* Never use fascistfirewall; we're going via Tor. */
675 pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
676 rs = router_pick_directory_server(type, pds_flags);
679 /* If we have any hope of building an indirect conn, we know some router
680 * descriptors. If (rs==NULL), we can't build circuits anyway, so
681 * there's no point in falling back to the authorities in this case. */
682 if (rs) {
683 const dir_indirection_t indirection =
684 get_via_tor ? DIRIND_ANONYMOUS : DIRIND_ONEHOP;
685 directory_request_t *req = directory_request_new(dir_purpose);
686 directory_request_set_routerstatus(req, rs);
687 directory_request_set_router_purpose(req, router_purpose);
688 directory_request_set_indirection(req, indirection);
689 directory_request_set_resource(req, resource);
690 if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS)
691 dir_consensus_request_set_additional_headers(req, resource);
692 if (guard_state)
693 directory_request_set_guard_state(req, guard_state);
694 directory_initiate_request(req);
695 directory_request_free(req);
696 } else {
697 log_notice(LD_DIR,
698 "While fetching directory info, "
699 "no running dirservers known. Will try again later. "
700 "(purpose %d)", dir_purpose);
701 if (!purpose_needs_anonymity(dir_purpose, router_purpose, resource)) {
702 /* remember we tried them all and failed. */
703 directory_all_unreachable(time(NULL));
708 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
709 * directory authority other than ourself. Only for use by authorities when
710 * searching for missing information while voting. */
711 void
712 directory_get_from_all_authorities(uint8_t dir_purpose,
713 uint8_t router_purpose,
714 const char *resource)
716 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
717 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
719 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
720 dir_server_t *, ds) {
721 if (router_digest_is_me(ds->digest))
722 continue;
723 if (!(ds->type & V3_DIRINFO))
724 continue;
725 const routerstatus_t *rs = &ds->fake_status;
726 directory_request_t *req = directory_request_new(dir_purpose);
727 directory_request_set_routerstatus(req, rs);
728 directory_request_set_router_purpose(req, router_purpose);
729 directory_request_set_resource(req, resource);
730 directory_initiate_request(req);
731 directory_request_free(req);
732 } SMARTLIST_FOREACH_END(ds);
735 /** Return true iff <b>ind</b> requires a multihop circuit. */
736 static int
737 dirind_is_anon(dir_indirection_t ind)
739 return ind == DIRIND_ANON_DIRPORT || ind == DIRIND_ANONYMOUS;
742 /* Choose reachable OR and Dir addresses and ports from status, copying them
743 * into use_or_ap and use_dir_ap. If indirection is anonymous, then we're
744 * connecting via another relay, so choose the primary IPv4 address and ports.
746 * status should have at least one reachable address, if we can't choose a
747 * reachable address, warn and return -1. Otherwise, return 0.
749 static int
750 directory_choose_address_routerstatus(const routerstatus_t *status,
751 dir_indirection_t indirection,
752 tor_addr_port_t *use_or_ap,
753 tor_addr_port_t *use_dir_ap)
755 tor_assert(status != NULL);
756 tor_assert(use_or_ap != NULL);
757 tor_assert(use_dir_ap != NULL);
759 const or_options_t *options = get_options();
760 int have_or = 0, have_dir = 0;
762 /* We expect status to have at least one reachable address if we're
763 * connecting to it directly.
765 * Therefore, we can simply use the other address if the one we want isn't
766 * allowed by the firewall.
768 * (When Tor uploads and downloads a hidden service descriptor, it uses
769 * DIRIND_ANONYMOUS, except for Tor2Web, which uses DIRIND_ONEHOP.
770 * So this code will only modify the address for Tor2Web's HS descriptor
771 * fetches. Even Single Onion Servers (NYI) use DIRIND_ANONYMOUS, to avoid
772 * HSDirs denying service by rejecting descriptors.)
775 /* Initialise the OR / Dir addresses */
776 tor_addr_make_null(&use_or_ap->addr, AF_UNSPEC);
777 use_or_ap->port = 0;
778 tor_addr_make_null(&use_dir_ap->addr, AF_UNSPEC);
779 use_dir_ap->port = 0;
781 /* ORPort connections */
782 if (indirection == DIRIND_ANONYMOUS) {
783 if (status->addr) {
784 /* Since we're going to build a 3-hop circuit and ask the 2nd relay
785 * to extend to this address, always use the primary (IPv4) OR address */
786 tor_addr_from_ipv4h(&use_or_ap->addr, status->addr);
787 use_or_ap->port = status->or_port;
788 have_or = 1;
790 } else if (indirection == DIRIND_ONEHOP) {
791 /* We use an IPv6 address if we have one and we prefer it.
792 * Use the preferred address and port if they are reachable, otherwise,
793 * use the alternate address and port (if any).
795 have_or = fascist_firewall_choose_address_rs(status,
796 FIREWALL_OR_CONNECTION, 0,
797 use_or_ap);
800 /* DirPort connections
801 * DIRIND_ONEHOP uses ORPort, but may fall back to the DirPort on relays */
802 if (indirection == DIRIND_DIRECT_CONN ||
803 indirection == DIRIND_ANON_DIRPORT ||
804 (indirection == DIRIND_ONEHOP
805 && !directory_must_use_begindir(options))) {
806 have_dir = fascist_firewall_choose_address_rs(status,
807 FIREWALL_DIR_CONNECTION, 0,
808 use_dir_ap);
811 /* We rejected all addresses in the relay's status. This means we can't
812 * connect to it. */
813 if (!have_or && !have_dir) {
814 static int logged_backtrace = 0;
815 log_info(LD_BUG, "Rejected all OR and Dir addresses from %s when "
816 "launching an outgoing directory connection to: IPv4 %s OR %d "
817 "Dir %d IPv6 %s OR %d Dir %d", routerstatus_describe(status),
818 fmt_addr32(status->addr), status->or_port,
819 status->dir_port, fmt_addr(&status->ipv6_addr),
820 status->ipv6_orport, status->dir_port);
821 if (!logged_backtrace) {
822 log_backtrace(LOG_INFO, LD_BUG, "Addresses came from");
823 logged_backtrace = 1;
825 return -1;
828 return 0;
831 /** Return true iff <b>conn</b> is the client side of a directory connection
832 * we launched to ourself in order to determine the reachability of our
833 * dir_port. */
834 static int
835 directory_conn_is_self_reachability_test(dir_connection_t *conn)
837 if (conn->requested_resource &&
838 !strcmpstart(conn->requested_resource,"authority")) {
839 const routerinfo_t *me = router_get_my_routerinfo();
840 if (me &&
841 router_digest_is_me(conn->identity_digest) &&
842 tor_addr_eq_ipv4h(&conn->base_.addr, me->addr) && /*XXXX prop 118*/
843 me->dir_port == conn->base_.port)
844 return 1;
846 return 0;
849 /** Called when we are unable to complete the client's request to a directory
850 * server due to a network error: Mark the router as down and try again if
851 * possible.
853 static void
854 connection_dir_request_failed(dir_connection_t *conn)
856 if (conn->guard_state) {
857 /* We haven't seen a success on this guard state, so consider it to have
858 * failed. */
859 entry_guard_failed(&conn->guard_state);
861 if (directory_conn_is_self_reachability_test(conn)) {
862 return; /* this was a test fetch. don't retry. */
864 if (!entry_list_is_constrained(get_options()))
865 router_set_status(conn->identity_digest, 0); /* don't try this one again */
866 if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
867 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
868 log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
869 "directory server at '%s'; retrying",
870 conn->base_.address);
871 if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
872 connection_dir_bridge_routerdesc_failed(conn);
873 connection_dir_download_routerdesc_failed(conn);
874 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
875 if (conn->requested_resource)
876 networkstatus_consensus_download_failed(0, conn->requested_resource);
877 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
878 log_info(LD_DIR, "Giving up on certificate fetch from directory server "
879 "at '%s'; retrying",
880 conn->base_.address);
881 connection_dir_download_cert_failed(conn, 0);
882 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
883 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
884 conn->base_.address);
885 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
886 log_info(LD_DIR, "Giving up downloading votes from '%s'",
887 conn->base_.address);
888 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
889 log_info(LD_DIR, "Giving up on downloading microdescriptors from "
890 "directory server at '%s'; will retry", conn->base_.address);
891 connection_dir_download_routerdesc_failed(conn);
895 /** Helper: Attempt to fetch directly the descriptors of each bridge
896 * listed in <b>failed</b>.
898 static void
899 connection_dir_retry_bridges(smartlist_t *descs)
901 char digest[DIGEST_LEN];
902 SMARTLIST_FOREACH(descs, const char *, cp,
904 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) != DIGEST_LEN) {
905 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
906 escaped(cp));
907 continue;
909 retry_bridge_descriptor_fetch_directly(digest);
913 /** Called when an attempt to download one or more router descriptors
914 * or extra-info documents on connection <b>conn</b> failed.
916 static void
917 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
919 /* No need to increment the failure count for routerdescs, since
920 * it's not their fault. */
922 /* No need to relaunch descriptor downloads here: we already do it
923 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
924 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
925 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
926 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
928 (void) conn;
931 /** Called when an attempt to download a bridge's routerdesc from
932 * one of the authorities failed due to a network error. If
933 * possible attempt to download descriptors from the bridge directly.
935 static void
936 connection_dir_bridge_routerdesc_failed(dir_connection_t *conn)
938 smartlist_t *which = NULL;
940 /* Requests for bridge descriptors are in the form 'fp/', so ignore
941 anything else. */
942 if (!conn->requested_resource || strcmpstart(conn->requested_resource,"fp/"))
943 return;
945 which = smartlist_new();
946 dir_split_resource_into_fingerprints(conn->requested_resource
947 + strlen("fp/"),
948 which, NULL, 0);
950 tor_assert(conn->base_.purpose != DIR_PURPOSE_FETCH_EXTRAINFO);
951 if (smartlist_len(which)) {
952 connection_dir_retry_bridges(which);
953 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
955 smartlist_free(which);
958 /** Called when an attempt to fetch a certificate fails. */
959 static void
960 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
962 const char *fp_pfx = "fp/";
963 const char *fpsk_pfx = "fp-sk/";
964 smartlist_t *failed;
965 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
967 if (!conn->requested_resource)
968 return;
969 failed = smartlist_new();
971 * We have two cases download by fingerprint (resource starts
972 * with "fp/") or download by fingerprint/signing key pair
973 * (resource starts with "fp-sk/").
975 if (!strcmpstart(conn->requested_resource, fp_pfx)) {
976 /* Download by fingerprint case */
977 dir_split_resource_into_fingerprints(conn->requested_resource +
978 strlen(fp_pfx),
979 failed, NULL, DSR_HEX);
980 SMARTLIST_FOREACH_BEGIN(failed, char *, cp) {
981 /* Null signing key digest indicates download by fp only */
982 authority_cert_dl_failed(cp, NULL, status);
983 tor_free(cp);
984 } SMARTLIST_FOREACH_END(cp);
985 } else if (!strcmpstart(conn->requested_resource, fpsk_pfx)) {
986 /* Download by (fp,sk) pairs */
987 dir_split_resource_into_fingerprint_pairs(conn->requested_resource +
988 strlen(fpsk_pfx), failed);
989 SMARTLIST_FOREACH_BEGIN(failed, fp_pair_t *, cp) {
990 authority_cert_dl_failed(cp->first, cp->second, status);
991 tor_free(cp);
992 } SMARTLIST_FOREACH_END(cp);
993 } else {
994 log_warn(LD_DIR,
995 "Don't know what to do with failure for cert fetch %s",
996 conn->requested_resource);
999 smartlist_free(failed);
1001 update_certificate_downloads(time(NULL));
1004 /* Should this tor instance only use begindir for all its directory requests?
1007 directory_must_use_begindir(const or_options_t *options)
1009 /* Clients, onion services, and bridges must use begindir,
1010 * relays and authorities do not have to */
1011 return !public_server_mode(options);
1014 struct directory_request_t {
1016 * These fields specify which directory we're contacting. Routerstatus,
1017 * if present, overrides the other fields.
1019 * @{ */
1020 tor_addr_port_t or_addr_port;
1021 tor_addr_port_t dir_addr_port;
1022 char digest[DIGEST_LEN];
1024 const routerstatus_t *routerstatus;
1025 /** @} */
1026 /** One of DIR_PURPOSE_* other than DIR_PURPOSE_SERVER. Describes what
1027 * kind of operation we'll be doing (upload/download), and of what kind
1028 * of document. */
1029 uint8_t dir_purpose;
1030 /** One of ROUTER_PURPOSE_*; used for uploads and downloads of routerinfo
1031 * and extrainfo docs. */
1032 uint8_t router_purpose;
1033 /** Enum: determines whether to anonymize, and whether to use dirport or
1034 * orport. */
1035 dir_indirection_t indirection;
1036 /** Alias to the variable part of the URL for this request */
1037 const char *resource;
1038 /** Alias to the payload to upload (if any) */
1039 const char *payload;
1040 /** Number of bytes to upload from payload</b> */
1041 size_t payload_len;
1042 /** Value to send in an if-modified-since header, or 0 for none. */
1043 time_t if_modified_since;
1044 /** Hidden-service-specific information v2. */
1045 const rend_data_t *rend_query;
1046 /** Extra headers to append to the request */
1047 config_line_t *additional_headers;
1048 /** Hidden-service-specific information for v3+. */
1049 const hs_ident_dir_conn_t *hs_ident;
1050 /** Used internally to directory.c: gets informed when the attempt to
1051 * connect to the directory succeeds or fails, if that attempt bears on the
1052 * directory's usability as a directory guard. */
1053 circuit_guard_state_t *guard_state;
1056 /** Evaluate the situation and decide if we should use an encrypted
1057 * "begindir-style" connection for this directory request.
1058 * 0) If there is no DirPort, yes.
1059 * 1) If or_port is 0, or it's a direct conn and or_port is firewalled
1060 * or we're a dir mirror, no.
1061 * 2) If we prefer to avoid begindir conns, and we're not fetching or
1062 * publishing a bridge relay descriptor, no.
1063 * 3) Else yes.
1064 * If returning 0, return in *reason why we can't use begindir.
1065 * reason must not be NULL.
1067 static int
1068 directory_command_should_use_begindir(const or_options_t *options,
1069 const directory_request_t *req,
1070 const char **reason)
1072 const tor_addr_t *or_addr = &req->or_addr_port.addr;
1073 //const tor_addr_t *dir_addr = &req->dir_addr_port.addr;
1074 const int or_port = req->or_addr_port.port;
1075 const int dir_port = req->dir_addr_port.port;
1077 const dir_indirection_t indirection = req->indirection;
1079 tor_assert(reason);
1080 *reason = NULL;
1082 /* Reasons why we must use begindir */
1083 if (!dir_port) {
1084 *reason = "(using begindir - directory with no DirPort)";
1085 return 1; /* We don't know a DirPort -- must begindir. */
1087 /* Reasons why we can't possibly use begindir */
1088 if (!or_port) {
1089 *reason = "directory with unknown ORPort";
1090 return 0; /* We don't know an ORPort -- no chance. */
1092 if (indirection == DIRIND_DIRECT_CONN ||
1093 indirection == DIRIND_ANON_DIRPORT) {
1094 *reason = "DirPort connection";
1095 return 0;
1097 if (indirection == DIRIND_ONEHOP) {
1098 /* We're firewalled and want a direct OR connection */
1099 if (!fascist_firewall_allows_address_addr(or_addr, or_port,
1100 FIREWALL_OR_CONNECTION, 0, 0)) {
1101 *reason = "ORPort not reachable";
1102 return 0;
1105 /* Reasons why we want to avoid using begindir */
1106 if (indirection == DIRIND_ONEHOP) {
1107 if (!directory_must_use_begindir(options)) {
1108 *reason = "in relay mode";
1109 return 0;
1112 /* DIRIND_ONEHOP on a client, or DIRIND_ANONYMOUS
1114 *reason = "(using begindir)";
1115 return 1;
1119 * Create and return a new directory_request_t with purpose
1120 * <b>dir_purpose</b>.
1122 directory_request_t *
1123 directory_request_new(uint8_t dir_purpose)
1125 tor_assert(dir_purpose >= DIR_PURPOSE_MIN_);
1126 tor_assert(dir_purpose <= DIR_PURPOSE_MAX_);
1127 tor_assert(dir_purpose != DIR_PURPOSE_SERVER);
1128 tor_assert(dir_purpose != DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2);
1129 tor_assert(dir_purpose != DIR_PURPOSE_HAS_FETCHED_HSDESC);
1131 directory_request_t *result = tor_malloc_zero(sizeof(*result));
1132 tor_addr_make_null(&result->or_addr_port.addr, AF_INET);
1133 result->or_addr_port.port = 0;
1134 tor_addr_make_null(&result->dir_addr_port.addr, AF_INET);
1135 result->dir_addr_port.port = 0;
1136 result->dir_purpose = dir_purpose;
1137 result->router_purpose = ROUTER_PURPOSE_GENERAL;
1138 result->indirection = DIRIND_ONEHOP;
1139 return result;
1142 * Release all resources held by <b>req</b>.
1144 void
1145 directory_request_free(directory_request_t *req)
1147 if (req == NULL)
1148 return;
1149 config_free_lines(req->additional_headers);
1150 tor_free(req);
1153 * Set the address and OR port to use for this directory request. If there is
1154 * no OR port, we'll have to connect over the dirport. (If there are both,
1155 * the indirection setting determins which to use.)
1157 void
1158 directory_request_set_or_addr_port(directory_request_t *req,
1159 const tor_addr_port_t *p)
1161 memcpy(&req->or_addr_port, p, sizeof(*p));
1164 * Set the address and dirport to use for this directory request. If there
1165 * is no dirport, we'll have to connect over the OR port. (If there are both,
1166 * the indirection setting determins which to use.)
1168 void
1169 directory_request_set_dir_addr_port(directory_request_t *req,
1170 const tor_addr_port_t *p)
1172 memcpy(&req->dir_addr_port, p, sizeof(*p));
1175 * Set the RSA identity digest of the directory to use for this directory
1176 * request.
1178 void
1179 directory_request_set_directory_id_digest(directory_request_t *req,
1180 const char *digest)
1182 memcpy(req->digest, digest, DIGEST_LEN);
1185 * Set the router purpose associated with uploaded and downloaded router
1186 * descriptors and extrainfo documents in this directory request. The purpose
1187 * must be one of ROUTER_PURPOSE_GENERAL (the default) or
1188 * ROUTER_PURPOSE_BRIDGE.
1190 void
1191 directory_request_set_router_purpose(directory_request_t *req,
1192 uint8_t router_purpose)
1194 tor_assert(router_purpose == ROUTER_PURPOSE_GENERAL ||
1195 router_purpose == ROUTER_PURPOSE_BRIDGE);
1196 // assert that it actually makes sense to set this purpose, given
1197 // the dir_purpose.
1198 req->router_purpose = router_purpose;
1201 * Set the indirection to be used for the directory request. The indirection
1202 * parameter configures whether to connect to a DirPort or ORPort, and whether
1203 * to anonymize the connection. DIRIND_ONEHOP (use ORPort, don't anonymize)
1204 * is the default. See dir_indirection_t for more information.
1206 void
1207 directory_request_set_indirection(directory_request_t *req,
1208 dir_indirection_t indirection)
1210 req->indirection = indirection;
1214 * Set a pointer to the resource to request from a directory. Different
1215 * request types use resources to indicate different components of their URL.
1216 * Note that only an alias to <b>resource</b> is stored, so the
1217 * <b>resource</b> must outlive the request.
1219 void
1220 directory_request_set_resource(directory_request_t *req,
1221 const char *resource)
1223 req->resource = resource;
1226 * Set a pointer to the payload to include with this directory request, along
1227 * with its length. Note that only an alias to <b>payload</b> is stored, so
1228 * the <b>payload</b> must outlive the request.
1230 void
1231 directory_request_set_payload(directory_request_t *req,
1232 const char *payload,
1233 size_t payload_len)
1235 tor_assert(DIR_PURPOSE_IS_UPLOAD(req->dir_purpose));
1237 req->payload = payload;
1238 req->payload_len = payload_len;
1241 * Set an if-modified-since date to send along with the request. The
1242 * default is 0 (meaning, send no if-modified-since header).
1244 void
1245 directory_request_set_if_modified_since(directory_request_t *req,
1246 time_t if_modified_since)
1248 req->if_modified_since = if_modified_since;
1251 /** Include a header of name <b>key</b> with content <b>val</b> in the
1252 * request. Neither may include newlines or other odd characters. Their
1253 * ordering is not currently guaranteed.
1255 * Note that, as elsewhere in this module, header keys include a trailing
1256 * colon and space.
1258 void
1259 directory_request_add_header(directory_request_t *req,
1260 const char *key,
1261 const char *val)
1263 config_line_prepend(&req->additional_headers, key, val);
1266 * Set an object containing HS data to be associated with this request. Note
1267 * that only an alias to <b>query</b> is stored, so the <b>query</b> object
1268 * must outlive the request.
1270 void
1271 directory_request_set_rend_query(directory_request_t *req,
1272 const rend_data_t *query)
1274 if (query) {
1275 tor_assert(req->dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 ||
1276 req->dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2);
1278 req->rend_query = query;
1281 * Set an object containing HS connection identifier to be associated with
1282 * this request. Note that only an alias to <b>ident</b> is stored, so the
1283 * <b>ident</b> object must outlive the request.
1285 void
1286 directory_request_upload_set_hs_ident(directory_request_t *req,
1287 const hs_ident_dir_conn_t *ident)
1289 if (ident) {
1290 tor_assert(req->dir_purpose == DIR_PURPOSE_UPLOAD_HSDESC);
1292 req->hs_ident = ident;
1295 * Set an object containing HS connection identifier to be associated with
1296 * this fetch request. Note that only an alias to <b>ident</b> is stored, so
1297 * the <b>ident</b> object must outlive the request.
1299 void
1300 directory_request_fetch_set_hs_ident(directory_request_t *req,
1301 const hs_ident_dir_conn_t *ident)
1303 if (ident) {
1304 tor_assert(req->dir_purpose == DIR_PURPOSE_FETCH_HSDESC);
1306 req->hs_ident = ident;
1308 /** Set a static circuit_guard_state_t object to affliate with the request in
1309 * <b>req</b>. This object will receive notification when the attempt to
1310 * connect to the guard either succeeds or fails. */
1311 void
1312 directory_request_set_guard_state(directory_request_t *req,
1313 circuit_guard_state_t *state)
1315 req->guard_state = state;
1319 * Internal: Return true if any information for contacting the directory in
1320 * <b>req</b> has been set, other than by the routerstatus. */
1321 static int
1322 directory_request_dir_contact_info_specified(const directory_request_t *req)
1324 /* We only check for ports here, since we don't use an addr unless the port
1325 * is set */
1326 return (req->or_addr_port.port ||
1327 req->dir_addr_port.port ||
1328 ! tor_digest_is_zero(req->digest));
1332 * Set the routerstatus to use for the directory associated with this
1333 * request. If this option is set, then no other function to set the
1334 * directory's address or identity should be called.
1336 void
1337 directory_request_set_routerstatus(directory_request_t *req,
1338 const routerstatus_t *status)
1340 req->routerstatus = status;
1343 * Helper: update the addresses, ports, and identities in <b>req</b>
1344 * from the routerstatus object in <b>req</b>. Return 0 on success.
1345 * On failure, warn and return -1.
1347 static int
1348 directory_request_set_dir_from_routerstatus(directory_request_t *req)
1351 const routerstatus_t *status = req->routerstatus;
1352 if (BUG(status == NULL))
1353 return -1;
1354 const or_options_t *options = get_options();
1355 const node_t *node;
1356 tor_addr_port_t use_or_ap, use_dir_ap;
1357 const int anonymized_connection = dirind_is_anon(req->indirection);
1359 tor_assert(status != NULL);
1361 node = node_get_by_id(status->identity_digest);
1363 /* XXX The below check is wrong: !node means it's not in the consensus,
1364 * but we haven't checked if we have a descriptor for it -- and also,
1365 * we only care about the descriptor if it's a begindir-style anonymized
1366 * connection. */
1367 if (!node && anonymized_connection) {
1368 log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
1369 "don't have its router descriptor.",
1370 routerstatus_describe(status));
1371 return -1;
1374 if (options->ExcludeNodes && options->StrictNodes &&
1375 routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
1376 log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
1377 "it's in our ExcludedNodes list and StrictNodes is set. "
1378 "Skipping. This choice might make your Tor not work.",
1379 routerstatus_describe(status),
1380 dir_conn_purpose_to_string(req->dir_purpose));
1381 return -1;
1384 /* At this point, if we are a client making a direct connection to a
1385 * directory server, we have selected a server that has at least one address
1386 * allowed by ClientUseIPv4/6 and Reachable{"",OR,Dir}Addresses. This
1387 * selection uses the preference in ClientPreferIPv6{OR,Dir}Port, if
1388 * possible. (If UseBridges is set, clients always use IPv6, and prefer it
1389 * by default.)
1391 * Now choose an address that we can use to connect to the directory server.
1393 if (directory_choose_address_routerstatus(status,
1394 req->indirection, &use_or_ap,
1395 &use_dir_ap) < 0) {
1396 return -1;
1399 directory_request_set_or_addr_port(req, &use_or_ap);
1400 directory_request_set_dir_addr_port(req, &use_dir_ap);
1401 directory_request_set_directory_id_digest(req, status->identity_digest);
1402 return 0;
1406 * Launch the provided directory request, configured in <b>request</b>.
1407 * After this function is called, you can free <b>request</b>.
1409 MOCK_IMPL(void,
1410 directory_initiate_request,(directory_request_t *request))
1412 tor_assert(request);
1413 if (request->routerstatus) {
1414 tor_assert_nonfatal(
1415 ! directory_request_dir_contact_info_specified(request));
1416 if (directory_request_set_dir_from_routerstatus(request) < 0) {
1417 return;
1421 const tor_addr_port_t *or_addr_port = &request->or_addr_port;
1422 const tor_addr_port_t *dir_addr_port = &request->dir_addr_port;
1423 const char *digest = request->digest;
1424 const uint8_t dir_purpose = request->dir_purpose;
1425 const uint8_t router_purpose = request->router_purpose;
1426 const dir_indirection_t indirection = request->indirection;
1427 const char *resource = request->resource;
1428 const rend_data_t *rend_query = request->rend_query;
1429 const hs_ident_dir_conn_t *hs_ident = request->hs_ident;
1430 circuit_guard_state_t *guard_state = request->guard_state;
1432 tor_assert(or_addr_port->port || dir_addr_port->port);
1433 tor_assert(digest);
1435 dir_connection_t *conn;
1436 const or_options_t *options = get_options();
1437 int socket_error = 0;
1438 const char *begindir_reason = NULL;
1439 /* Should the connection be to a relay's OR port (and inside that we will
1440 * send our directory request)? */
1441 const int use_begindir =
1442 directory_command_should_use_begindir(options, request, &begindir_reason);
1444 /* Will the connection go via a three-hop Tor circuit? Note that this
1445 * is separate from whether it will use_begindir. */
1446 const int anonymized_connection = dirind_is_anon(indirection);
1448 /* What is the address we want to make the directory request to? If
1449 * we're making a begindir request this is the ORPort of the relay
1450 * we're contacting; if not a begindir request, this is its DirPort.
1451 * Note that if anonymized_connection is true, we won't be initiating
1452 * a connection directly to this address. */
1453 tor_addr_t addr;
1454 tor_addr_copy(&addr, &(use_begindir ? or_addr_port : dir_addr_port)->addr);
1455 uint16_t port = (use_begindir ? or_addr_port : dir_addr_port)->port;
1457 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
1458 anonymized_connection, use_begindir);
1460 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
1462 if (purpose_needs_anonymity(dir_purpose, router_purpose, resource)) {
1463 tor_assert(anonymized_connection ||
1464 rend_non_anonymous_mode_enabled(options));
1467 /* use encrypted begindir connections for everything except relays
1468 * this provides better protection for directory fetches */
1469 if (!use_begindir && directory_must_use_begindir(options)) {
1470 log_warn(LD_BUG, "Client could not use begindir connection: %s",
1471 begindir_reason ? begindir_reason : "(NULL)");
1472 return;
1475 /* ensure that we don't make direct connections when a SOCKS server is
1476 * configured. */
1477 if (!anonymized_connection && !use_begindir && !options->HTTPProxy &&
1478 (options->Socks4Proxy || options->Socks5Proxy)) {
1479 log_warn(LD_DIR, "Cannot connect to a directory server through a "
1480 "SOCKS proxy!");
1481 return;
1484 /* Make sure that the destination addr and port we picked is viable. */
1485 if (!port || tor_addr_is_null(&addr)) {
1486 static int logged_backtrace = 0;
1487 log_warn(LD_DIR,
1488 "Cannot make an outgoing %sconnection without a remote %sPort.",
1489 use_begindir ? "begindir " : "",
1490 use_begindir ? "OR" : "Dir");
1491 if (!logged_backtrace) {
1492 log_backtrace(LOG_INFO, LD_BUG, "Address came from");
1493 logged_backtrace = 1;
1495 return;
1498 conn = dir_connection_new(tor_addr_family(&addr));
1500 /* set up conn so it's got all the data we need to remember */
1501 tor_addr_copy(&conn->base_.addr, &addr);
1502 conn->base_.port = port;
1503 conn->base_.address = tor_addr_to_str_dup(&addr);
1504 memcpy(conn->identity_digest, digest, DIGEST_LEN);
1506 conn->base_.purpose = dir_purpose;
1507 conn->router_purpose = router_purpose;
1509 /* give it an initial state */
1510 conn->base_.state = DIR_CONN_STATE_CONNECTING;
1512 /* decide whether we can learn our IP address from this conn */
1513 /* XXXX This is a bad name for this field now. */
1514 conn->dirconn_direct = !anonymized_connection;
1516 /* copy rendezvous data, if any */
1517 if (rend_query) {
1518 /* We can't have both v2 and v3+ identifier. */
1519 tor_assert_nonfatal(!hs_ident);
1520 conn->rend_data = rend_data_dup(rend_query);
1522 if (hs_ident) {
1523 /* We can't have both v2 and v3+ identifier. */
1524 tor_assert_nonfatal(!rend_query);
1525 conn->hs_ident = hs_ident_dir_conn_dup(hs_ident);
1528 if (!anonymized_connection && !use_begindir) {
1529 /* then we want to connect to dirport directly */
1531 if (options->HTTPProxy) {
1532 tor_addr_copy(&addr, &options->HTTPProxyAddr);
1533 port = options->HTTPProxyPort;
1536 // In this case we should not have picked a directory guard.
1537 if (BUG(guard_state)) {
1538 entry_guard_cancel(&guard_state);
1541 switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr,
1542 port, &socket_error)) {
1543 case -1:
1544 connection_mark_for_close(TO_CONN(conn));
1545 return;
1546 case 1:
1547 /* start flushing conn */
1548 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
1549 /* fall through */
1550 case 0:
1551 /* queue the command on the outbuf */
1552 directory_send_command(conn, 1, request);
1553 connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT);
1554 /* writable indicates finish, readable indicates broken link,
1555 error indicates broken link in windowsland. */
1557 } else {
1558 /* We will use a Tor circuit (maybe 1-hop, maybe 3-hop, maybe with
1559 * begindir, maybe not with begindir) */
1561 entry_connection_t *linked_conn;
1563 /* Anonymized tunneled connections can never share a circuit.
1564 * One-hop directory connections can share circuits with each other
1565 * but nothing else. */
1566 int iso_flags = anonymized_connection ? ISO_STREAM : ISO_SESSIONGRP;
1568 /* If it's an anonymized connection, remember the fact that we
1569 * wanted it for later: maybe we'll want it again soon. */
1570 if (anonymized_connection && use_begindir)
1571 rep_hist_note_used_internal(time(NULL), 0, 1);
1572 else if (anonymized_connection && !use_begindir)
1573 rep_hist_note_used_port(time(NULL), conn->base_.port);
1575 // In this case we should not have a directory guard; we'll
1576 // get a regular guard later when we build the circuit.
1577 if (BUG(anonymized_connection && guard_state)) {
1578 entry_guard_cancel(&guard_state);
1581 conn->guard_state = guard_state;
1583 /* make an AP connection
1584 * populate it and add it at the right state
1585 * hook up both sides
1587 linked_conn =
1588 connection_ap_make_link(TO_CONN(conn),
1589 conn->base_.address, conn->base_.port,
1590 digest,
1591 SESSION_GROUP_DIRCONN, iso_flags,
1592 use_begindir, !anonymized_connection);
1593 if (!linked_conn) {
1594 log_warn(LD_NET,"Making tunnel to dirserver failed.");
1595 connection_mark_for_close(TO_CONN(conn));
1596 return;
1599 if (connection_add(TO_CONN(conn)) < 0) {
1600 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
1601 connection_mark_for_close(TO_CONN(conn));
1602 return;
1604 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
1605 /* queue the command on the outbuf */
1606 directory_send_command(conn, 0, request);
1608 connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
1609 connection_start_reading(ENTRY_TO_CONN(linked_conn));
1613 /** Return true iff anything we say on <b>conn</b> is being encrypted before
1614 * we send it to the client/server. */
1616 connection_dir_is_encrypted(const dir_connection_t *conn)
1618 /* Right now it's sufficient to see if conn is or has been linked, since
1619 * the only thing it could be linked to is an edge connection on a
1620 * circuit, and the only way it could have been unlinked is at the edge
1621 * connection getting closed.
1623 return TO_CONN(conn)->linked;
1626 /** Helper for sorting
1628 * sort strings alphabetically
1630 static int
1631 compare_strs_(const void **a, const void **b)
1633 const char *s1 = *a, *s2 = *b;
1634 return strcmp(s1, s2);
1637 #define CONDITIONAL_CONSENSUS_FPR_LEN 3
1638 #if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
1639 #error "conditional consensus fingerprint length is larger than digest length"
1640 #endif
1642 /** Return the URL we should use for a consensus download.
1644 * Use the "conditional consensus downloading" feature described in
1645 * dir-spec.txt, i.e.
1646 * GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
1648 * If 'resource' is provided, it is the name of a consensus flavor to request.
1650 static char *
1651 directory_get_consensus_url(const char *resource)
1653 char *url = NULL;
1654 const char *hyphen, *flavor;
1655 if (resource==NULL || strcmp(resource, "ns")==0) {
1656 flavor = ""; /* Request ns consensuses as "", so older servers will work*/
1657 hyphen = "";
1658 } else {
1659 flavor = resource;
1660 hyphen = "-";
1664 char *authority_id_list;
1665 smartlist_t *authority_digests = smartlist_new();
1667 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
1668 dir_server_t *, ds) {
1669 char *hex;
1670 if (!(ds->type & V3_DIRINFO))
1671 continue;
1673 hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
1674 base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
1675 ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN);
1676 smartlist_add(authority_digests, hex);
1677 } SMARTLIST_FOREACH_END(ds);
1678 smartlist_sort(authority_digests, compare_strs_);
1679 authority_id_list = smartlist_join_strings(authority_digests,
1680 "+", 0, NULL);
1682 tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s/%s.z",
1683 hyphen, flavor, authority_id_list);
1685 SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
1686 smartlist_free(authority_digests);
1687 tor_free(authority_id_list);
1689 return url;
1693 * Copies the ipv6 from source to destination, subject to buffer size limit
1694 * size. If decorate is true, makes sure the copied address is decorated.
1696 static void
1697 copy_ipv6_address(char* destination, const char* source, size_t len,
1698 int decorate) {
1699 tor_assert(destination);
1700 tor_assert(source);
1702 if (decorate && source[0] != '[') {
1703 tor_snprintf(destination, len, "[%s]", source);
1704 } else {
1705 strlcpy(destination, source, len);
1709 /** Queue an appropriate HTTP command for <b>request</b> on
1710 * <b>conn</b>-\>outbuf. If <b>direct</b> is true, we're making a
1711 * non-anonymized connection to the dirport.
1713 static void
1714 directory_send_command(dir_connection_t *conn,
1715 const int direct,
1716 const directory_request_t *req)
1718 tor_assert(req);
1719 const int purpose = req->dir_purpose;
1720 const char *resource = req->resource;
1721 const char *payload = req->payload;
1722 const size_t payload_len = req->payload_len;
1723 const time_t if_modified_since = req->if_modified_since;
1724 const int anonymized_connection = dirind_is_anon(req->indirection);
1726 char proxystring[256];
1727 char hoststring[128];
1728 /* NEEDS to be the same size hoststring.
1729 Will be decorated with brackets around it if it is ipv6. */
1730 char decorated_address[128];
1731 smartlist_t *headers = smartlist_new();
1732 char *url;
1733 char *accept_encoding;
1734 size_t url_len;
1735 char request[8192];
1736 size_t request_len, total_request_len = 0;
1737 const char *httpcommand = NULL;
1739 tor_assert(conn);
1740 tor_assert(conn->base_.type == CONN_TYPE_DIR);
1742 tor_free(conn->requested_resource);
1743 if (resource)
1744 conn->requested_resource = tor_strdup(resource);
1746 /* decorate the ip address if it is ipv6 */
1747 if (strchr(conn->base_.address, ':')) {
1748 copy_ipv6_address(decorated_address, conn->base_.address,
1749 sizeof(decorated_address), 1);
1750 } else {
1751 strlcpy(decorated_address, conn->base_.address, sizeof(decorated_address));
1754 /* come up with a string for which Host: we want */
1755 if (conn->base_.port == 80) {
1756 strlcpy(hoststring, decorated_address, sizeof(hoststring));
1757 } else {
1758 tor_snprintf(hoststring, sizeof(hoststring), "%s:%d",
1759 decorated_address, conn->base_.port);
1762 /* Format if-modified-since */
1763 if (if_modified_since) {
1764 char b[RFC1123_TIME_LEN+1];
1765 format_rfc1123_time(b, if_modified_since);
1766 smartlist_add_asprintf(headers, "If-Modified-Since: %s\r\n", b);
1769 /* come up with some proxy lines, if we're using one. */
1770 if (direct && get_options()->HTTPProxy) {
1771 char *base64_authenticator=NULL;
1772 const char *authenticator = get_options()->HTTPProxyAuthenticator;
1774 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
1775 if (authenticator) {
1776 base64_authenticator = alloc_http_authenticator(authenticator);
1777 if (!base64_authenticator)
1778 log_warn(LD_BUG, "Encoding http authenticator failed");
1780 if (base64_authenticator) {
1781 smartlist_add_asprintf(headers,
1782 "Proxy-Authorization: Basic %s\r\n",
1783 base64_authenticator);
1784 tor_free(base64_authenticator);
1786 } else {
1787 proxystring[0] = 0;
1790 if (! anonymized_connection) {
1791 /* Add Accept-Encoding. */
1792 accept_encoding = accept_encoding_header();
1793 smartlist_add_asprintf(headers, "Accept-Encoding: %s\r\n",
1794 accept_encoding);
1795 tor_free(accept_encoding);
1798 /* Add additional headers, if any */
1800 config_line_t *h;
1801 for (h = req->additional_headers; h; h = h->next) {
1802 smartlist_add_asprintf(headers, "%s%s\r\n", h->key, h->value);
1806 switch (purpose) {
1807 case DIR_PURPOSE_FETCH_CONSENSUS:
1808 /* resource is optional. If present, it's a flavor name */
1809 tor_assert(!payload);
1810 httpcommand = "GET";
1811 url = directory_get_consensus_url(resource);
1812 log_info(LD_DIR, "Downloading consensus from %s using %s",
1813 hoststring, url);
1814 break;
1815 case DIR_PURPOSE_FETCH_CERTIFICATE:
1816 tor_assert(resource);
1817 tor_assert(!payload);
1818 httpcommand = "GET";
1819 tor_asprintf(&url, "/tor/keys/%s", resource);
1820 break;
1821 case DIR_PURPOSE_FETCH_STATUS_VOTE:
1822 tor_assert(resource);
1823 tor_assert(!payload);
1824 httpcommand = "GET";
1825 tor_asprintf(&url, "/tor/status-vote/next/%s.z", resource);
1826 break;
1827 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
1828 tor_assert(!resource);
1829 tor_assert(!payload);
1830 httpcommand = "GET";
1831 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
1832 break;
1833 case DIR_PURPOSE_FETCH_SERVERDESC:
1834 tor_assert(resource);
1835 httpcommand = "GET";
1836 tor_asprintf(&url, "/tor/server/%s", resource);
1837 break;
1838 case DIR_PURPOSE_FETCH_EXTRAINFO:
1839 tor_assert(resource);
1840 httpcommand = "GET";
1841 tor_asprintf(&url, "/tor/extra/%s", resource);
1842 break;
1843 case DIR_PURPOSE_FETCH_MICRODESC:
1844 tor_assert(resource);
1845 httpcommand = "GET";
1846 tor_asprintf(&url, "/tor/micro/%s", resource);
1847 break;
1848 case DIR_PURPOSE_UPLOAD_DIR: {
1849 const char *why = router_get_descriptor_gen_reason();
1850 tor_assert(!resource);
1851 tor_assert(payload);
1852 httpcommand = "POST";
1853 url = tor_strdup("/tor/");
1854 if (why) {
1855 smartlist_add_asprintf(headers, "X-Desc-Gen-Reason: %s\r\n", why);
1857 break;
1859 case DIR_PURPOSE_UPLOAD_VOTE:
1860 tor_assert(!resource);
1861 tor_assert(payload);
1862 httpcommand = "POST";
1863 url = tor_strdup("/tor/post/vote");
1864 break;
1865 case DIR_PURPOSE_UPLOAD_SIGNATURES:
1866 tor_assert(!resource);
1867 tor_assert(payload);
1868 httpcommand = "POST";
1869 url = tor_strdup("/tor/post/consensus-signature");
1870 break;
1871 case DIR_PURPOSE_FETCH_RENDDESC_V2:
1872 tor_assert(resource);
1873 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
1874 tor_assert(!payload);
1875 httpcommand = "GET";
1876 tor_asprintf(&url, "/tor/rendezvous2/%s", resource);
1877 break;
1878 case DIR_PURPOSE_FETCH_HSDESC:
1879 tor_assert(resource);
1880 tor_assert(strlen(resource) <= ED25519_BASE64_LEN);
1881 tor_assert(!payload);
1882 httpcommand = "GET";
1883 tor_asprintf(&url, "/tor/hs/3/%s", resource);
1884 break;
1885 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
1886 tor_assert(!resource);
1887 tor_assert(payload);
1888 httpcommand = "POST";
1889 url = tor_strdup("/tor/rendezvous2/publish");
1890 break;
1891 case DIR_PURPOSE_UPLOAD_HSDESC:
1892 tor_assert(resource);
1893 tor_assert(payload);
1894 httpcommand = "POST";
1895 tor_asprintf(&url, "/tor/hs/%s/publish", resource);
1896 break;
1897 default:
1898 tor_assert(0);
1899 return;
1902 /* warn in the non-tunneled case */
1903 if (direct && (strlen(proxystring) + strlen(url) >= 4096)) {
1904 log_warn(LD_BUG,
1905 "Squid does not like URLs longer than 4095 bytes, and this "
1906 "one is %d bytes long: %s%s",
1907 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
1910 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
1912 request_len = strlen(request);
1913 total_request_len += request_len;
1914 connection_buf_add(request, request_len, TO_CONN(conn));
1916 url_len = strlen(url);
1917 total_request_len += url_len;
1918 connection_buf_add(url, url_len, TO_CONN(conn));
1919 tor_free(url);
1921 if (!strcmp(httpcommand, "POST") || payload) {
1922 smartlist_add_asprintf(headers, "Content-Length: %lu\r\n",
1923 payload ? (unsigned long)payload_len : 0);
1927 char *header = smartlist_join_strings(headers, "", 0, NULL);
1928 tor_snprintf(request, sizeof(request), " HTTP/1.0\r\nHost: %s\r\n%s\r\n",
1929 hoststring, header);
1930 tor_free(header);
1933 request_len = strlen(request);
1934 total_request_len += request_len;
1935 connection_buf_add(request, request_len, TO_CONN(conn));
1937 if (payload) {
1938 /* then send the payload afterwards too */
1939 connection_buf_add(payload, payload_len, TO_CONN(conn));
1940 total_request_len += payload_len;
1943 SMARTLIST_FOREACH(headers, char *, h, tor_free(h));
1944 smartlist_free(headers);
1946 log_debug(LD_DIR,
1947 "Sent request to directory server '%s:%d': "
1948 "(purpose: %d, request size: " U64_FORMAT ", "
1949 "payload size: " U64_FORMAT ")",
1950 conn->base_.address, conn->base_.port,
1951 conn->base_.purpose,
1952 U64_PRINTF_ARG(total_request_len),
1953 U64_PRINTF_ARG(payload ? payload_len : 0));
1956 /** Parse an HTTP request string <b>headers</b> of the form
1957 * \verbatim
1958 * "\%s [http[s]://]\%s HTTP/1..."
1959 * \endverbatim
1960 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
1961 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
1962 * so it does. Return 0.
1963 * Otherwise, return -1.
1965 STATIC int
1966 parse_http_url(const char *headers, char **url)
1968 char *command = NULL;
1969 if (parse_http_command(headers, &command, url) < 0) {
1970 return -1;
1972 if (strcmpstart(*url, "/tor/")) {
1973 char *new_url = NULL;
1974 tor_asprintf(&new_url, "/tor/%s", *url);
1975 tor_free(*url);
1976 *url = new_url;
1978 tor_free(command);
1979 return 0;
1982 /** Parse an HTTP request line at the start of a headers string. On failure,
1983 * return -1. On success, set *<b>command_out</b> to a copy of the HTTP
1984 * command ("get", "post", etc), set *<b>url_out</b> to a copy of the URL, and
1985 * return 0. */
1987 parse_http_command(const char *headers, char **command_out, char **url_out)
1989 const char *command, *end_of_command;
1990 char *s, *start, *tmp;
1992 s = (char *)eat_whitespace_no_nl(headers);
1993 if (!*s) return -1;
1994 command = s;
1995 s = (char *)find_whitespace(s); /* get past GET/POST */
1996 if (!*s) return -1;
1997 end_of_command = s;
1998 s = (char *)eat_whitespace_no_nl(s);
1999 if (!*s) return -1;
2000 start = s; /* this is the URL, assuming it's valid */
2001 s = (char *)find_whitespace(start);
2002 if (!*s) return -1;
2004 /* tolerate the http[s] proxy style of putting the hostname in the url */
2005 if (s-start >= 4 && !strcmpstart(start,"http")) {
2006 tmp = start + 4;
2007 if (*tmp == 's')
2008 tmp++;
2009 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
2010 tmp = strchr(tmp+3, '/');
2011 if (tmp && tmp < s) {
2012 log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
2013 start = tmp;
2018 /* Check if the header is well formed (next sequence
2019 * should be HTTP/1.X\r\n). Assumes we're supporting 1.0? */
2021 unsigned minor_ver;
2022 char ch;
2023 char *e = (char *)eat_whitespace_no_nl(s);
2024 if (2 != tor_sscanf(e, "HTTP/1.%u%c", &minor_ver, &ch)) {
2025 return -1;
2027 if (ch != '\r')
2028 return -1;
2031 *url_out = tor_memdup_nulterm(start, s-start);
2032 *command_out = tor_memdup_nulterm(command, end_of_command - command);
2033 return 0;
2036 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
2037 * <b>which</b>. The key should be given with a terminating colon and space;
2038 * this function copies everything after, up to but not including the
2039 * following \\r\\n. */
2040 char *
2041 http_get_header(const char *headers, const char *which)
2043 const char *cp = headers;
2044 while (cp) {
2045 if (!strcasecmpstart(cp, which)) {
2046 char *eos;
2047 cp += strlen(which);
2048 if ((eos = strchr(cp,'\r')))
2049 return tor_strndup(cp, eos-cp);
2050 else
2051 return tor_strdup(cp);
2053 cp = strchr(cp, '\n');
2054 if (cp)
2055 ++cp;
2057 return NULL;
2060 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
2061 * <b>conn</b>-\>address to describe our best guess of the address that
2062 * originated this HTTP request. */
2063 static void
2064 http_set_address_origin(const char *headers, connection_t *conn)
2066 char *fwd;
2068 fwd = http_get_header(headers, "Forwarded-For: ");
2069 if (!fwd)
2070 fwd = http_get_header(headers, "X-Forwarded-For: ");
2071 if (fwd) {
2072 tor_addr_t toraddr;
2073 if (tor_addr_parse(&toraddr,fwd) == -1 ||
2074 tor_addr_is_internal(&toraddr,0)) {
2075 log_debug(LD_DIR, "Ignoring local/internal IP %s", escaped(fwd));
2076 tor_free(fwd);
2077 return;
2080 tor_free(conn->address);
2081 conn->address = tor_strdup(fwd);
2082 tor_free(fwd);
2086 /** Parse an HTTP response string <b>headers</b> of the form
2087 * \verbatim
2088 * "HTTP/1.\%d \%d\%s\r\n...".
2089 * \endverbatim
2091 * If it's well-formed, assign the status code to *<b>code</b> and
2092 * return 0. Otherwise, return -1.
2094 * On success: If <b>date</b> is provided, set *date to the Date
2095 * header in the http headers, or 0 if no such header is found. If
2096 * <b>compression</b> is provided, set *<b>compression</b> to the
2097 * compression method given in the Content-Encoding header, or 0 if no
2098 * such header is found, or -1 if the value of the header is not
2099 * recognized. If <b>reason</b> is provided, strdup the reason string
2100 * into it.
2103 parse_http_response(const char *headers, int *code, time_t *date,
2104 compress_method_t *compression, char **reason)
2106 unsigned n1, n2;
2107 char datestr[RFC1123_TIME_LEN+1];
2108 smartlist_t *parsed_headers;
2109 tor_assert(headers);
2110 tor_assert(code);
2112 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
2114 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
2115 (n1 != 0 && n1 != 1) ||
2116 (n2 < 100 || n2 >= 600)) {
2117 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
2118 return -1;
2120 *code = n2;
2122 parsed_headers = smartlist_new();
2123 smartlist_split_string(parsed_headers, headers, "\n",
2124 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
2125 if (reason) {
2126 smartlist_t *status_line_elements = smartlist_new();
2127 tor_assert(smartlist_len(parsed_headers));
2128 smartlist_split_string(status_line_elements,
2129 smartlist_get(parsed_headers, 0),
2130 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
2131 tor_assert(smartlist_len(status_line_elements) <= 3);
2132 if (smartlist_len(status_line_elements) == 3) {
2133 *reason = smartlist_get(status_line_elements, 2);
2134 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
2136 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
2137 smartlist_free(status_line_elements);
2139 if (date) {
2140 *date = 0;
2141 SMARTLIST_FOREACH(parsed_headers, const char *, s,
2142 if (!strcmpstart(s, "Date: ")) {
2143 strlcpy(datestr, s+6, sizeof(datestr));
2144 /* This will do nothing on failure, so we don't need to check
2145 the result. We shouldn't warn, since there are many other valid
2146 date formats besides the one we use. */
2147 parse_rfc1123_time(datestr, date);
2148 break;
2151 if (compression) {
2152 const char *enc = NULL;
2153 SMARTLIST_FOREACH(parsed_headers, const char *, s,
2154 if (!strcmpstart(s, "Content-Encoding: ")) {
2155 enc = s+18; break;
2158 if (enc == NULL)
2159 *compression = NO_METHOD;
2160 else {
2161 *compression = compression_method_get_by_name(enc);
2163 if (*compression == UNKNOWN_METHOD)
2164 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
2165 escaped(enc));
2168 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
2169 smartlist_free(parsed_headers);
2171 return 0;
2174 /** Return true iff <b>body</b> doesn't start with a plausible router or
2175 * network-status or microdescriptor opening. This is a sign of possible
2176 * compression. */
2177 static int
2178 body_is_plausible(const char *body, size_t len, int purpose)
2180 int i;
2181 if (len == 0)
2182 return 1; /* empty bodies don't need decompression */
2183 if (len < 32)
2184 return 0;
2185 if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
2186 return (!strcmpstart(body,"onion-key"));
2189 if (!strcmpstart(body,"router") ||
2190 !strcmpstart(body,"network-status"))
2191 return 1;
2192 for (i=0;i<32;++i) {
2193 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
2194 return 0;
2197 return 1;
2200 /** Called when we've just fetched a bunch of router descriptors in
2201 * <b>body</b>. The list <b>which</b>, if present, holds digests for
2202 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
2203 * is true, or identity digests otherwise. Parse the descriptors, validate
2204 * them, and annotate them as having purpose <b>purpose</b> and as having been
2205 * downloaded from <b>source</b>.
2207 * Return the number of routers actually added. */
2208 static int
2209 load_downloaded_routers(const char *body, smartlist_t *which,
2210 int descriptor_digests,
2211 int router_purpose,
2212 const char *source)
2214 char buf[256];
2215 char time_buf[ISO_TIME_LEN+1];
2216 int added = 0;
2217 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
2218 format_iso_time(time_buf, time(NULL));
2219 tor_assert(source);
2221 if (tor_snprintf(buf, sizeof(buf),
2222 "@downloaded-at %s\n"
2223 "@source %s\n"
2224 "%s%s%s", time_buf, escaped(source),
2225 !general ? "@purpose " : "",
2226 !general ? router_purpose_to_string(router_purpose) : "",
2227 !general ? "\n" : "")<0)
2228 return added;
2230 added = router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
2231 descriptor_digests, buf);
2232 if (added && general)
2233 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
2234 count_loading_descriptors_progress());
2235 return added;
2238 static int handle_response_fetch_consensus(dir_connection_t *,
2239 const response_handler_args_t *);
2240 static int handle_response_fetch_certificate(dir_connection_t *,
2241 const response_handler_args_t *);
2242 static int handle_response_fetch_status_vote(dir_connection_t *,
2243 const response_handler_args_t *);
2244 static int handle_response_fetch_detached_signatures(dir_connection_t *,
2245 const response_handler_args_t *);
2246 static int handle_response_fetch_desc(dir_connection_t *,
2247 const response_handler_args_t *);
2248 static int handle_response_fetch_microdesc(dir_connection_t *,
2249 const response_handler_args_t *);
2250 static int handle_response_upload_dir(dir_connection_t *,
2251 const response_handler_args_t *);
2252 static int handle_response_upload_vote(dir_connection_t *,
2253 const response_handler_args_t *);
2254 static int handle_response_upload_signatures(dir_connection_t *,
2255 const response_handler_args_t *);
2256 static int handle_response_fetch_renddesc_v2(dir_connection_t *,
2257 const response_handler_args_t *);
2258 static int handle_response_upload_renddesc_v2(dir_connection_t *,
2259 const response_handler_args_t *);
2260 static int handle_response_upload_hsdesc(dir_connection_t *,
2261 const response_handler_args_t *);
2263 static int
2264 dir_client_decompress_response_body(char **bodyp, size_t *bodylenp,
2265 dir_connection_t *conn,
2266 compress_method_t compression,
2267 int anonymized_connection)
2269 int rv = 0;
2270 const char *body = *bodyp;
2271 size_t body_len = *bodylenp;
2272 int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
2273 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
2274 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
2276 int plausible = body_is_plausible(body, body_len, conn->base_.purpose);
2278 if (plausible && compression == NO_METHOD) {
2279 return 0;
2282 int severity = LOG_DEBUG;
2283 char *new_body = NULL;
2284 size_t new_len = 0;
2285 const char *description1, *description2;
2286 int want_to_try_both = 0;
2287 int tried_both = 0;
2288 compress_method_t guessed = detect_compression_method(body, body_len);
2290 description1 = compression_method_get_human_name(compression);
2292 if (BUG(description1 == NULL))
2293 description1 = compression_method_get_human_name(UNKNOWN_METHOD);
2295 if (guessed == UNKNOWN_METHOD && !plausible)
2296 description2 = "confusing binary junk";
2297 else
2298 description2 = compression_method_get_human_name(guessed);
2300 /* Tell the user if we don't believe what we're told about compression.*/
2301 want_to_try_both = (compression == UNKNOWN_METHOD ||
2302 guessed != compression);
2303 if (want_to_try_both) {
2304 severity = LOG_PROTOCOL_WARN;
2307 tor_log(severity, LD_HTTP,
2308 "HTTP body from server '%s:%d' was labeled as %s, "
2309 "%s it seems to be %s.%s",
2310 conn->base_.address, conn->base_.port, description1,
2311 guessed != compression?"but":"and",
2312 description2,
2313 (compression>0 && guessed>0 && want_to_try_both)?
2314 " Trying both.":"");
2316 /* Try declared compression first if we can.
2317 * tor_compress_supports_method() also returns true for NO_METHOD.
2318 * Ensure that the server is not sending us data compressed using a
2319 * compression method that is not allowed for anonymous connections. */
2320 if (anonymized_connection &&
2321 ! allowed_anonymous_connection_compression_method(compression)) {
2322 warn_disallowed_anonymous_compression_method(compression);
2323 rv = -1;
2324 goto done;
2327 if (tor_compress_supports_method(compression)) {
2328 tor_uncompress(&new_body, &new_len, body, body_len, compression,
2329 !allow_partial, LOG_PROTOCOL_WARN);
2330 if (new_body) {
2331 /* We succeeded with the declared compression method. Great! */
2332 rv = 0;
2333 goto done;
2337 /* Okay, if that didn't work, and we think that it was compressed
2338 * differently, try that. */
2339 if (anonymized_connection &&
2340 ! allowed_anonymous_connection_compression_method(guessed)) {
2341 warn_disallowed_anonymous_compression_method(guessed);
2342 rv = -1;
2343 goto done;
2346 if (tor_compress_supports_method(guessed) &&
2347 compression != guessed) {
2348 tor_uncompress(&new_body, &new_len, body, body_len, guessed,
2349 !allow_partial, LOG_INFO);
2350 tried_both = 1;
2352 /* If we're pretty sure that we have a compressed directory, and
2353 * we didn't manage to uncompress it, then warn and bail. */
2354 if (!plausible && !new_body) {
2355 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
2356 "Unable to decompress HTTP body (tried %s%s%s, server '%s:%d').",
2357 description1,
2358 tried_both?" and ":"",
2359 tried_both?description2:"",
2360 conn->base_.address, conn->base_.port);
2361 rv = -1;
2362 goto done;
2365 done:
2366 if (new_body) {
2367 if (rv == 0) {
2368 /* success! */
2369 tor_free(*bodyp);
2370 *bodyp = new_body;
2371 *bodylenp = new_len;
2372 } else {
2373 tor_free(new_body);
2377 return rv;
2380 /** We are a client, and we've finished reading the server's
2381 * response. Parse it and act appropriately.
2383 * If we're still happy with using this directory server in the future, return
2384 * 0. Otherwise return -1; and the caller should consider trying the request
2385 * again.
2387 * The caller will take care of marking the connection for close.
2389 static int
2390 connection_dir_client_reached_eof(dir_connection_t *conn)
2392 char *body = NULL;
2393 char *headers = NULL;
2394 char *reason = NULL;
2395 size_t body_len = 0;
2396 int status_code;
2397 time_t date_header = 0;
2398 long apparent_skew;
2399 compress_method_t compression;
2400 int skewed = 0;
2401 int rv;
2402 int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
2403 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
2404 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
2405 size_t received_bytes;
2406 const int anonymized_connection =
2407 purpose_needs_anonymity(conn->base_.purpose,
2408 conn->router_purpose,
2409 conn->requested_resource);
2411 received_bytes = connection_get_inbuf_len(TO_CONN(conn));
2413 switch (connection_fetch_from_buf_http(TO_CONN(conn),
2414 &headers, MAX_HEADERS_SIZE,
2415 &body, &body_len, MAX_DIR_DL_SIZE,
2416 allow_partial)) {
2417 case -1: /* overflow */
2418 log_warn(LD_PROTOCOL,
2419 "'fetch' response too large (server '%s:%d'). Closing.",
2420 conn->base_.address, conn->base_.port);
2421 return -1;
2422 case 0:
2423 log_info(LD_HTTP,
2424 "'fetch' response not all here, but we're at eof. Closing.");
2425 return -1;
2426 /* case 1, fall through */
2429 if (parse_http_response(headers, &status_code, &date_header,
2430 &compression, &reason) < 0) {
2431 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
2432 conn->base_.address, conn->base_.port);
2434 rv = -1;
2435 goto done;
2437 if (!reason) reason = tor_strdup("[no reason given]");
2439 tor_log(LOG_DEBUG, LD_DIR,
2440 "Received response from directory server '%s:%d': %d %s "
2441 "(purpose: %d, response size: " U64_FORMAT
2442 #ifdef MEASUREMENTS_21206
2443 ", data cells received: %d, data cells sent: %d"
2444 #endif
2445 ", compression: %d)",
2446 conn->base_.address, conn->base_.port, status_code,
2447 escaped(reason), conn->base_.purpose,
2448 U64_PRINTF_ARG(received_bytes),
2449 #ifdef MEASUREMENTS_21206
2450 conn->data_cells_received, conn->data_cells_sent,
2451 #endif
2452 compression);
2454 if (conn->guard_state) {
2455 /* we count the connection as successful once we can read from it. We do
2456 * not, however, delay use of the circuit here, since it's just for a
2457 * one-hop directory request. */
2458 /* XXXXprop271 note that this will not do the right thing for other
2459 * waiting circuits that would be triggered by this circuit becoming
2460 * complete/usable. But that's ok, I think.
2462 entry_guard_succeeded(&conn->guard_state);
2463 circuit_guard_state_free(conn->guard_state);
2464 conn->guard_state = NULL;
2467 /* now check if it's got any hints for us about our IP address. */
2468 if (conn->dirconn_direct) {
2469 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
2470 if (guess) {
2471 router_new_address_suggestion(guess, conn);
2472 tor_free(guess);
2476 if (date_header > 0) {
2477 /* The date header was written very soon after we sent our request,
2478 * so compute the skew as the difference between sending the request
2479 * and the date header. (We used to check now-date_header, but that's
2480 * inaccurate if we spend a lot of time downloading.)
2482 apparent_skew = conn->base_.timestamp_lastwritten - date_header;
2483 if (labs(apparent_skew)>ALLOW_DIRECTORY_TIME_SKEW) {
2484 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
2485 clock_skew_warning(TO_CONN(conn), apparent_skew, trusted, LD_HTTP,
2486 "directory", "DIRSERV");
2487 skewed = 1; /* don't check the recommended-versions line */
2488 } else {
2489 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
2490 "we are %ld seconds skewed. (That's okay.)", apparent_skew);
2493 (void) skewed; /* skewed isn't used yet. */
2495 if (status_code == 503) {
2496 routerstatus_t *rs;
2497 dir_server_t *ds;
2498 const char *id_digest = conn->identity_digest;
2499 log_info(LD_DIR,"Received http status code %d (%s) from server "
2500 "'%s:%d'. I'll try again soon.",
2501 status_code, escaped(reason), conn->base_.address,
2502 conn->base_.port);
2503 time_t now = approx_time();
2504 if ((rs = router_get_mutable_consensus_status_by_id(id_digest)))
2505 rs->last_dir_503_at = now;
2506 if ((ds = router_get_fallback_dirserver_by_digest(id_digest)))
2507 ds->fake_status.last_dir_503_at = now;
2509 rv = -1;
2510 goto done;
2513 if (dir_client_decompress_response_body(&body, &body_len,
2514 conn, compression, anonymized_connection) < 0) {
2515 rv = -1;
2516 goto done;
2519 response_handler_args_t args;
2520 memset(&args, 0, sizeof(args));
2521 args.status_code = status_code;
2522 args.reason = reason;
2523 args.body = body;
2524 args.body_len = body_len;
2525 args.headers = headers;
2527 switch (conn->base_.purpose) {
2528 case DIR_PURPOSE_FETCH_CONSENSUS:
2529 rv = handle_response_fetch_consensus(conn, &args);
2530 break;
2531 case DIR_PURPOSE_FETCH_CERTIFICATE:
2532 rv = handle_response_fetch_certificate(conn, &args);
2533 break;
2534 case DIR_PURPOSE_FETCH_STATUS_VOTE:
2535 rv = handle_response_fetch_status_vote(conn, &args);
2536 break;
2537 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
2538 rv = handle_response_fetch_detached_signatures(conn, &args);
2539 break;
2540 case DIR_PURPOSE_FETCH_SERVERDESC:
2541 case DIR_PURPOSE_FETCH_EXTRAINFO:
2542 rv = handle_response_fetch_desc(conn, &args);
2543 break;
2544 case DIR_PURPOSE_FETCH_MICRODESC:
2545 rv = handle_response_fetch_microdesc(conn, &args);
2546 break;
2547 case DIR_PURPOSE_FETCH_RENDDESC_V2:
2548 rv = handle_response_fetch_renddesc_v2(conn, &args);
2549 break;
2550 case DIR_PURPOSE_UPLOAD_DIR:
2551 rv = handle_response_upload_dir(conn, &args);
2552 break;
2553 case DIR_PURPOSE_UPLOAD_SIGNATURES:
2554 rv = handle_response_upload_signatures(conn, &args);
2555 break;
2556 case DIR_PURPOSE_UPLOAD_VOTE:
2557 rv = handle_response_upload_vote(conn, &args);
2558 break;
2559 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
2560 rv = handle_response_upload_renddesc_v2(conn, &args);
2561 break;
2562 case DIR_PURPOSE_UPLOAD_HSDESC:
2563 rv = handle_response_upload_hsdesc(conn, &args);
2564 break;
2565 case DIR_PURPOSE_FETCH_HSDESC:
2566 rv = handle_response_fetch_hsdesc_v3(conn, &args);
2567 break;
2568 default:
2569 tor_assert_nonfatal_unreached();
2570 rv = -1;
2571 break;
2574 done:
2575 tor_free(body);
2576 tor_free(headers);
2577 tor_free(reason);
2578 return rv;
2582 * Handler function: processes a response to a request for a networkstatus
2583 * consensus document by checking the consensus, storing it, and marking
2584 * router requests as reachable.
2586 static int
2587 handle_response_fetch_consensus(dir_connection_t *conn,
2588 const response_handler_args_t *args)
2590 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS);
2591 const int status_code = args->status_code;
2592 const char *body = args->body;
2593 const size_t body_len = args->body_len;
2594 const char *reason = args->reason;
2595 const time_t now = approx_time();
2597 const char *consensus;
2598 char *new_consensus = NULL;
2599 const char *sourcename;
2601 int r;
2602 const char *flavname = conn->requested_resource;
2603 if (status_code != 200) {
2604 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
2605 tor_log(severity, LD_DIR,
2606 "Received http status code %d (%s) from server "
2607 "'%s:%d' while fetching consensus directory.",
2608 status_code, escaped(reason), conn->base_.address,
2609 conn->base_.port);
2610 networkstatus_consensus_download_failed(status_code, flavname);
2611 return -1;
2614 if (looks_like_a_consensus_diff(body, body_len)) {
2615 /* First find our previous consensus. Maybe it's in ram, maybe not. */
2616 cached_dir_t *cd = dirserv_get_consensus(flavname);
2617 const char *consensus_body;
2618 char *owned_consensus = NULL;
2619 if (cd) {
2620 consensus_body = cd->dir;
2621 } else {
2622 owned_consensus = networkstatus_read_cached_consensus(flavname);
2623 consensus_body = owned_consensus;
2625 if (!consensus_body) {
2626 log_warn(LD_DIR, "Received a consensus diff, but we can't find "
2627 "any %s-flavored consensus in our current cache.",flavname);
2628 networkstatus_consensus_download_failed(0, flavname);
2629 // XXXX if this happens too much, see below
2630 return -1;
2633 new_consensus = consensus_diff_apply(consensus_body, body);
2634 tor_free(owned_consensus);
2635 if (new_consensus == NULL) {
2636 log_warn(LD_DIR, "Could not apply consensus diff received from server "
2637 "'%s:%d'", conn->base_.address, conn->base_.port);
2638 // XXXX If this happens too many times, we should maybe not use
2639 // XXXX this directory for diffs any more?
2640 networkstatus_consensus_download_failed(0, flavname);
2641 return -1;
2643 log_info(LD_DIR, "Applied consensus diff (size %d) from server "
2644 "'%s:%d', resulting in a new consensus document (size %d).",
2645 (int)body_len, conn->base_.address, conn->base_.port,
2646 (int)strlen(new_consensus));
2647 consensus = new_consensus;
2648 sourcename = "generated based on a diff";
2649 } else {
2650 log_info(LD_DIR,"Received consensus directory (body size %d) from server "
2651 "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
2652 consensus = body;
2653 sourcename = "downloaded";
2656 if ((r=networkstatus_set_current_consensus(consensus, flavname, 0,
2657 conn->identity_digest))<0) {
2658 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
2659 "Unable to load %s consensus directory %s from "
2660 "server '%s:%d'. I'll try again soon.",
2661 flavname, sourcename, conn->base_.address, conn->base_.port);
2662 networkstatus_consensus_download_failed(0, flavname);
2663 tor_free(new_consensus);
2664 return -1;
2667 /* If we launched other fetches for this consensus, cancel them. */
2668 connection_dir_close_consensus_fetches(conn, flavname);
2670 /* launches router downloads as needed */
2671 routers_update_all_from_networkstatus(now, 3);
2672 update_microdescs_from_networkstatus(now);
2673 update_microdesc_downloads(now);
2674 directory_info_has_arrived(now, 0, 0);
2675 if (authdir_mode_v3(get_options())) {
2676 sr_act_post_consensus(
2677 networkstatus_get_latest_consensus_by_flavor(FLAV_NS));
2679 log_info(LD_DIR, "Successfully loaded consensus.");
2681 tor_free(new_consensus);
2682 return 0;
2686 * Handler function: processes a response to a request for one or more
2687 * authority certificates
2689 static int
2690 handle_response_fetch_certificate(dir_connection_t *conn,
2691 const response_handler_args_t *args)
2693 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
2694 const int status_code = args->status_code;
2695 const char *reason = args->reason;
2696 const char *body = args->body;
2697 const size_t body_len = args->body_len;
2699 if (status_code != 200) {
2700 log_warn(LD_DIR,
2701 "Received http status code %d (%s) from server "
2702 "'%s:%d' while fetching \"/tor/keys/%s\".",
2703 status_code, escaped(reason), conn->base_.address,
2704 conn->base_.port, conn->requested_resource);
2705 connection_dir_download_cert_failed(conn, status_code);
2706 return -1;
2708 log_info(LD_DIR,"Received authority certificates (body size %d) from "
2709 "server '%s:%d'",
2710 (int)body_len, conn->base_.address, conn->base_.port);
2713 * Tell trusted_dirs_load_certs_from_string() whether it was by fp
2714 * or fp-sk pair.
2716 int src_code = -1;
2717 if (!strcmpstart(conn->requested_resource, "fp/")) {
2718 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST;
2719 } else if (!strcmpstart(conn->requested_resource, "fp-sk/")) {
2720 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST;
2723 if (src_code != -1) {
2724 if (trusted_dirs_load_certs_from_string(body, src_code, 1,
2725 conn->identity_digest)<0) {
2726 log_warn(LD_DIR, "Unable to parse fetched certificates");
2727 /* if we fetched more than one and only some failed, the successful
2728 * ones got flushed to disk so it's safe to call this on them */
2729 connection_dir_download_cert_failed(conn, status_code);
2730 } else {
2731 time_t now = approx_time();
2732 directory_info_has_arrived(now, 0, 0);
2733 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
2735 } else {
2736 log_warn(LD_DIR,
2737 "Couldn't figure out what to do with fetched certificates for "
2738 "unknown resource %s",
2739 conn->requested_resource);
2740 connection_dir_download_cert_failed(conn, status_code);
2742 return 0;
2746 * Handler function: processes a response to a request for an authority's
2747 * current networkstatus vote.
2749 static int
2750 handle_response_fetch_status_vote(dir_connection_t *conn,
2751 const response_handler_args_t *args)
2753 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE);
2754 const int status_code = args->status_code;
2755 const char *reason = args->reason;
2756 const char *body = args->body;
2757 const size_t body_len = args->body_len;
2759 const char *msg;
2760 int st;
2761 log_info(LD_DIR,"Got votes (body size %d) from server %s:%d",
2762 (int)body_len, conn->base_.address, conn->base_.port);
2763 if (status_code != 200) {
2764 log_warn(LD_DIR,
2765 "Received http status code %d (%s) from server "
2766 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
2767 status_code, escaped(reason), conn->base_.address,
2768 conn->base_.port, conn->requested_resource);
2769 return -1;
2771 dirvote_add_vote(body, &msg, &st);
2772 if (st > 299) {
2773 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
2774 } else {
2775 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
2778 return 0;
2782 * Handler function: processes a response to a request for the signatures
2783 * that an authority knows about on a given consensus.
2785 static int
2786 handle_response_fetch_detached_signatures(dir_connection_t *conn,
2787 const response_handler_args_t *args)
2789 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
2790 const int status_code = args->status_code;
2791 const char *reason = args->reason;
2792 const char *body = args->body;
2793 const size_t body_len = args->body_len;
2795 const char *msg = NULL;
2796 log_info(LD_DIR,"Got detached signatures (body size %d) from server %s:%d",
2797 (int)body_len, conn->base_.address, conn->base_.port);
2798 if (status_code != 200) {
2799 log_warn(LD_DIR,
2800 "Received http status code %d (%s) from server '%s:%d' while fetching "
2801 "\"/tor/status-vote/next/consensus-signatures.z\".",
2802 status_code, escaped(reason), conn->base_.address,
2803 conn->base_.port);
2804 return -1;
2806 if (dirvote_add_signatures(body, conn->base_.address, &msg)<0) {
2807 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
2808 conn->base_.address, conn->base_.port, msg?msg:"???");
2811 return 0;
2815 * Handler function: processes a response to a request for a group of server
2816 * descriptors or an extrainfo documents.
2818 static int
2819 handle_response_fetch_desc(dir_connection_t *conn,
2820 const response_handler_args_t *args)
2822 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
2823 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
2824 const int status_code = args->status_code;
2825 const char *reason = args->reason;
2826 const char *body = args->body;
2827 const size_t body_len = args->body_len;
2829 int was_ei = conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
2830 smartlist_t *which = NULL;
2831 int n_asked_for = 0;
2832 int descriptor_digests = conn->requested_resource &&
2833 !strcmpstart(conn->requested_resource,"d/");
2834 log_info(LD_DIR,"Received %s (body size %d) from server '%s:%d'",
2835 was_ei ? "extra server info" : "server info",
2836 (int)body_len, conn->base_.address, conn->base_.port);
2837 if (conn->requested_resource &&
2838 (!strcmpstart(conn->requested_resource,"d/") ||
2839 !strcmpstart(conn->requested_resource,"fp/"))) {
2840 which = smartlist_new();
2841 dir_split_resource_into_fingerprints(conn->requested_resource +
2842 (descriptor_digests ? 2 : 3),
2843 which, NULL, 0);
2844 n_asked_for = smartlist_len(which);
2846 if (status_code != 200) {
2847 int dir_okay = status_code == 404 ||
2848 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
2849 /* 404 means that it didn't have them; no big deal.
2850 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
2851 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
2852 "Received http status code %d (%s) from server '%s:%d' "
2853 "while fetching \"/tor/server/%s\". I'll try again soon.",
2854 status_code, escaped(reason), conn->base_.address,
2855 conn->base_.port, conn->requested_resource);
2856 if (!which) {
2857 connection_dir_download_routerdesc_failed(conn);
2858 } else {
2859 dir_routerdesc_download_failed(which, status_code,
2860 conn->router_purpose,
2861 was_ei, descriptor_digests);
2862 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2863 smartlist_free(which);
2865 return dir_okay ? 0 : -1;
2867 /* Learn the routers, assuming we requested by fingerprint or "all"
2868 * or "authority".
2870 * We use "authority" to fetch our own descriptor for
2871 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
2872 * the output of "authority" requests unless we are using bridges,
2873 * since otherwise they'll be the response from reachability tests,
2874 * and we don't really want to add that to our routerlist. */
2875 if (which || (conn->requested_resource &&
2876 (!strcmpstart(conn->requested_resource, "all") ||
2877 (!strcmpstart(conn->requested_resource, "authority") &&
2878 get_options()->UseBridges)))) {
2879 /* as we learn from them, we remove them from 'which' */
2880 if (was_ei) {
2881 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
2882 descriptor_digests);
2883 } else {
2884 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
2885 // descriptor_digests, conn->router_purpose);
2886 if (load_downloaded_routers(body, which, descriptor_digests,
2887 conn->router_purpose,
2888 conn->base_.address)) {
2889 time_t now = approx_time();
2890 directory_info_has_arrived(now, 0, 0);
2894 if (which) { /* mark remaining ones as failed */
2895 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
2896 n_asked_for-smartlist_len(which), n_asked_for,
2897 was_ei ? "extra-info documents" : "router descriptors",
2898 conn->base_.address, (int)conn->base_.port);
2899 if (smartlist_len(which)) {
2900 dir_routerdesc_download_failed(which, status_code,
2901 conn->router_purpose,
2902 was_ei, descriptor_digests);
2904 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2905 smartlist_free(which);
2907 if (directory_conn_is_self_reachability_test(conn))
2908 router_dirport_found_reachable();
2910 return 0;
2914 * Handler function: processes a response to a request for a group of
2915 * microdescriptors
2917 static int
2918 handle_response_fetch_microdesc(dir_connection_t *conn,
2919 const response_handler_args_t *args)
2921 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
2922 const int status_code = args->status_code;
2923 const char *reason = args->reason;
2924 const char *body = args->body;
2925 const size_t body_len = args->body_len;
2927 smartlist_t *which = NULL;
2928 log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
2929 "body size %d) from server '%s:%d'",
2930 status_code, (int)body_len, conn->base_.address,
2931 conn->base_.port);
2932 tor_assert(conn->requested_resource &&
2933 !strcmpstart(conn->requested_resource, "d/"));
2934 which = smartlist_new();
2935 dir_split_resource_into_fingerprints(conn->requested_resource+2,
2936 which, NULL,
2937 DSR_DIGEST256|DSR_BASE64);
2938 if (status_code != 200) {
2939 log_info(LD_DIR, "Received status code %d (%s) from server "
2940 "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again "
2941 "soon.",
2942 status_code, escaped(reason), conn->base_.address,
2943 (int)conn->base_.port, conn->requested_resource);
2944 dir_microdesc_download_failed(which, status_code);
2945 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2946 smartlist_free(which);
2947 return 0;
2948 } else {
2949 smartlist_t *mds;
2950 time_t now = approx_time();
2951 mds = microdescs_add_to_cache(get_microdesc_cache(),
2952 body, body+body_len, SAVED_NOWHERE, 0,
2953 now, which);
2954 if (smartlist_len(which)) {
2955 /* Mark remaining ones as failed. */
2956 dir_microdesc_download_failed(which, status_code);
2958 if (mds && smartlist_len(mds)) {
2959 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
2960 count_loading_descriptors_progress());
2961 directory_info_has_arrived(now, 0, 1);
2963 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2964 smartlist_free(which);
2965 smartlist_free(mds);
2968 return 0;
2972 * Handler function: processes a response to a POST request to upload our
2973 * router descriptor.
2975 static int
2976 handle_response_upload_dir(dir_connection_t *conn,
2977 const response_handler_args_t *args)
2979 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_DIR);
2980 const int status_code = args->status_code;
2981 const char *reason = args->reason;
2982 const char *headers = args->headers;
2984 switch (status_code) {
2985 case 200: {
2986 dir_server_t *ds =
2987 router_get_trusteddirserver_by_digest(conn->identity_digest);
2988 char *rejected_hdr = http_get_header(headers,
2989 "X-Descriptor-Not-New: ");
2990 if (rejected_hdr) {
2991 if (!strcmp(rejected_hdr, "Yes")) {
2992 log_info(LD_GENERAL,
2993 "Authority '%s' declined our descriptor (not new)",
2994 ds->nickname);
2995 /* XXXX use this information; be sure to upload next one
2996 * sooner. -NM */
2997 /* XXXX++ On further thought, the task above implies that we're
2998 * basing our regenerate-descriptor time on when we uploaded the
2999 * last descriptor, not on the published time of the last
3000 * descriptor. If those are different, that's a bad thing to
3001 * do. -NM */
3003 tor_free(rejected_hdr);
3005 log_info(LD_GENERAL,"eof (status 200) after uploading server "
3006 "descriptor: finished.");
3007 control_event_server_status(
3008 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
3009 conn->base_.address, conn->base_.port);
3011 ds->has_accepted_serverdesc = 1;
3012 if (directories_have_accepted_server_descriptor())
3013 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
3015 break;
3016 case 400:
3017 log_warn(LD_GENERAL,"http status 400 (%s) response from "
3018 "dirserver '%s:%d'. Please correct.",
3019 escaped(reason), conn->base_.address, conn->base_.port);
3020 control_event_server_status(LOG_WARN,
3021 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
3022 conn->base_.address, conn->base_.port, escaped(reason));
3023 break;
3024 default:
3025 log_warn(LD_GENERAL,
3026 "HTTP status %d (%s) was unexpected while uploading "
3027 "descriptor to server '%s:%d'. Possibly the server is "
3028 "misconfigured?",
3029 status_code, escaped(reason), conn->base_.address,
3030 conn->base_.port);
3031 break;
3033 /* return 0 in all cases, since we don't want to mark any
3034 * dirservers down just because they don't like us. */
3036 return 0;
3040 * Handler function: processes a response to POST request to upload our
3041 * own networkstatus vote.
3043 static int
3044 handle_response_upload_vote(dir_connection_t *conn,
3045 const response_handler_args_t *args)
3047 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_VOTE);
3048 const int status_code = args->status_code;
3049 const char *reason = args->reason;
3051 switch (status_code) {
3052 case 200: {
3053 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
3054 conn->base_.address, conn->base_.port);
3056 break;
3057 case 400:
3058 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
3059 "vote to dirserver '%s:%d'. Please correct.",
3060 escaped(reason), conn->base_.address, conn->base_.port);
3061 break;
3062 default:
3063 log_warn(LD_GENERAL,
3064 "HTTP status %d (%s) was unexpected while uploading "
3065 "vote to server '%s:%d'.",
3066 status_code, escaped(reason), conn->base_.address,
3067 conn->base_.port);
3068 break;
3070 /* return 0 in all cases, since we don't want to mark any
3071 * dirservers down just because they don't like us. */
3072 return 0;
3076 * Handler function: processes a response to POST request to upload our
3077 * view of the signatures on the current consensus.
3079 static int
3080 handle_response_upload_signatures(dir_connection_t *conn,
3081 const response_handler_args_t *args)
3083 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES);
3084 const int status_code = args->status_code;
3085 const char *reason = args->reason;
3087 switch (status_code) {
3088 case 200: {
3089 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
3090 conn->base_.address, conn->base_.port);
3092 break;
3093 case 400:
3094 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
3095 "signatures to dirserver '%s:%d'. Please correct.",
3096 escaped(reason), conn->base_.address, conn->base_.port);
3097 break;
3098 default:
3099 log_warn(LD_GENERAL,
3100 "HTTP status %d (%s) was unexpected while uploading "
3101 "signatures to server '%s:%d'.",
3102 status_code, escaped(reason), conn->base_.address,
3103 conn->base_.port);
3104 break;
3106 /* return 0 in all cases, since we don't want to mark any
3107 * dirservers down just because they don't like us. */
3109 return 0;
3113 * Handler function: processes a response to a request for a v3 hidden service
3114 * descriptor.
3116 STATIC int
3117 handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
3118 const response_handler_args_t *args)
3120 const int status_code = args->status_code;
3121 const char *reason = args->reason;
3122 const char *body = args->body;
3123 const size_t body_len = args->body_len;
3125 tor_assert(conn->hs_ident);
3127 log_info(LD_REND,"Received v3 hsdesc (body size %d, status %d (%s))",
3128 (int)body_len, status_code, escaped(reason));
3130 switch (status_code) {
3131 case 200:
3132 /* We got something: Try storing it in the cache. */
3133 if (hs_cache_store_as_client(body, &conn->hs_ident->identity_pk) < 0) {
3134 log_warn(LD_REND, "Failed to store hidden service descriptor");
3135 } else {
3136 log_info(LD_REND, "Stored hidden service descriptor successfully.");
3137 TO_CONN(conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
3138 hs_client_desc_has_arrived(conn->hs_ident);
3140 break;
3141 case 404:
3142 /* Not there. We'll retry when connection_about_to_close_connection()
3143 * tries to clean this conn up. */
3144 log_info(LD_REND, "Fetching hidden service v3 descriptor not found: "
3145 "Retrying at another directory.");
3146 /* TODO: Inform the control port */
3147 break;
3148 case 400:
3149 log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
3150 "http status 400 (%s). Dirserver didn't like our "
3151 "query? Retrying at another directory.",
3152 escaped(reason));
3153 break;
3154 default:
3155 log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
3156 "http status %d (%s) response unexpected from HSDir server "
3157 "'%s:%d'. Retrying at another directory.",
3158 status_code, escaped(reason), TO_CONN(conn)->address,
3159 TO_CONN(conn)->port);
3160 break;
3163 return 0;
3167 * Handler function: processes a response to a request for a v2 hidden service
3168 * descriptor.
3170 static int
3171 handle_response_fetch_renddesc_v2(dir_connection_t *conn,
3172 const response_handler_args_t *args)
3174 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2);
3175 const int status_code = args->status_code;
3176 const char *reason = args->reason;
3177 const char *body = args->body;
3178 const size_t body_len = args->body_len;
3180 #define SEND_HS_DESC_FAILED_EVENT(reason) \
3181 (control_event_hs_descriptor_failed(conn->rend_data, \
3182 conn->identity_digest, \
3183 reason))
3184 #define SEND_HS_DESC_FAILED_CONTENT() \
3185 (control_event_hs_descriptor_content( \
3186 rend_data_get_address(conn->rend_data), \
3187 conn->requested_resource, \
3188 conn->identity_digest, \
3189 NULL))
3191 tor_assert(conn->rend_data);
3192 log_info(LD_REND,"Received rendezvous descriptor (body size %d, status %d "
3193 "(%s))",
3194 (int)body_len, status_code, escaped(reason));
3195 switch (status_code) {
3196 case 200:
3198 rend_cache_entry_t *entry = NULL;
3200 if (rend_cache_store_v2_desc_as_client(body,
3201 conn->requested_resource,
3202 conn->rend_data, &entry) < 0) {
3203 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
3204 "Retrying at another directory.");
3205 /* We'll retry when connection_about_to_close_connection()
3206 * cleans this dir conn up. */
3207 SEND_HS_DESC_FAILED_EVENT("BAD_DESC");
3208 SEND_HS_DESC_FAILED_CONTENT();
3209 } else {
3210 char service_id[REND_SERVICE_ID_LEN_BASE32 + 1];
3211 /* Should never be NULL here if we found the descriptor. */
3212 tor_assert(entry);
3213 rend_get_service_id(entry->parsed->pk, service_id);
3215 /* success. notify pending connections about this. */
3216 log_info(LD_REND, "Successfully fetched v2 rendezvous "
3217 "descriptor.");
3218 control_event_hs_descriptor_received(service_id,
3219 conn->rend_data,
3220 conn->identity_digest);
3221 control_event_hs_descriptor_content(service_id,
3222 conn->requested_resource,
3223 conn->identity_digest,
3224 body);
3225 conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
3226 rend_client_desc_trynow(service_id);
3227 memwipe(service_id, 0, sizeof(service_id));
3229 break;
3231 case 404:
3232 /* Not there. We'll retry when
3233 * connection_about_to_close_connection() cleans this conn up. */
3234 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
3235 "Retrying at another directory.");
3236 SEND_HS_DESC_FAILED_EVENT("NOT_FOUND");
3237 SEND_HS_DESC_FAILED_CONTENT();
3238 break;
3239 case 400:
3240 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
3241 "http status 400 (%s). Dirserver didn't like our "
3242 "v2 rendezvous query? Retrying at another directory.",
3243 escaped(reason));
3244 SEND_HS_DESC_FAILED_EVENT("QUERY_REJECTED");
3245 SEND_HS_DESC_FAILED_CONTENT();
3246 break;
3247 default:
3248 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
3249 "http status %d (%s) response unexpected while "
3250 "fetching v2 hidden service descriptor (server '%s:%d'). "
3251 "Retrying at another directory.",
3252 status_code, escaped(reason), conn->base_.address,
3253 conn->base_.port);
3254 SEND_HS_DESC_FAILED_EVENT("UNEXPECTED");
3255 SEND_HS_DESC_FAILED_CONTENT();
3256 break;
3259 return 0;
3263 * Handler function: processes a response to a POST request to upload a v2
3264 * hidden service descriptor.
3266 static int
3267 handle_response_upload_renddesc_v2(dir_connection_t *conn,
3268 const response_handler_args_t *args)
3270 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2);
3271 const int status_code = args->status_code;
3272 const char *reason = args->reason;
3274 #define SEND_HS_DESC_UPLOAD_FAILED_EVENT(reason) \
3275 (control_event_hs_descriptor_upload_failed( \
3276 conn->identity_digest, \
3277 rend_data_get_address(conn->rend_data), \
3278 reason))
3280 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
3281 "(%s))",
3282 status_code, escaped(reason));
3283 /* Without the rend data, we'll have a problem identifying what has been
3284 * uploaded for which service. */
3285 tor_assert(conn->rend_data);
3286 switch (status_code) {
3287 case 200:
3288 log_info(LD_REND,
3289 "Uploading rendezvous descriptor: finished with status "
3290 "200 (%s)", escaped(reason));
3291 control_event_hs_descriptor_uploaded(conn->identity_digest,
3292 rend_data_get_address(conn->rend_data));
3293 rend_service_desc_has_uploaded(conn->rend_data);
3294 break;
3295 case 400:
3296 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
3297 "'%s:%d'. Malformed rendezvous descriptor?",
3298 escaped(reason), conn->base_.address, conn->base_.port);
3299 SEND_HS_DESC_UPLOAD_FAILED_EVENT("UPLOAD_REJECTED");
3300 break;
3301 default:
3302 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
3303 "'%s:%d').",
3304 status_code, escaped(reason), conn->base_.address,
3305 conn->base_.port);
3306 SEND_HS_DESC_UPLOAD_FAILED_EVENT("UNEXPECTED");
3307 break;
3310 return 0;
3314 * Handler function: processes a response to a POST request to upload an
3315 * hidden service descriptor.
3317 static int
3318 handle_response_upload_hsdesc(dir_connection_t *conn,
3319 const response_handler_args_t *args)
3321 const int status_code = args->status_code;
3322 const char *reason = args->reason;
3324 tor_assert(conn);
3325 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_HSDESC);
3327 log_info(LD_REND, "Uploaded hidden service descriptor (status %d "
3328 "(%s))",
3329 status_code, escaped(reason));
3330 /* For this directory response, it MUST have an hidden service identifier on
3331 * this connection. */
3332 tor_assert(conn->hs_ident);
3333 switch (status_code) {
3334 case 200:
3335 log_info(LD_REND, "Uploading hidden service descriptor: "
3336 "finished with status 200 (%s)", escaped(reason));
3337 /* XXX: Trigger control event. */
3338 break;
3339 case 400:
3340 log_warn(LD_REND, "Uploading hidden service descriptor: http "
3341 "status 400 (%s) response from dirserver "
3342 "'%s:%d'. Malformed hidden service descriptor?",
3343 escaped(reason), conn->base_.address, conn->base_.port);
3344 /* XXX: Trigger control event. */
3345 break;
3346 default:
3347 log_warn(LD_REND, "Uploading hidden service descriptor: http "
3348 "status %d (%s) response unexpected (server "
3349 "'%s:%d').",
3350 status_code, escaped(reason), conn->base_.address,
3351 conn->base_.port);
3352 /* XXX: Trigger control event. */
3353 break;
3356 return 0;
3359 /** Called when a directory connection reaches EOF. */
3361 connection_dir_reached_eof(dir_connection_t *conn)
3363 int retval;
3364 if (conn->base_.state != DIR_CONN_STATE_CLIENT_READING) {
3365 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
3366 conn->base_.state);
3367 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
3368 connection_mark_for_close(TO_CONN(conn));
3369 return -1;
3372 retval = connection_dir_client_reached_eof(conn);
3373 if (retval == 0) /* success */
3374 conn->base_.state = DIR_CONN_STATE_CLIENT_FINISHED;
3375 connection_mark_for_close(TO_CONN(conn));
3376 return retval;
3379 /** If any directory object is arriving, and it's over 10MB large, we're
3380 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
3381 * ask for more than 96 router descriptors at a time.)
3383 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
3385 #define MAX_VOTE_DL_SIZE (MAX_DIRECTORY_OBJECT_SIZE * 5)
3387 /** Read handler for directory connections. (That's connections <em>to</em>
3388 * directory servers and connections <em>at</em> directory servers.)
3391 connection_dir_process_inbuf(dir_connection_t *conn)
3393 size_t max_size;
3394 tor_assert(conn);
3395 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3397 /* Directory clients write, then read data until they receive EOF;
3398 * directory servers read data until they get an HTTP command, then
3399 * write their response (when it's finished flushing, they mark for
3400 * close).
3403 /* If we're on the dirserver side, look for a command. */
3404 if (conn->base_.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
3405 if (directory_handle_command(conn) < 0) {
3406 connection_mark_for_close(TO_CONN(conn));
3407 return -1;
3409 return 0;
3412 max_size =
3413 (TO_CONN(conn)->purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) ?
3414 MAX_VOTE_DL_SIZE : MAX_DIRECTORY_OBJECT_SIZE;
3416 if (connection_get_inbuf_len(TO_CONN(conn)) > max_size) {
3417 log_warn(LD_HTTP,
3418 "Too much data received from directory connection (%s): "
3419 "denial of service attempt, or you need to upgrade?",
3420 conn->base_.address);
3421 connection_mark_for_close(TO_CONN(conn));
3422 return -1;
3425 if (!conn->base_.inbuf_reached_eof)
3426 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
3427 return 0;
3430 /** We are closing a dir connection: If <b>dir_conn</b> is a dir connection
3431 * that tried to fetch an HS descriptor, check if it successfuly fetched it,
3432 * or if we need to try again. */
3433 static void
3434 refetch_hsdesc_if_needed(dir_connection_t *dir_conn)
3436 connection_t *conn = TO_CONN(dir_conn);
3438 /* If we were trying to fetch a v2 rend desc and did not succeed, retry as
3439 * needed. (If a fetch is successful, the connection state is changed to
3440 * DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 or DIR_PURPOSE_HAS_FETCHED_HSDESC to
3441 * mark that refetching is unnecessary.) */
3442 if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
3443 dir_conn->rend_data &&
3444 rend_valid_v2_service_id(
3445 rend_data_get_address(dir_conn->rend_data))) {
3446 rend_client_refetch_v2_renddesc(dir_conn->rend_data);
3449 /* Check for v3 rend desc fetch */
3450 if (conn->purpose == DIR_PURPOSE_FETCH_HSDESC &&
3451 dir_conn->hs_ident &&
3452 !ed25519_public_key_is_zero(&dir_conn->hs_ident->identity_pk)) {
3453 hs_client_refetch_hsdesc(&dir_conn->hs_ident->identity_pk);
3457 /** Called when we're about to finally unlink and free a directory connection:
3458 * perform necessary accounting and cleanup */
3459 void
3460 connection_dir_about_to_close(dir_connection_t *dir_conn)
3462 connection_t *conn = TO_CONN(dir_conn);
3464 if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
3465 /* It's a directory connection and connecting or fetching
3466 * failed: forget about this router, and maybe try again. */
3467 connection_dir_request_failed(dir_conn);
3470 refetch_hsdesc_if_needed(dir_conn);
3473 /** Create an http response for the client <b>conn</b> out of
3474 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
3476 static void
3477 write_http_status_line(dir_connection_t *conn, int status,
3478 const char *reason_phrase)
3480 char buf[256];
3481 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
3482 status, reason_phrase ? reason_phrase : "OK") < 0) {
3483 log_warn(LD_BUG,"status line too long.");
3484 return;
3486 log_debug(LD_DIRSERV,"Wrote status 'HTTP/1.0 %d %s'", status, reason_phrase);
3487 connection_buf_add(buf, strlen(buf), TO_CONN(conn));
3490 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
3491 * with <b>type</b> as the Content-Type.
3493 * If <b>length</b> is nonnegative, it is the Content-Length.
3494 * If <b>encoding</b> is provided, it is the Content-Encoding.
3495 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
3496 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
3497 static void
3498 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
3499 const char *type, const char *encoding,
3500 const char *extra_headers,
3501 long cache_lifetime)
3503 char date[RFC1123_TIME_LEN+1];
3504 char tmp[1024];
3505 char *cp;
3506 time_t now = time(NULL);
3508 tor_assert(conn);
3510 format_rfc1123_time(date, now);
3511 cp = tmp;
3512 tor_snprintf(cp, sizeof(tmp),
3513 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
3514 date);
3515 cp += strlen(tmp);
3516 if (type) {
3517 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
3518 cp += strlen(cp);
3520 if (!is_local_addr(&conn->base_.addr)) {
3521 /* Don't report the source address for a nearby/private connection.
3522 * Otherwise we tend to mis-report in cases where incoming ports are
3523 * being forwarded to a Tor server running behind the firewall. */
3524 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
3525 X_ADDRESS_HEADER "%s\r\n", conn->base_.address);
3526 cp += strlen(cp);
3528 if (encoding) {
3529 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
3530 "Content-Encoding: %s\r\n", encoding);
3531 cp += strlen(cp);
3533 if (length >= 0) {
3534 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
3535 "Content-Length: %ld\r\n", (long)length);
3536 cp += strlen(cp);
3538 if (cache_lifetime > 0) {
3539 char expbuf[RFC1123_TIME_LEN+1];
3540 format_rfc1123_time(expbuf, (time_t)(now + cache_lifetime));
3541 /* We could say 'Cache-control: max-age=%d' here if we start doing
3542 * http/1.1 */
3543 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
3544 "Expires: %s\r\n", expbuf);
3545 cp += strlen(cp);
3546 } else if (cache_lifetime == 0) {
3547 /* We could say 'Cache-control: no-cache' here if we start doing
3548 * http/1.1 */
3549 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
3550 cp += strlen(cp);
3552 if (extra_headers) {
3553 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
3554 cp += strlen(cp);
3556 if (sizeof(tmp)-(cp-tmp) > 3)
3557 memcpy(cp, "\r\n", 3);
3558 else
3559 tor_assert(0);
3560 connection_buf_add(tmp, strlen(tmp), TO_CONN(conn));
3563 /** As write_http_response_header_impl, but sets encoding and content-typed
3564 * based on whether the response will be <b>compressed</b> or not. */
3565 static void
3566 write_http_response_headers(dir_connection_t *conn, ssize_t length,
3567 compress_method_t method,
3568 const char *extra_headers, long cache_lifetime)
3570 const char *methodname = compression_method_get_name(method);
3571 const char *doctype;
3572 if (method == NO_METHOD)
3573 doctype = "text/plain";
3574 else
3575 doctype = "application/octet-stream";
3576 write_http_response_header_impl(conn, length,
3577 doctype,
3578 methodname,
3579 extra_headers,
3580 cache_lifetime);
3583 /** As write_http_response_headers, but assumes extra_headers is NULL */
3584 static void
3585 write_http_response_header(dir_connection_t *conn, ssize_t length,
3586 compress_method_t method,
3587 long cache_lifetime)
3589 write_http_response_headers(conn, length, method, NULL, cache_lifetime);
3592 /** Array of compression methods to use (if supported) for serving
3593 * precompressed data, ordered from best to worst. */
3594 static compress_method_t srv_meth_pref_precompressed[] = {
3595 LZMA_METHOD,
3596 ZSTD_METHOD,
3597 ZLIB_METHOD,
3598 GZIP_METHOD,
3599 NO_METHOD
3602 /** Array of compression methods to use (if supported) for serving
3603 * streamed data, ordered from best to worst. */
3604 static compress_method_t srv_meth_pref_streaming_compression[] = {
3605 ZSTD_METHOD,
3606 ZLIB_METHOD,
3607 GZIP_METHOD,
3608 NO_METHOD
3611 /** Array of allowed compression methods to use (if supported) when receiving a
3612 * response from a request that was required to be anonymous. */
3613 static compress_method_t client_meth_allowed_anonymous_compression[] = {
3614 ZLIB_METHOD,
3615 GZIP_METHOD,
3616 NO_METHOD
3619 /** Parse the compression methods listed in an Accept-Encoding header <b>h</b>,
3620 * and convert them to a bitfield where compression method x is supported if
3621 * and only if 1 &lt;&lt; x is set in the bitfield. */
3622 STATIC unsigned
3623 parse_accept_encoding_header(const char *h)
3625 unsigned result = (1u << NO_METHOD);
3626 smartlist_t *methods = smartlist_new();
3627 smartlist_split_string(methods, h, ",",
3628 SPLIT_SKIP_SPACE|SPLIT_STRIP_SPACE|SPLIT_IGNORE_BLANK, 0);
3630 SMARTLIST_FOREACH_BEGIN(methods, const char *, m) {
3631 compress_method_t method = compression_method_get_by_name(m);
3632 if (method != UNKNOWN_METHOD) {
3633 tor_assert(((unsigned)method) < 8*sizeof(unsigned));
3634 result |= (1u << method);
3636 } SMARTLIST_FOREACH_END(m);
3637 SMARTLIST_FOREACH_BEGIN(methods, char *, m) {
3638 tor_free(m);
3639 } SMARTLIST_FOREACH_END(m);
3640 smartlist_free(methods);
3641 return result;
3644 /** Array of compression methods to use (if supported) for requesting
3645 * compressed data, ordered from best to worst. */
3646 static compress_method_t client_meth_pref[] = {
3647 LZMA_METHOD,
3648 ZSTD_METHOD,
3649 ZLIB_METHOD,
3650 GZIP_METHOD,
3651 NO_METHOD
3654 /** Return a newly allocated string containing a comma separated list of
3655 * supported encodings. */
3656 STATIC char *
3657 accept_encoding_header(void)
3659 smartlist_t *methods = smartlist_new();
3660 char *header = NULL;
3661 compress_method_t method;
3662 unsigned i;
3664 for (i = 0; i < ARRAY_LENGTH(client_meth_pref); ++i) {
3665 method = client_meth_pref[i];
3666 if (tor_compress_supports_method(method))
3667 smartlist_add(methods, (char *)compression_method_get_name(method));
3670 header = smartlist_join_strings(methods, ", ", 0, NULL);
3671 smartlist_free(methods);
3673 return header;
3676 /** Decide whether a client would accept the consensus we have.
3678 * Clients can say they only want a consensus if it's signed by more
3679 * than half the authorities in a list. They pass this list in
3680 * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
3682 * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
3683 * of the full authority identity digest. (Only strings of even length,
3684 * i.e. encodings of full bytes, are handled correctly. In the case
3685 * of an odd number of hex digits the last one is silently ignored.)
3687 * Returns 1 if more than half of the requested authorities signed the
3688 * consensus, 0 otherwise.
3691 client_likes_consensus(const struct consensus_cache_entry_t *ent,
3692 const char *want_url)
3694 smartlist_t *voters = smartlist_new();
3695 int need_at_least;
3696 int have = 0;
3698 if (consensus_cache_entry_get_voter_id_digests(ent, voters) != 0) {
3699 return 1; // We don't know the voters; assume the client won't mind. */
3702 smartlist_t *want_authorities = smartlist_new();
3703 dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0);
3704 need_at_least = smartlist_len(want_authorities)/2+1;
3706 SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, want_digest) {
3708 SMARTLIST_FOREACH_BEGIN(voters, const char *, digest) {
3709 if (!strcasecmpstart(digest, want_digest)) {
3710 have++;
3711 break;
3713 } SMARTLIST_FOREACH_END(digest);
3715 /* early exit, if we already have enough */
3716 if (have >= need_at_least)
3717 break;
3718 } SMARTLIST_FOREACH_END(want_digest);
3720 SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
3721 smartlist_free(want_authorities);
3722 SMARTLIST_FOREACH(voters, char *, cp, tor_free(cp));
3723 smartlist_free(voters);
3724 return (have >= need_at_least);
3727 /** Return the compression level we should use for sending a compressed
3728 * response of size <b>n_bytes</b>. */
3729 STATIC compression_level_t
3730 choose_compression_level(ssize_t n_bytes)
3732 if (! have_been_under_memory_pressure()) {
3733 return HIGH_COMPRESSION; /* we have plenty of RAM. */
3734 } else if (n_bytes < 0) {
3735 return HIGH_COMPRESSION; /* unknown; might be big. */
3736 } else if (n_bytes < 1024) {
3737 return LOW_COMPRESSION;
3738 } else if (n_bytes < 2048) {
3739 return MEDIUM_COMPRESSION;
3740 } else {
3741 return HIGH_COMPRESSION;
3745 /** Information passed to handle a GET request. */
3746 typedef struct get_handler_args_t {
3747 /** Bitmask of compression methods that the client said (or implied) it
3748 * supported. */
3749 unsigned compression_supported;
3750 /** If nonzero, the time included an if-modified-since header with this
3751 * value. */
3752 time_t if_modified_since;
3753 /** String containing the requested URL or resource. */
3754 const char *url;
3755 /** String containing the HTTP headers */
3756 const char *headers;
3757 } get_handler_args_t;
3759 /** Entry for handling an HTTP GET request.
3761 * This entry matches a request if "string" is equal to the requested
3762 * resource, or if "is_prefix" is true and "string" is a prefix of the
3763 * requested resource.
3765 * The 'handler' function is called to handle the request. It receives
3766 * an arguments structure, and must return 0 on success or -1 if we should
3767 * close the connection.
3769 typedef struct url_table_ent_s {
3770 const char *string;
3771 int is_prefix;
3772 int (*handler)(dir_connection_t *conn, const get_handler_args_t *args);
3773 } url_table_ent_t;
3775 static int handle_get_frontpage(dir_connection_t *conn,
3776 const get_handler_args_t *args);
3777 static int handle_get_current_consensus(dir_connection_t *conn,
3778 const get_handler_args_t *args);
3779 static int handle_get_status_vote(dir_connection_t *conn,
3780 const get_handler_args_t *args);
3781 static int handle_get_microdesc(dir_connection_t *conn,
3782 const get_handler_args_t *args);
3783 static int handle_get_descriptor(dir_connection_t *conn,
3784 const get_handler_args_t *args);
3785 static int handle_get_keys(dir_connection_t *conn,
3786 const get_handler_args_t *args);
3787 static int handle_get_hs_descriptor_v2(dir_connection_t *conn,
3788 const get_handler_args_t *args);
3789 static int handle_get_robots(dir_connection_t *conn,
3790 const get_handler_args_t *args);
3791 static int handle_get_networkstatus_bridges(dir_connection_t *conn,
3792 const get_handler_args_t *args);
3794 /** Table for handling GET requests. */
3795 static const url_table_ent_t url_table[] = {
3796 { "/tor/", 0, handle_get_frontpage },
3797 { "/tor/status-vote/current/consensus", 1, handle_get_current_consensus },
3798 { "/tor/status-vote/current/", 1, handle_get_status_vote },
3799 { "/tor/status-vote/next/", 1, handle_get_status_vote },
3800 { "/tor/micro/d/", 1, handle_get_microdesc },
3801 { "/tor/server/", 1, handle_get_descriptor },
3802 { "/tor/extra/", 1, handle_get_descriptor },
3803 { "/tor/keys/", 1, handle_get_keys },
3804 { "/tor/rendezvous2/", 1, handle_get_hs_descriptor_v2 },
3805 { "/tor/hs/3/", 1, handle_get_hs_descriptor_v3 },
3806 { "/tor/robots.txt", 0, handle_get_robots },
3807 { "/tor/networkstatus-bridges", 0, handle_get_networkstatus_bridges },
3808 { NULL, 0, NULL },
3811 /** Helper function: called when a dirserver gets a complete HTTP GET
3812 * request. Look for a request for a directory or for a rendezvous
3813 * service descriptor. On finding one, write a response into
3814 * conn-\>outbuf. If the request is unrecognized, send a 404.
3815 * Return 0 if we handled this successfully, or -1 if we need to close
3816 * the connection. */
3817 MOCK_IMPL(STATIC int,
3818 directory_handle_command_get,(dir_connection_t *conn, const char *headers,
3819 const char *req_body, size_t req_body_len))
3821 char *url, *url_mem, *header;
3822 time_t if_modified_since = 0;
3823 int zlib_compressed_in_url;
3824 size_t url_len;
3825 unsigned compression_methods_supported;
3827 /* We ignore the body of a GET request. */
3828 (void)req_body;
3829 (void)req_body_len;
3831 log_debug(LD_DIRSERV,"Received GET command.");
3833 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
3835 if (parse_http_url(headers, &url) < 0) {
3836 write_http_status_line(conn, 400, "Bad request");
3837 return 0;
3839 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
3840 struct tm tm;
3841 if (parse_http_time(header, &tm) == 0) {
3842 if (tor_timegm(&tm, &if_modified_since)<0) {
3843 if_modified_since = 0;
3844 } else {
3845 log_debug(LD_DIRSERV, "If-Modified-Since is '%s'.", escaped(header));
3848 /* The correct behavior on a malformed If-Modified-Since header is to
3849 * act as if no If-Modified-Since header had been given. */
3850 tor_free(header);
3852 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
3854 url_mem = url;
3855 url_len = strlen(url);
3857 zlib_compressed_in_url = url_len > 2 && !strcmp(url+url_len-2, ".z");
3858 if (zlib_compressed_in_url) {
3859 url[url_len-2] = '\0';
3860 url_len -= 2;
3863 if ((header = http_get_header(headers, "Accept-Encoding: "))) {
3864 compression_methods_supported = parse_accept_encoding_header(header);
3865 tor_free(header);
3866 } else {
3867 compression_methods_supported = (1u << NO_METHOD);
3869 if (zlib_compressed_in_url) {
3870 compression_methods_supported |= (1u << ZLIB_METHOD);
3873 /* Remove all methods that we don't both support. */
3874 compression_methods_supported &= tor_compress_get_supported_method_bitmask();
3876 get_handler_args_t args;
3877 args.url = url;
3878 args.headers = headers;
3879 args.if_modified_since = if_modified_since;
3880 args.compression_supported = compression_methods_supported;
3882 int i, result = -1;
3883 for (i = 0; url_table[i].string; ++i) {
3884 int match;
3885 if (url_table[i].is_prefix) {
3886 match = !strcmpstart(url, url_table[i].string);
3887 } else {
3888 match = !strcmp(url, url_table[i].string);
3890 if (match) {
3891 result = url_table[i].handler(conn, &args);
3892 goto done;
3896 /* we didn't recognize the url */
3897 write_http_status_line(conn, 404, "Not found");
3898 result = 0;
3900 done:
3901 tor_free(url_mem);
3902 return result;
3905 /** Helper function for GET / or GET /tor/
3907 static int
3908 handle_get_frontpage(dir_connection_t *conn, const get_handler_args_t *args)
3910 (void) args; /* unused */
3911 const char *frontpage = get_dirportfrontpage();
3913 if (frontpage) {
3914 size_t dlen;
3915 dlen = strlen(frontpage);
3916 /* Let's return a disclaimer page (users shouldn't use V1 anymore,
3917 and caches don't fetch '/', so this is safe). */
3919 /* [We don't check for write_bucket_low here, since we want to serve
3920 * this page no matter what.] */
3921 write_http_response_header_impl(conn, dlen, "text/html", "identity",
3922 NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
3923 connection_buf_add(frontpage, dlen, TO_CONN(conn));
3924 } else {
3925 write_http_status_line(conn, 404, "Not found");
3927 return 0;
3930 /** Warn that the cached consensus <b>consensus</b> of type
3931 * <b>flavor</b> is too old and will not be served to clients. Rate-limit the
3932 * warning to avoid logging an entry on every request.
3934 static void
3935 warn_consensus_is_too_old(const struct consensus_cache_entry_t *consensus,
3936 const char *flavor, time_t now)
3938 #define TOO_OLD_WARNING_INTERVAL (60*60)
3939 static ratelim_t warned = RATELIM_INIT(TOO_OLD_WARNING_INTERVAL);
3940 char timestamp[ISO_TIME_LEN+1];
3941 time_t valid_until;
3942 char *dupes;
3944 if (consensus_cache_entry_get_valid_until(consensus, &valid_until))
3945 return;
3947 if ((dupes = rate_limit_log(&warned, now))) {
3948 format_local_iso_time(timestamp, valid_until);
3949 log_warn(LD_DIRSERV, "Our %s%sconsensus is too old, so we will not "
3950 "serve it to clients. It was valid until %s local time and we "
3951 "continued to serve it for up to 24 hours after it expired.%s",
3952 flavor ? flavor : "", flavor ? " " : "", timestamp, dupes);
3953 tor_free(dupes);
3958 * Parse a single hex-encoded sha3-256 digest from <b>hex</b> into
3959 * <b>digest</b>. Return 0 on success. On failure, report that the hash came
3960 * from <b>location</b>, report that we are taking <b>action</b> with it, and
3961 * return -1.
3963 static int
3964 parse_one_diff_hash(uint8_t *digest, const char *hex, const char *location,
3965 const char *action)
3967 if (base16_decode((char*)digest, DIGEST256_LEN, hex, strlen(hex)) ==
3968 DIGEST256_LEN) {
3969 return 0;
3970 } else {
3971 log_fn(LOG_PROTOCOL_WARN, LD_DIR,
3972 "%s contained bogus digest %s; %s.",
3973 location, escaped(hex), action);
3974 return -1;
3978 /** If there is an X-Or-Diff-From-Consensus header included in <b>headers</b>,
3979 * set <b>digest_out<b> to a new smartlist containing every 256-bit
3980 * hex-encoded digest listed in that header and return 0. Otherwise return
3981 * -1. */
3982 static int
3983 parse_or_diff_from_header(smartlist_t **digests_out, const char *headers)
3985 char *hdr = http_get_header(headers, X_OR_DIFF_FROM_CONSENSUS_HEADER);
3986 if (hdr == NULL) {
3987 return -1;
3989 smartlist_t *hex_digests = smartlist_new();
3990 *digests_out = smartlist_new();
3991 smartlist_split_string(hex_digests, hdr, " ",
3992 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
3993 SMARTLIST_FOREACH_BEGIN(hex_digests, const char *, hex) {
3994 uint8_t digest[DIGEST256_LEN];
3995 if (!parse_one_diff_hash(digest, hex, "X-Or-Diff-From-Consensus header",
3996 "ignoring")) {
3997 smartlist_add(*digests_out, tor_memdup(digest, sizeof(digest)));
3999 } SMARTLIST_FOREACH_END(hex);
4000 SMARTLIST_FOREACH(hex_digests, char *, cp, tor_free(cp));
4001 smartlist_free(hex_digests);
4002 tor_free(hdr);
4003 return 0;
4006 /** Fallback compression method. The fallback compression method is used in
4007 * case a client requests a non-compressed document. We only store compressed
4008 * documents, so we use this compression method to fetch the document and let
4009 * the spooling system do the streaming decompression.
4011 #define FALLBACK_COMPRESS_METHOD ZLIB_METHOD
4014 * Try to find the best consensus diff possible in order to serve a client
4015 * request for a diff from one of the consensuses in <b>digests</b> to the
4016 * current consensus of flavor <b>flav</b>. The client supports the
4017 * compression methods listed in the <b>compression_methods</b> bitfield:
4018 * place the method chosen (if any) into <b>compression_used_out</b>.
4020 static struct consensus_cache_entry_t *
4021 find_best_diff(const smartlist_t *digests, int flav,
4022 unsigned compression_methods,
4023 compress_method_t *compression_used_out)
4025 struct consensus_cache_entry_t *result = NULL;
4027 SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, diff_from) {
4028 unsigned u;
4029 for (u = 0; u < ARRAY_LENGTH(srv_meth_pref_precompressed); ++u) {
4030 compress_method_t method = srv_meth_pref_precompressed[u];
4031 if (0 == (compression_methods & (1u<<method)))
4032 continue; // client doesn't like this one, or we don't have it.
4033 if (consdiffmgr_find_diff_from(&result, flav, DIGEST_SHA3_256,
4034 diff_from, DIGEST256_LEN,
4035 method) == CONSDIFF_AVAILABLE) {
4036 tor_assert_nonfatal(result);
4037 *compression_used_out = method;
4038 return result;
4041 } SMARTLIST_FOREACH_END(diff_from);
4043 SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, diff_from) {
4044 if (consdiffmgr_find_diff_from(&result, flav, DIGEST_SHA3_256, diff_from,
4045 DIGEST256_LEN, FALLBACK_COMPRESS_METHOD) == CONSDIFF_AVAILABLE) {
4046 tor_assert_nonfatal(result);
4047 *compression_used_out = FALLBACK_COMPRESS_METHOD;
4048 return result;
4050 } SMARTLIST_FOREACH_END(diff_from);
4052 return NULL;
4055 /** Lookup the cached consensus document by the flavor found in <b>flav</b>.
4056 * The prefered set of compression methods should be listed in the
4057 * <b>compression_methods</b> bitfield. The compression method chosen (if any)
4058 * is stored in <b>compression_used_out</b>. */
4059 static struct consensus_cache_entry_t *
4060 find_best_consensus(int flav,
4061 unsigned compression_methods,
4062 compress_method_t *compression_used_out)
4064 struct consensus_cache_entry_t *result = NULL;
4065 unsigned u;
4067 for (u = 0; u < ARRAY_LENGTH(srv_meth_pref_precompressed); ++u) {
4068 compress_method_t method = srv_meth_pref_precompressed[u];
4070 if (0 == (compression_methods & (1u<<method)))
4071 continue;
4073 if (consdiffmgr_find_consensus(&result, flav,
4074 method) == CONSDIFF_AVAILABLE) {
4075 tor_assert_nonfatal(result);
4076 *compression_used_out = method;
4077 return result;
4081 if (consdiffmgr_find_consensus(&result, flav,
4082 FALLBACK_COMPRESS_METHOD) == CONSDIFF_AVAILABLE) {
4083 tor_assert_nonfatal(result);
4084 *compression_used_out = FALLBACK_COMPRESS_METHOD;
4085 return result;
4088 return NULL;
4091 /** Try to find the best supported compression method possible from a given
4092 * <b>compression_methods</b>. Return NO_METHOD if no mutually supported
4093 * compression method could be found. */
4094 static compress_method_t
4095 find_best_compression_method(unsigned compression_methods, int stream)
4097 unsigned u;
4098 compress_method_t *methods;
4099 size_t length;
4101 if (stream) {
4102 methods = srv_meth_pref_streaming_compression;
4103 length = ARRAY_LENGTH(srv_meth_pref_streaming_compression);
4104 } else {
4105 methods = srv_meth_pref_precompressed;
4106 length = ARRAY_LENGTH(srv_meth_pref_precompressed);
4109 for (u = 0; u < length; ++u) {
4110 compress_method_t method = methods[u];
4111 if (compression_methods & (1u<<method))
4112 return method;
4115 return NO_METHOD;
4118 /** Check if any of the digests in <b>digests</b> matches the latest consensus
4119 * flavor (given in <b>flavor</b>) that we have available. */
4120 static int
4121 digest_list_contains_best_consensus(consensus_flavor_t flavor,
4122 const smartlist_t *digests)
4124 const networkstatus_t *ns = NULL;
4126 if (digests == NULL)
4127 return 0;
4129 ns = networkstatus_get_latest_consensus_by_flavor(flavor);
4131 if (ns == NULL)
4132 return 0;
4134 SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, digest) {
4135 if (tor_memeq(ns->digest_sha3_as_signed, digest, DIGEST256_LEN))
4136 return 1;
4137 } SMARTLIST_FOREACH_END(digest);
4139 return 0;
4142 /** Check if the given compression method is allowed for a connection that is
4143 * supposed to be anonymous. Returns 1 if the compression method is allowed,
4144 * otherwise 0. */
4145 STATIC int
4146 allowed_anonymous_connection_compression_method(compress_method_t method)
4148 unsigned u;
4150 for (u = 0; u < ARRAY_LENGTH(client_meth_allowed_anonymous_compression);
4151 ++u) {
4152 compress_method_t allowed_method =
4153 client_meth_allowed_anonymous_compression[u];
4155 if (! tor_compress_supports_method(allowed_method))
4156 continue;
4158 if (method == allowed_method)
4159 return 1;
4162 return 0;
4165 /** Log a warning when a remote server has sent us a document using a
4166 * compression method that is not allowed for anonymous directory requests. */
4167 STATIC void
4168 warn_disallowed_anonymous_compression_method(compress_method_t method)
4170 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
4171 "Received a %s HTTP response, which is not "
4172 "allowed for anonymous directory requests.",
4173 compression_method_get_human_name(method));
4176 /** Encodes the results of parsing a consensus request to figure out what
4177 * consensus, and possibly what diffs, the user asked for. */
4178 typedef struct {
4179 /** name of the flavor to retrieve. */
4180 char *flavor;
4181 /** flavor to retrive, as enum. */
4182 consensus_flavor_t flav;
4183 /** plus-separated list of authority fingerprints; see
4184 * client_likes_consensus(). Aliases the URL in the request passed to
4185 * parse_consensus_request(). */
4186 const char *want_fps;
4187 /** Optionally, a smartlist of sha3 digests-as-signed of the consensuses
4188 * to return a diff from. */
4189 smartlist_t *diff_from_digests;
4190 /** If true, never send a full consensus. If there is no diff, send
4191 * a 404 instead. */
4192 int diff_only;
4193 } parsed_consensus_request_t;
4195 /** Remove all data held in <b>req</b>. Do not free <b>req</b> itself, since
4196 * it is stack-allocated. */
4197 static void
4198 parsed_consensus_request_clear(parsed_consensus_request_t *req)
4200 if (!req)
4201 return;
4202 tor_free(req->flavor);
4203 if (req->diff_from_digests) {
4204 SMARTLIST_FOREACH(req->diff_from_digests, uint8_t *, d, tor_free(d));
4205 smartlist_free(req->diff_from_digests);
4207 memset(req, 0, sizeof(parsed_consensus_request_t));
4211 * Parse the URL and relevant headers of <b>args</b> for a current-consensus
4212 * request to learn what flavor of consensus we want, what keys it must be
4213 * signed with, and what diffs we would accept (or demand) instead. Return 0
4214 * on success and -1 on failure.
4216 static int
4217 parse_consensus_request(parsed_consensus_request_t *out,
4218 const get_handler_args_t *args)
4220 const char *url = args->url;
4221 memset(out, 0, sizeof(parsed_consensus_request_t));
4222 out->flav = FLAV_NS;
4224 const char CONSENSUS_URL_PREFIX[] = "/tor/status-vote/current/consensus/";
4225 const char CONSENSUS_FLAVORED_PREFIX[] =
4226 "/tor/status-vote/current/consensus-";
4228 /* figure out the flavor if any, and who we wanted to sign the thing */
4229 const char *after_flavor = NULL;
4231 if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) {
4232 const char *f, *cp;
4233 f = url + strlen(CONSENSUS_FLAVORED_PREFIX);
4234 cp = strchr(f, '/');
4235 if (cp) {
4236 after_flavor = cp+1;
4237 out->flavor = tor_strndup(f, cp-f);
4238 } else {
4239 out->flavor = tor_strdup(f);
4241 int flav = networkstatus_parse_flavor_name(out->flavor);
4242 if (flav < 0)
4243 flav = FLAV_NS;
4244 out->flav = flav;
4245 } else {
4246 if (!strcmpstart(url, CONSENSUS_URL_PREFIX))
4247 after_flavor = url+strlen(CONSENSUS_URL_PREFIX);
4250 /* see whether we've been asked explicitly for a diff from an older
4251 * consensus. (The user might also have said that a diff would be okay,
4252 * via X-Or-Diff-From-Consensus */
4253 const char DIFF_COMPONENT[] = "diff/";
4254 char *diff_hash_in_url = NULL;
4255 if (after_flavor && !strcmpstart(after_flavor, DIFF_COMPONENT)) {
4256 after_flavor += strlen(DIFF_COMPONENT);
4257 const char *cp = strchr(after_flavor, '/');
4258 if (cp) {
4259 diff_hash_in_url = tor_strndup(after_flavor, cp-after_flavor);
4260 out->want_fps = cp+1;
4261 } else {
4262 diff_hash_in_url = tor_strdup(after_flavor);
4263 out->want_fps = NULL;
4265 } else {
4266 out->want_fps = after_flavor;
4269 if (diff_hash_in_url) {
4270 uint8_t diff_from[DIGEST256_LEN];
4271 out->diff_from_digests = smartlist_new();
4272 out->diff_only = 1;
4273 int ok = !parse_one_diff_hash(diff_from, diff_hash_in_url, "URL",
4274 "rejecting");
4275 tor_free(diff_hash_in_url);
4276 if (ok) {
4277 smartlist_add(out->diff_from_digests,
4278 tor_memdup(diff_from, DIGEST256_LEN));
4279 } else {
4280 return -1;
4282 } else {
4283 parse_or_diff_from_header(&out->diff_from_digests, args->headers);
4286 return 0;
4289 /** Helper function for GET /tor/status-vote/current/consensus
4291 static int
4292 handle_get_current_consensus(dir_connection_t *conn,
4293 const get_handler_args_t *args)
4295 const compress_method_t compress_method =
4296 find_best_compression_method(args->compression_supported, 0);
4297 const time_t if_modified_since = args->if_modified_since;
4298 int clear_spool = 0;
4300 /* v3 network status fetch. */
4301 long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
4303 time_t now = time(NULL);
4304 parsed_consensus_request_t req;
4306 if (parse_consensus_request(&req, args) < 0) {
4307 write_http_status_line(conn, 404, "Couldn't parse request");
4308 goto done;
4311 if (digest_list_contains_best_consensus(req.flav,
4312 req.diff_from_digests)) {
4313 write_http_status_line(conn, 304, "Not modified");
4314 geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
4315 goto done;
4318 struct consensus_cache_entry_t *cached_consensus = NULL;
4320 compress_method_t compression_used = NO_METHOD;
4321 if (req.diff_from_digests) {
4322 cached_consensus = find_best_diff(req.diff_from_digests, req.flav,
4323 args->compression_supported,
4324 &compression_used);
4327 if (req.diff_only && !cached_consensus) {
4328 write_http_status_line(conn, 404, "No such diff available");
4329 // XXXX warn_consensus_is_too_old(v, req.flavor, now);
4330 geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
4331 goto done;
4334 if (! cached_consensus) {
4335 cached_consensus = find_best_consensus(req.flav,
4336 args->compression_supported,
4337 &compression_used);
4340 time_t fresh_until, valid_until;
4341 int have_fresh_until = 0, have_valid_until = 0;
4342 if (cached_consensus) {
4343 have_fresh_until =
4344 !consensus_cache_entry_get_fresh_until(cached_consensus, &fresh_until);
4345 have_valid_until =
4346 !consensus_cache_entry_get_valid_until(cached_consensus, &valid_until);
4349 if (cached_consensus && have_valid_until &&
4350 !networkstatus_valid_until_is_reasonably_live(valid_until, now)) {
4351 write_http_status_line(conn, 404, "Consensus is too old");
4352 warn_consensus_is_too_old(cached_consensus, req.flavor, now);
4353 geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
4354 goto done;
4357 if (cached_consensus && req.want_fps &&
4358 !client_likes_consensus(cached_consensus, req.want_fps)) {
4359 write_http_status_line(conn, 404, "Consensus not signed by sufficient "
4360 "number of requested authorities");
4361 geoip_note_ns_response(GEOIP_REJECT_NOT_ENOUGH_SIGS);
4362 goto done;
4365 conn->spool = smartlist_new();
4366 clear_spool = 1;
4368 spooled_resource_t *spooled;
4369 if (cached_consensus) {
4370 spooled = spooled_resource_new_from_cache_entry(cached_consensus);
4371 smartlist_add(conn->spool, spooled);
4375 lifetime = (have_fresh_until && fresh_until > now) ? fresh_until - now : 0;
4377 size_t size_guess = 0;
4378 int n_expired = 0;
4379 dirserv_spool_remove_missing_and_guess_size(conn, if_modified_since,
4380 compress_method != NO_METHOD,
4381 &size_guess,
4382 &n_expired);
4384 if (!smartlist_len(conn->spool) && !n_expired) {
4385 write_http_status_line(conn, 404, "Not found");
4386 geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
4387 goto done;
4388 } else if (!smartlist_len(conn->spool)) {
4389 write_http_status_line(conn, 304, "Not modified");
4390 geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
4391 goto done;
4394 if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
4395 log_debug(LD_DIRSERV,
4396 "Client asked for network status lists, but we've been "
4397 "writing too many bytes lately. Sending 503 Dir busy.");
4398 write_http_status_line(conn, 503, "Directory busy, try again later");
4399 geoip_note_ns_response(GEOIP_REJECT_BUSY);
4400 goto done;
4403 tor_addr_t addr;
4404 if (tor_addr_parse(&addr, (TO_CONN(conn))->address) >= 0) {
4405 geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS,
4406 &addr, NULL,
4407 time(NULL));
4408 geoip_note_ns_response(GEOIP_SUCCESS);
4409 /* Note that a request for a network status has started, so that we
4410 * can measure the download time later on. */
4411 if (conn->dirreq_id)
4412 geoip_start_dirreq(conn->dirreq_id, size_guess, DIRREQ_TUNNELED);
4413 else
4414 geoip_start_dirreq(TO_CONN(conn)->global_identifier, size_guess,
4415 DIRREQ_DIRECT);
4418 /* Use this header to tell caches that the response depends on the
4419 * X-Or-Diff-From-Consensus header (or lack thereof). */
4420 const char vary_header[] = "Vary: X-Or-Diff-From-Consensus\r\n";
4422 clear_spool = 0;
4424 // The compress_method might have been NO_METHOD, but we store the data
4425 // compressed. Decompress them using `compression_used`. See fallback code in
4426 // find_best_consensus() and find_best_diff().
4427 write_http_response_headers(conn, -1,
4428 compress_method == NO_METHOD ?
4429 NO_METHOD : compression_used,
4430 vary_header,
4431 smartlist_len(conn->spool) == 1 ? lifetime : 0);
4433 if (compress_method == NO_METHOD && smartlist_len(conn->spool))
4434 conn->compress_state = tor_compress_new(0, compression_used,
4435 HIGH_COMPRESSION);
4437 /* Prime the connection with some data. */
4438 const int initial_flush_result = connection_dirserv_flushed_some(conn);
4439 tor_assert_nonfatal(initial_flush_result == 0);
4440 goto done;
4442 done:
4443 parsed_consensus_request_clear(&req);
4444 if (clear_spool) {
4445 dir_conn_clear_spool(conn);
4447 return 0;
4450 /** Helper function for GET /tor/status-vote/{current,next}/...
4452 static int
4453 handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
4455 const char *url = args->url;
4457 int current;
4458 ssize_t body_len = 0;
4459 ssize_t estimated_len = 0;
4460 /* This smartlist holds strings that we can compress on the fly. */
4461 smartlist_t *items = smartlist_new();
4462 /* This smartlist holds cached_dir_t objects that have a precompressed
4463 * deflated version. */
4464 smartlist_t *dir_items = smartlist_new();
4465 int lifetime = 60; /* XXXX?? should actually use vote intervals. */
4466 url += strlen("/tor/status-vote/");
4467 current = !strcmpstart(url, "current/");
4468 url = strchr(url, '/');
4469 tor_assert(url);
4470 ++url;
4471 if (!strcmp(url, "consensus")) {
4472 const char *item;
4473 tor_assert(!current); /* we handle current consensus specially above,
4474 * since it wants to be spooled. */
4475 if ((item = dirvote_get_pending_consensus(FLAV_NS)))
4476 smartlist_add(items, (char*)item);
4477 } else if (!current && !strcmp(url, "consensus-signatures")) {
4478 /* XXXX the spec says that we should implement
4479 * current/consensus-signatures too. It doesn't seem to be needed,
4480 * though. */
4481 const char *item;
4482 if ((item=dirvote_get_pending_detached_signatures()))
4483 smartlist_add(items, (char*)item);
4484 } else if (!strcmp(url, "authority")) {
4485 const cached_dir_t *d;
4486 int flags = DGV_BY_ID |
4487 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
4488 if ((d=dirvote_get_vote(NULL, flags)))
4489 smartlist_add(dir_items, (cached_dir_t*)d);
4490 } else {
4491 const cached_dir_t *d;
4492 smartlist_t *fps = smartlist_new();
4493 int flags;
4494 if (!strcmpstart(url, "d/")) {
4495 url += 2;
4496 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
4497 } else {
4498 flags = DGV_BY_ID |
4499 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
4501 dir_split_resource_into_fingerprints(url, fps, NULL,
4502 DSR_HEX|DSR_SORT_UNIQ);
4503 SMARTLIST_FOREACH(fps, char *, fp, {
4504 if ((d = dirvote_get_vote(fp, flags)))
4505 smartlist_add(dir_items, (cached_dir_t*)d);
4506 tor_free(fp);
4508 smartlist_free(fps);
4510 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
4511 write_http_status_line(conn, 404, "Not found");
4512 goto vote_done;
4515 /* We're sending items from at most one kind of source */
4516 tor_assert_nonfatal(smartlist_len(items) == 0 ||
4517 smartlist_len(dir_items) == 0);
4519 int streaming;
4520 unsigned mask;
4521 if (smartlist_len(items)) {
4522 /* We're taking strings and compressing them on the fly. */
4523 streaming = 1;
4524 mask = ~0u;
4525 } else {
4526 /* We're taking cached_dir_t objects. We only have them uncompressed
4527 * or deflated. */
4528 streaming = 0;
4529 mask = (1u<<NO_METHOD) | (1u<<ZLIB_METHOD);
4531 const compress_method_t compress_method = find_best_compression_method(
4532 args->compression_supported&mask, streaming);
4534 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
4535 body_len += compress_method != NO_METHOD ?
4536 d->dir_compressed_len : d->dir_len);
4537 estimated_len += body_len;
4538 SMARTLIST_FOREACH(items, const char *, item, {
4539 size_t ln = strlen(item);
4540 if (compress_method != NO_METHOD) {
4541 estimated_len += ln/2;
4542 } else {
4543 body_len += ln; estimated_len += ln;
4547 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
4548 write_http_status_line(conn, 503, "Directory busy, try again later");
4549 goto vote_done;
4551 write_http_response_header(conn, body_len ? body_len : -1,
4552 compress_method,
4553 lifetime);
4555 if (smartlist_len(items)) {
4556 if (compress_method != NO_METHOD) {
4557 conn->compress_state = tor_compress_new(1, compress_method,
4558 choose_compression_level(estimated_len));
4559 SMARTLIST_FOREACH(items, const char *, c,
4560 connection_buf_add_compress(c, strlen(c), conn, 0));
4561 connection_buf_add_compress("", 0, conn, 1);
4562 } else {
4563 SMARTLIST_FOREACH(items, const char *, c,
4564 connection_buf_add(c, strlen(c), TO_CONN(conn)));
4566 } else {
4567 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
4568 connection_buf_add(compress_method != NO_METHOD ?
4569 d->dir_compressed : d->dir,
4570 compress_method != NO_METHOD ?
4571 d->dir_compressed_len : d->dir_len,
4572 TO_CONN(conn)));
4574 vote_done:
4575 smartlist_free(items);
4576 smartlist_free(dir_items);
4577 goto done;
4579 done:
4580 return 0;
4583 /** Helper function for GET /tor/micro/d/...
4585 static int
4586 handle_get_microdesc(dir_connection_t *conn, const get_handler_args_t *args)
4588 const char *url = args->url;
4589 const compress_method_t compress_method =
4590 find_best_compression_method(args->compression_supported, 1);
4591 int clear_spool = 1;
4593 conn->spool = smartlist_new();
4595 dir_split_resource_into_spoolable(url+strlen("/tor/micro/d/"),
4596 DIR_SPOOL_MICRODESC,
4597 conn->spool, NULL,
4598 DSR_DIGEST256|DSR_BASE64|DSR_SORT_UNIQ);
4600 size_t size_guess = 0;
4601 dirserv_spool_remove_missing_and_guess_size(conn, 0,
4602 compress_method != NO_METHOD,
4603 &size_guess, NULL);
4604 if (smartlist_len(conn->spool) == 0) {
4605 write_http_status_line(conn, 404, "Not found");
4606 goto done;
4608 if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
4609 log_info(LD_DIRSERV,
4610 "Client asked for server descriptors, but we've been "
4611 "writing too many bytes lately. Sending 503 Dir busy.");
4612 write_http_status_line(conn, 503, "Directory busy, try again later");
4613 goto done;
4616 clear_spool = 0;
4617 write_http_response_header(conn, -1,
4618 compress_method,
4619 MICRODESC_CACHE_LIFETIME);
4621 if (compress_method != NO_METHOD)
4622 conn->compress_state = tor_compress_new(1, compress_method,
4623 choose_compression_level(size_guess));
4625 const int initial_flush_result = connection_dirserv_flushed_some(conn);
4626 tor_assert_nonfatal(initial_flush_result == 0);
4627 goto done;
4630 done:
4631 if (clear_spool) {
4632 dir_conn_clear_spool(conn);
4634 return 0;
4637 /** Helper function for GET /tor/{server,extra}/...
4639 static int
4640 handle_get_descriptor(dir_connection_t *conn, const get_handler_args_t *args)
4642 const char *url = args->url;
4643 const compress_method_t compress_method =
4644 find_best_compression_method(args->compression_supported, 1);
4645 const or_options_t *options = get_options();
4646 int clear_spool = 1;
4647 if (!strcmpstart(url,"/tor/server/") ||
4648 (!options->BridgeAuthoritativeDir &&
4649 !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
4650 int res;
4651 const char *msg = NULL;
4652 int cache_lifetime = 0;
4653 int is_extra = !strcmpstart(url,"/tor/extra/");
4654 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
4655 dir_spool_source_t source;
4656 time_t publish_cutoff = 0;
4657 if (!strcmpstart(url, "d/")) {
4658 source =
4659 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
4660 } else {
4661 source =
4662 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
4663 /* We only want to apply a publish cutoff when we're requesting
4664 * resources by fingerprint. */
4665 publish_cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
4668 conn->spool = smartlist_new();
4669 res = dirserv_get_routerdesc_spool(conn->spool, url,
4670 source,
4671 connection_dir_is_encrypted(conn),
4672 &msg);
4674 if (!strcmpstart(url, "all")) {
4675 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
4676 } else if (smartlist_len(conn->spool) == 1) {
4677 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
4680 size_t size_guess = 0;
4681 int n_expired = 0;
4682 dirserv_spool_remove_missing_and_guess_size(conn, publish_cutoff,
4683 compress_method != NO_METHOD,
4684 &size_guess, &n_expired);
4686 /* If we are the bridge authority and the descriptor is a bridge
4687 * descriptor, remember that we served this descriptor for desc stats. */
4688 /* XXXX it's a bit of a kludge to have this here. */
4689 if (get_options()->BridgeAuthoritativeDir &&
4690 source == DIR_SPOOL_SERVER_BY_FP) {
4691 SMARTLIST_FOREACH_BEGIN(conn->spool, spooled_resource_t *, spooled) {
4692 const routerinfo_t *router =
4693 router_get_by_id_digest((const char *)spooled->digest);
4694 /* router can be NULL here when the bridge auth is asked for its own
4695 * descriptor. */
4696 if (router && router->purpose == ROUTER_PURPOSE_BRIDGE)
4697 rep_hist_note_desc_served(router->cache_info.identity_digest);
4698 } SMARTLIST_FOREACH_END(spooled);
4701 if (res < 0 || size_guess == 0 || smartlist_len(conn->spool) == 0) {
4702 if (msg == NULL)
4703 msg = "Not found";
4704 write_http_status_line(conn, 404, msg);
4705 } else {
4706 if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
4707 log_info(LD_DIRSERV,
4708 "Client asked for server descriptors, but we've been "
4709 "writing too many bytes lately. Sending 503 Dir busy.");
4710 write_http_status_line(conn, 503, "Directory busy, try again later");
4711 dir_conn_clear_spool(conn);
4712 goto done;
4714 write_http_response_header(conn, -1, compress_method, cache_lifetime);
4715 if (compress_method != NO_METHOD)
4716 conn->compress_state = tor_compress_new(1, compress_method,
4717 choose_compression_level(size_guess));
4718 clear_spool = 0;
4719 /* Prime the connection with some data. */
4720 int initial_flush_result = connection_dirserv_flushed_some(conn);
4721 tor_assert_nonfatal(initial_flush_result == 0);
4723 goto done;
4725 done:
4726 if (clear_spool)
4727 dir_conn_clear_spool(conn);
4728 return 0;
4731 /** Helper function for GET /tor/keys/...
4733 static int
4734 handle_get_keys(dir_connection_t *conn, const get_handler_args_t *args)
4736 const char *url = args->url;
4737 const compress_method_t compress_method =
4738 find_best_compression_method(args->compression_supported, 1);
4739 const time_t if_modified_since = args->if_modified_since;
4741 smartlist_t *certs = smartlist_new();
4742 ssize_t len = -1;
4743 if (!strcmp(url, "/tor/keys/all")) {
4744 authority_cert_get_all(certs);
4745 } else if (!strcmp(url, "/tor/keys/authority")) {
4746 authority_cert_t *cert = get_my_v3_authority_cert();
4747 if (cert)
4748 smartlist_add(certs, cert);
4749 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
4750 smartlist_t *fps = smartlist_new();
4751 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
4752 fps, NULL,
4753 DSR_HEX|DSR_SORT_UNIQ);
4754 SMARTLIST_FOREACH(fps, char *, d, {
4755 authority_cert_t *c = authority_cert_get_newest_by_id(d);
4756 if (c) smartlist_add(certs, c);
4757 tor_free(d);
4759 smartlist_free(fps);
4760 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
4761 smartlist_t *fps = smartlist_new();
4762 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
4763 fps, NULL,
4764 DSR_HEX|DSR_SORT_UNIQ);
4765 SMARTLIST_FOREACH(fps, char *, d, {
4766 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
4767 if (c) smartlist_add(certs, c);
4768 tor_free(d);
4770 smartlist_free(fps);
4771 } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
4772 smartlist_t *fp_sks = smartlist_new();
4773 dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
4774 fp_sks);
4775 SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
4776 authority_cert_t *c = authority_cert_get_by_digests(pair->first,
4777 pair->second);
4778 if (c) smartlist_add(certs, c);
4779 tor_free(pair);
4781 smartlist_free(fp_sks);
4782 } else {
4783 write_http_status_line(conn, 400, "Bad request");
4784 goto keys_done;
4786 if (!smartlist_len(certs)) {
4787 write_http_status_line(conn, 404, "Not found");
4788 goto keys_done;
4790 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
4791 if (c->cache_info.published_on < if_modified_since)
4792 SMARTLIST_DEL_CURRENT(certs, c));
4793 if (!smartlist_len(certs)) {
4794 write_http_status_line(conn, 304, "Not modified");
4795 goto keys_done;
4797 len = 0;
4798 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
4799 len += c->cache_info.signed_descriptor_len);
4801 if (global_write_bucket_low(TO_CONN(conn),
4802 compress_method != NO_METHOD ? len/2 : len,
4803 2)) {
4804 write_http_status_line(conn, 503, "Directory busy, try again later");
4805 goto keys_done;
4808 write_http_response_header(conn,
4809 compress_method != NO_METHOD ? -1 : len,
4810 compress_method,
4811 60*60);
4812 if (compress_method != NO_METHOD) {
4813 conn->compress_state = tor_compress_new(1, compress_method,
4814 choose_compression_level(len));
4815 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
4816 connection_buf_add_compress(
4817 c->cache_info.signed_descriptor_body,
4818 c->cache_info.signed_descriptor_len,
4819 conn, 0));
4820 connection_buf_add_compress("", 0, conn, 1);
4821 } else {
4822 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
4823 connection_buf_add(c->cache_info.signed_descriptor_body,
4824 c->cache_info.signed_descriptor_len,
4825 TO_CONN(conn)));
4827 keys_done:
4828 smartlist_free(certs);
4829 goto done;
4831 done:
4832 return 0;
4835 /** Helper function for GET /tor/rendezvous2/
4837 static int
4838 handle_get_hs_descriptor_v2(dir_connection_t *conn,
4839 const get_handler_args_t *args)
4841 const char *url = args->url;
4842 if (connection_dir_is_encrypted(conn)) {
4843 /* Handle v2 rendezvous descriptor fetch request. */
4844 const char *descp;
4845 const char *query = url + strlen("/tor/rendezvous2/");
4846 if (rend_valid_descriptor_id(query)) {
4847 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
4848 safe_str(escaped(query)));
4849 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
4850 case 1: /* valid */
4851 write_http_response_header(conn, strlen(descp), NO_METHOD, 0);
4852 connection_buf_add(descp, strlen(descp), TO_CONN(conn));
4853 break;
4854 case 0: /* well-formed but not present */
4855 write_http_status_line(conn, 404, "Not found");
4856 break;
4857 case -1: /* not well-formed */
4858 write_http_status_line(conn, 400, "Bad request");
4859 break;
4861 } else { /* not well-formed */
4862 write_http_status_line(conn, 400, "Bad request");
4864 goto done;
4865 } else {
4866 /* Not encrypted! */
4867 write_http_status_line(conn, 404, "Not found");
4869 done:
4870 return 0;
4873 /** Helper function for GET /tor/hs/3/<z>. Only for version 3.
4875 STATIC int
4876 handle_get_hs_descriptor_v3(dir_connection_t *conn,
4877 const get_handler_args_t *args)
4879 int retval;
4880 const char *desc_str = NULL;
4881 const char *pubkey_str = NULL;
4882 const char *url = args->url;
4884 /* Reject unencrypted dir connections */
4885 if (!connection_dir_is_encrypted(conn)) {
4886 write_http_status_line(conn, 404, "Not found");
4887 goto done;
4890 /* After the path prefix follows the base64 encoded blinded pubkey which we
4891 * use to get the descriptor from the cache. Skip the prefix and get the
4892 * pubkey. */
4893 tor_assert(!strcmpstart(url, "/tor/hs/3/"));
4894 pubkey_str = url + strlen("/tor/hs/3/");
4895 retval = hs_cache_lookup_as_dir(HS_VERSION_THREE,
4896 pubkey_str, &desc_str);
4897 if (retval <= 0 || desc_str == NULL) {
4898 write_http_status_line(conn, 404, "Not found");
4899 goto done;
4902 /* Found requested descriptor! Pass it to this nice client. */
4903 write_http_response_header(conn, strlen(desc_str), NO_METHOD, 0);
4904 connection_buf_add(desc_str, strlen(desc_str), TO_CONN(conn));
4906 done:
4907 return 0;
4910 /** Helper function for GET /tor/networkstatus-bridges
4912 static int
4913 handle_get_networkstatus_bridges(dir_connection_t *conn,
4914 const get_handler_args_t *args)
4916 const char *headers = args->headers;
4918 const or_options_t *options = get_options();
4919 if (options->BridgeAuthoritativeDir &&
4920 options->BridgePassword_AuthDigest_ &&
4921 connection_dir_is_encrypted(conn)) {
4922 char *status;
4923 char digest[DIGEST256_LEN];
4925 char *header = http_get_header(headers, "Authorization: Basic ");
4926 if (header)
4927 crypto_digest256(digest, header, strlen(header), DIGEST_SHA256);
4929 /* now make sure the password is there and right */
4930 if (!header ||
4931 tor_memneq(digest,
4932 options->BridgePassword_AuthDigest_, DIGEST256_LEN)) {
4933 write_http_status_line(conn, 404, "Not found");
4934 tor_free(header);
4935 goto done;
4937 tor_free(header);
4939 /* all happy now. send an answer. */
4940 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
4941 size_t dlen = strlen(status);
4942 write_http_response_header(conn, dlen, NO_METHOD, 0);
4943 connection_buf_add(status, dlen, TO_CONN(conn));
4944 tor_free(status);
4945 goto done;
4947 done:
4948 return 0;
4951 /** Helper function for GET robots.txt or /tor/robots.txt */
4952 static int
4953 handle_get_robots(dir_connection_t *conn, const get_handler_args_t *args)
4955 (void)args;
4957 const char robots[] = "User-agent: *\r\nDisallow: /\r\n";
4958 size_t len = strlen(robots);
4959 write_http_response_header(conn, len, NO_METHOD, ROBOTS_CACHE_LIFETIME);
4960 connection_buf_add(robots, len, TO_CONN(conn));
4962 return 0;
4965 /* Given the <b>url</b> from a POST request, try to extract the version number
4966 * using the provided <b>prefix</b>. The version should be after the prefix and
4967 * ending with the seperator "/". For instance:
4968 * /tor/hs/3/publish
4970 * On success, <b>end_pos</b> points to the position right after the version
4971 * was found. On error, it is set to NULL.
4973 * Return version on success else negative value. */
4974 STATIC int
4975 parse_hs_version_from_post(const char *url, const char *prefix,
4976 const char **end_pos)
4978 int ok;
4979 unsigned long version;
4980 const char *start;
4981 char *end = NULL;
4983 tor_assert(url);
4984 tor_assert(prefix);
4985 tor_assert(end_pos);
4987 /* Check if the prefix does start the url. */
4988 if (strcmpstart(url, prefix)) {
4989 goto err;
4991 /* Move pointer to the end of the prefix string. */
4992 start = url + strlen(prefix);
4993 /* Try this to be the HS version and if we are still at the separator, next
4994 * will be move to the right value. */
4995 version = tor_parse_long(start, 10, 0, INT_MAX, &ok, &end);
4996 if (!ok) {
4997 goto err;
5000 *end_pos = end;
5001 return (int) version;
5002 err:
5003 *end_pos = NULL;
5004 return -1;
5007 /* Handle the POST request for a hidden service descripror. The request is in
5008 * <b>url</b>, the body of the request is in <b>body</b>. Return 200 on success
5009 * else return 400 indicating a bad request. */
5010 STATIC int
5011 handle_post_hs_descriptor(const char *url, const char *body)
5013 int version;
5014 const char *end_pos;
5016 tor_assert(url);
5017 tor_assert(body);
5019 version = parse_hs_version_from_post(url, "/tor/hs/", &end_pos);
5020 if (version < 0) {
5021 goto err;
5024 /* We have a valid version number, now make sure it's a publish request. Use
5025 * the end position just after the version and check for the command. */
5026 if (strcmpstart(end_pos, "/publish")) {
5027 goto err;
5030 switch (version) {
5031 case HS_VERSION_THREE:
5032 if (hs_cache_store_as_dir(body) < 0) {
5033 goto err;
5035 log_info(LD_REND, "Publish request for HS descriptor handled "
5036 "successfully.");
5037 break;
5038 default:
5039 /* Unsupported version, return a bad request. */
5040 goto err;
5043 return 200;
5044 err:
5045 /* Bad request. */
5046 return 400;
5049 /** Helper function: called when a dirserver gets a complete HTTP POST
5050 * request. Look for an uploaded server descriptor or rendezvous
5051 * service descriptor. On finding one, process it and write a
5052 * response into conn-\>outbuf. If the request is unrecognized, send a
5053 * 400. Always return 0. */
5054 MOCK_IMPL(STATIC int,
5055 directory_handle_command_post,(dir_connection_t *conn, const char *headers,
5056 const char *body, size_t body_len))
5058 char *url = NULL;
5059 const or_options_t *options = get_options();
5061 log_debug(LD_DIRSERV,"Received POST command.");
5063 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
5065 if (!public_server_mode(options)) {
5066 log_info(LD_DIR, "Rejected dir post request from %s "
5067 "since we're not a public relay.", conn->base_.address);
5068 write_http_status_line(conn, 503, "Not acting as a public relay");
5069 goto done;
5072 if (parse_http_url(headers, &url) < 0) {
5073 write_http_status_line(conn, 400, "Bad request");
5074 return 0;
5076 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
5078 /* Handle v2 rendezvous service publish request. */
5079 if (connection_dir_is_encrypted(conn) &&
5080 !strcmpstart(url,"/tor/rendezvous2/publish")) {
5081 if (rend_cache_store_v2_desc_as_dir(body) < 0) {
5082 log_warn(LD_REND, "Rejected v2 rend descriptor (body size %d) from %s.",
5083 (int)body_len, conn->base_.address);
5084 write_http_status_line(conn, 400,
5085 "Invalid v2 service descriptor rejected");
5086 } else {
5087 write_http_status_line(conn, 200, "Service descriptor (v2) stored");
5088 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
5090 goto done;
5093 /* Handle HS descriptor publish request. */
5094 /* XXX: This should be disabled with a consensus param until we want to
5095 * the prop224 be deployed and thus use. */
5096 if (connection_dir_is_encrypted(conn) && !strcmpstart(url, "/tor/hs/")) {
5097 const char *msg = "HS descriptor stored successfully.";
5099 /* We most probably have a publish request for an HS descriptor. */
5100 int code = handle_post_hs_descriptor(url, body);
5101 if (code != 200) {
5102 msg = "Invalid HS descriptor. Rejected.";
5104 write_http_status_line(conn, code, msg);
5105 goto done;
5108 if (!authdir_mode(options)) {
5109 /* we just provide cached directories; we don't want to
5110 * receive anything. */
5111 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
5112 "accept posted server descriptors");
5113 goto done;
5116 if (authdir_mode(options) &&
5117 !strcmp(url,"/tor/")) { /* server descriptor post */
5118 const char *msg = "[None]";
5119 uint8_t purpose = authdir_mode_bridge(options) ?
5120 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
5121 was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
5122 conn->base_.address, &msg);
5123 tor_assert(msg);
5125 if (r == ROUTER_ADDED_SUCCESSFULLY) {
5126 write_http_status_line(conn, 200, msg);
5127 } else if (WRA_WAS_OUTDATED(r)) {
5128 write_http_response_header_impl(conn, -1, NULL, NULL,
5129 "X-Descriptor-Not-New: Yes\r\n", -1);
5130 } else {
5131 log_info(LD_DIRSERV,
5132 "Rejected router descriptor or extra-info from %s "
5133 "(\"%s\").",
5134 conn->base_.address, msg);
5135 write_http_status_line(conn, 400, msg);
5137 goto done;
5140 if (authdir_mode_v3(options) &&
5141 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
5142 const char *msg = "OK";
5143 int status;
5144 if (dirvote_add_vote(body, &msg, &status)) {
5145 write_http_status_line(conn, status, "Vote stored");
5146 } else {
5147 tor_assert(msg);
5148 log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").",
5149 conn->base_.address, msg);
5150 write_http_status_line(conn, status, msg);
5152 goto done;
5155 if (authdir_mode_v3(options) &&
5156 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
5157 const char *msg = NULL;
5158 if (dirvote_add_signatures(body, conn->base_.address, &msg)>=0) {
5159 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
5160 } else {
5161 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
5162 conn->base_.address, msg?msg:"???");
5163 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
5165 goto done;
5168 /* we didn't recognize the url */
5169 write_http_status_line(conn, 404, "Not found");
5171 done:
5172 tor_free(url);
5173 return 0;
5176 /** Called when a dirserver receives data on a directory connection;
5177 * looks for an HTTP request. If the request is complete, remove it
5178 * from the inbuf, try to process it; otherwise, leave it on the
5179 * buffer. Return a 0 on success, or -1 on error.
5181 STATIC int
5182 directory_handle_command(dir_connection_t *conn)
5184 char *headers=NULL, *body=NULL;
5185 size_t body_len=0;
5186 int r;
5188 tor_assert(conn);
5189 tor_assert(conn->base_.type == CONN_TYPE_DIR);
5191 switch (connection_fetch_from_buf_http(TO_CONN(conn),
5192 &headers, MAX_HEADERS_SIZE,
5193 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
5194 case -1: /* overflow */
5195 log_warn(LD_DIRSERV,
5196 "Request too large from address '%s' to DirPort. Closing.",
5197 safe_str(conn->base_.address));
5198 return -1;
5199 case 0:
5200 log_debug(LD_DIRSERV,"command not all here yet.");
5201 return 0;
5202 /* case 1, fall through */
5205 http_set_address_origin(headers, TO_CONN(conn));
5206 // we should escape headers here as well,
5207 // but we can't call escaped() twice, as it uses the same buffer
5208 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, escaped(body));
5210 if (!strncasecmp(headers,"GET",3))
5211 r = directory_handle_command_get(conn, headers, body, body_len);
5212 else if (!strncasecmp(headers,"POST",4))
5213 r = directory_handle_command_post(conn, headers, body, body_len);
5214 else {
5215 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
5216 "Got headers %s with unknown command. Closing.",
5217 escaped(headers));
5218 r = -1;
5221 tor_free(headers); tor_free(body);
5222 return r;
5225 /** Write handler for directory connections; called when all data has
5226 * been flushed. Close the connection or wait for a response as
5227 * appropriate.
5230 connection_dir_finished_flushing(dir_connection_t *conn)
5232 tor_assert(conn);
5233 tor_assert(conn->base_.type == CONN_TYPE_DIR);
5235 /* Note that we have finished writing the directory response. For direct
5236 * connections this means we're done; for tunneled connections it's only
5237 * an intermediate step. */
5238 if (conn->dirreq_id)
5239 geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
5240 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
5241 else
5242 geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
5243 DIRREQ_DIRECT,
5244 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
5245 switch (conn->base_.state) {
5246 case DIR_CONN_STATE_CONNECTING:
5247 case DIR_CONN_STATE_CLIENT_SENDING:
5248 log_debug(LD_DIR,"client finished sending command.");
5249 conn->base_.state = DIR_CONN_STATE_CLIENT_READING;
5250 return 0;
5251 case DIR_CONN_STATE_SERVER_WRITING:
5252 if (conn->spool) {
5253 log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
5254 connection_mark_for_close(TO_CONN(conn));
5255 } else {
5256 log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
5257 connection_mark_for_close(TO_CONN(conn));
5259 return 0;
5260 default:
5261 log_warn(LD_BUG,"called in unexpected state %d.",
5262 conn->base_.state);
5263 tor_fragile_assert();
5264 return -1;
5266 return 0;
5269 /* We just got a new consensus! If there are other in-progress requests
5270 * for this consensus flavor (for example because we launched several in
5271 * parallel), cancel them.
5273 * We do this check here (not just in
5274 * connection_ap_handshake_attach_circuit()) to handle the edge case where
5275 * a consensus fetch begins and ends before some other one tries to attach to
5276 * a circuit, in which case the other one won't know that we're all happy now.
5278 * Don't mark the conn that just gave us the consensus -- otherwise we
5279 * would end up double-marking it when it cleans itself up.
5281 static void
5282 connection_dir_close_consensus_fetches(dir_connection_t *except_this_one,
5283 const char *resource)
5285 smartlist_t *conns_to_close =
5286 connection_dir_list_by_purpose_and_resource(DIR_PURPOSE_FETCH_CONSENSUS,
5287 resource);
5288 SMARTLIST_FOREACH_BEGIN(conns_to_close, dir_connection_t *, d) {
5289 if (d == except_this_one)
5290 continue;
5291 log_info(LD_DIR, "Closing consensus fetch (to %s) since one "
5292 "has just arrived.", TO_CONN(d)->address);
5293 connection_mark_for_close(TO_CONN(d));
5294 } SMARTLIST_FOREACH_END(d);
5295 smartlist_free(conns_to_close);
5298 /** Connected handler for directory connections: begin sending data to the
5299 * server, and return 0.
5300 * Only used when connections don't immediately connect. */
5302 connection_dir_finished_connecting(dir_connection_t *conn)
5304 tor_assert(conn);
5305 tor_assert(conn->base_.type == CONN_TYPE_DIR);
5306 tor_assert(conn->base_.state == DIR_CONN_STATE_CONNECTING);
5308 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
5309 conn->base_.address,conn->base_.port);
5311 /* start flushing conn */
5312 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
5313 return 0;
5316 /** Decide which download schedule we want to use based on descriptor type
5317 * in <b>dls</b> and <b>options</b>.
5318 * Then return a list of int pointers defining download delays in seconds.
5319 * Helper function for download_status_increment_failure(),
5320 * download_status_reset(), and download_status_increment_attempt(). */
5321 STATIC const smartlist_t *
5322 find_dl_schedule(const download_status_t *dls, const or_options_t *options)
5324 const int dir_server = dir_server_mode(options);
5325 const int multi_d = networkstatus_consensus_can_use_multiple_directories(
5326 options);
5327 const int we_are_bootstrapping = networkstatus_consensus_is_bootstrapping(
5328 time(NULL));
5329 const int use_fallbacks = networkstatus_consensus_can_use_extra_fallbacks(
5330 options);
5331 switch (dls->schedule) {
5332 case DL_SCHED_GENERIC:
5333 if (dir_server) {
5334 return options->TestingServerDownloadSchedule;
5335 } else {
5336 return options->TestingClientDownloadSchedule;
5338 case DL_SCHED_CONSENSUS:
5339 if (!multi_d) {
5340 return options->TestingServerConsensusDownloadSchedule;
5341 } else {
5342 if (we_are_bootstrapping) {
5343 if (!use_fallbacks) {
5344 /* A bootstrapping client without extra fallback directories */
5345 return
5346 options->ClientBootstrapConsensusAuthorityOnlyDownloadSchedule;
5347 } else if (dls->want_authority) {
5348 /* A bootstrapping client with extra fallback directories, but
5349 * connecting to an authority */
5350 return
5351 options->ClientBootstrapConsensusAuthorityDownloadSchedule;
5352 } else {
5353 /* A bootstrapping client connecting to extra fallback directories
5355 return
5356 options->ClientBootstrapConsensusFallbackDownloadSchedule;
5358 } else {
5359 return options->TestingClientConsensusDownloadSchedule;
5362 case DL_SCHED_BRIDGE:
5363 return options->TestingBridgeDownloadSchedule;
5364 default:
5365 tor_assert(0);
5368 /* Impossible, but gcc will fail with -Werror without a `return`. */
5369 return NULL;
5372 /** Decide which minimum and maximum delay step we want to use based on
5373 * descriptor type in <b>dls</b> and <b>options</b>.
5374 * Helper function for download_status_schedule_get_delay(). */
5375 STATIC void
5376 find_dl_min_and_max_delay(download_status_t *dls, const or_options_t *options,
5377 int *min, int *max)
5379 tor_assert(dls);
5380 tor_assert(options);
5381 tor_assert(min);
5382 tor_assert(max);
5385 * For now, just use the existing schedule config stuff and pick the
5386 * first/last entries off to get min/max delay for backoff purposes
5388 const smartlist_t *schedule = find_dl_schedule(dls, options);
5389 tor_assert(schedule != NULL && smartlist_len(schedule) >= 2);
5390 *min = *((int *)(smartlist_get(schedule, 0)));
5391 /* Increment on failure schedules always use exponential backoff, but they
5392 * have a smaller limit when they're deterministic */
5393 if (dls->backoff == DL_SCHED_DETERMINISTIC)
5394 *max = *((int *)((smartlist_get(schedule, smartlist_len(schedule) - 1))));
5395 else
5396 *max = INT_MAX;
5399 /** Advance one delay step. The algorithm is to use the previous delay to
5400 * compute an increment, we construct a value uniformly at random between
5401 * delay+1 and (delay*(DIR_DEFAULT_RANDOM_MULTIPLIER+1))+1 (or
5402 * DIR_TEST_NET_RANDOM_MULTIPLIER in test networks).
5403 * We then clamp that value to be no larger than max_delay, and return it.
5405 * Requires that delay is less than INT_MAX, and delay is in [0,max_delay].
5407 STATIC int
5408 next_random_exponential_delay(int delay, int max_delay)
5410 /* Check preconditions */
5411 if (BUG(max_delay < 0))
5412 max_delay = 0;
5413 if (BUG(delay > max_delay))
5414 delay = max_delay;
5415 if (delay == INT_MAX)
5416 return INT_MAX; /* prevent overflow */
5417 if (BUG(delay < 0))
5418 delay = 0;
5420 /* How much are we willing to add to the delay? */
5421 int max_increment;
5422 int multiplier = DIR_DEFAULT_RANDOM_MULTIPLIER;
5423 if (get_options()->TestingTorNetwork) {
5424 /* Decrease the multiplier in testing networks. This reduces the variance,
5425 * so that bootstrap is more reliable. */
5426 multiplier = DIR_TEST_NET_RANDOM_MULTIPLIER;
5429 if (delay && delay < (INT_MAX-1) / multiplier) {
5430 max_increment = delay * multiplier;
5431 } else if (delay) {
5432 max_increment = INT_MAX-1;
5433 } else {
5434 max_increment = 1;
5437 if (BUG(max_increment < 1))
5438 max_increment = 1;
5440 /* the + 1 here is so that we always wait longer than last time. */
5441 int increment = crypto_rand_int(max_increment)+1;
5443 if (increment < max_delay - delay)
5444 return delay + increment;
5445 else
5446 return max_delay;
5449 /** Find the current delay for dls based on schedule or min_delay/
5450 * max_delay if we're using exponential backoff. If dls->backoff is
5451 * DL_SCHED_RANDOM_EXPONENTIAL, we must have 0 <= min_delay <= max_delay <=
5452 * INT_MAX, but schedule may be set to NULL; otherwise schedule is required.
5453 * This function sets dls->next_attempt_at based on now, and returns the delay.
5454 * Helper for download_status_increment_failure and
5455 * download_status_increment_attempt. */
5456 STATIC int
5457 download_status_schedule_get_delay(download_status_t *dls,
5458 const smartlist_t *schedule,
5459 int min_delay, int max_delay,
5460 time_t now)
5462 tor_assert(dls);
5463 /* We don't need a schedule if we're using random exponential backoff */
5464 tor_assert(dls->backoff == DL_SCHED_RANDOM_EXPONENTIAL ||
5465 schedule != NULL);
5466 /* If we're using random exponential backoff, we do need min/max delay */
5467 tor_assert(dls->backoff != DL_SCHED_RANDOM_EXPONENTIAL ||
5468 (min_delay >= 0 && max_delay >= min_delay));
5470 int delay = INT_MAX;
5471 uint8_t dls_schedule_position = (dls->increment_on
5472 == DL_SCHED_INCREMENT_ATTEMPT
5473 ? dls->n_download_attempts
5474 : dls->n_download_failures);
5476 if (dls->backoff == DL_SCHED_DETERMINISTIC) {
5477 if (dls_schedule_position < smartlist_len(schedule))
5478 delay = *(int *)smartlist_get(schedule, dls_schedule_position);
5479 else if (dls_schedule_position == IMPOSSIBLE_TO_DOWNLOAD)
5480 delay = INT_MAX;
5481 else
5482 delay = *(int *)smartlist_get(schedule, smartlist_len(schedule) - 1);
5483 } else if (dls->backoff == DL_SCHED_RANDOM_EXPONENTIAL) {
5484 /* Check if we missed a reset somehow */
5485 IF_BUG_ONCE(dls->last_backoff_position > dls_schedule_position) {
5486 dls->last_backoff_position = 0;
5487 dls->last_delay_used = 0;
5490 if (dls_schedule_position > 0) {
5491 delay = dls->last_delay_used;
5493 while (dls->last_backoff_position < dls_schedule_position) {
5494 /* Do one increment step */
5495 delay = next_random_exponential_delay(delay, max_delay);
5496 /* Update our position */
5497 ++(dls->last_backoff_position);
5499 } else {
5500 /* If we're just starting out, use the minimum delay */
5501 delay = min_delay;
5504 /* Clamp it within min/max if we have them */
5505 if (min_delay >= 0 && delay < min_delay) delay = min_delay;
5506 if (max_delay != INT_MAX && delay > max_delay) delay = max_delay;
5508 /* Store it for next time */
5509 dls->last_backoff_position = dls_schedule_position;
5510 dls->last_delay_used = delay;
5513 /* A negative delay makes no sense. Knowing that delay is
5514 * non-negative allows us to safely do the wrapping check below. */
5515 tor_assert(delay >= 0);
5517 /* Avoid now+delay overflowing TIME_MAX, by comparing with a subtraction
5518 * that won't overflow (since delay is non-negative). */
5519 if (delay < INT_MAX && now <= TIME_MAX - delay) {
5520 dls->next_attempt_at = now+delay;
5521 } else {
5522 dls->next_attempt_at = TIME_MAX;
5525 return delay;
5528 /* Log a debug message about item, which increments on increment_action, has
5529 * incremented dls_n_download_increments times. The message varies based on
5530 * was_schedule_incremented (if not, not_incremented_response is logged), and
5531 * the values of increment, dls_next_attempt_at, and now.
5532 * Helper for download_status_increment_failure and
5533 * download_status_increment_attempt. */
5534 static void
5535 download_status_log_helper(const char *item, int was_schedule_incremented,
5536 const char *increment_action,
5537 const char *not_incremented_response,
5538 uint8_t dls_n_download_increments, int increment,
5539 time_t dls_next_attempt_at, time_t now)
5541 if (item) {
5542 if (!was_schedule_incremented)
5543 log_debug(LD_DIR, "%s %s %d time(s); I'll try again %s.",
5544 item, increment_action, (int)dls_n_download_increments,
5545 not_incremented_response);
5546 else if (increment == 0)
5547 log_debug(LD_DIR, "%s %s %d time(s); I'll try again immediately.",
5548 item, increment_action, (int)dls_n_download_increments);
5549 else if (dls_next_attempt_at < TIME_MAX)
5550 log_debug(LD_DIR, "%s %s %d time(s); I'll try again in %d seconds.",
5551 item, increment_action, (int)dls_n_download_increments,
5552 (int)(dls_next_attempt_at-now));
5553 else
5554 log_debug(LD_DIR, "%s %s %d time(s); Giving up for a while.",
5555 item, increment_action, (int)dls_n_download_increments);
5559 /** Determine when a failed download attempt should be retried.
5560 * Called when an attempt to download <b>dls</b> has failed with HTTP status
5561 * <b>status_code</b>. Increment the failure count (if the code indicates a
5562 * real failure, or if we're a server) and set <b>dls</b>-\>next_attempt_at to
5563 * an appropriate time in the future and return it.
5564 * If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_ATTEMPT, increment the
5565 * failure count, and return a time in the far future for the next attempt (to
5566 * avoid an immediate retry). */
5567 time_t
5568 download_status_increment_failure(download_status_t *dls, int status_code,
5569 const char *item, int server, time_t now)
5571 (void) status_code; // XXXX no longer used.
5572 (void) server; // XXXX no longer used.
5573 int increment = -1;
5574 int min_delay = 0, max_delay = INT_MAX;
5576 tor_assert(dls);
5578 /* dls wasn't reset before it was used */
5579 if (dls->next_attempt_at == 0) {
5580 download_status_reset(dls);
5583 /* count the failure */
5584 if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1) {
5585 ++dls->n_download_failures;
5588 if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
5589 /* We don't find out that a failure-based schedule has attempted a
5590 * connection until that connection fails.
5591 * We'll never find out about successful connections, but this doesn't
5592 * matter, because schedules are reset after a successful download.
5594 if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
5595 ++dls->n_download_attempts;
5597 /* only return a failure retry time if this schedule increments on failures
5599 const smartlist_t *schedule = find_dl_schedule(dls, get_options());
5600 find_dl_min_and_max_delay(dls, get_options(), &min_delay, &max_delay);
5601 increment = download_status_schedule_get_delay(dls, schedule,
5602 min_delay, max_delay, now);
5605 download_status_log_helper(item, !dls->increment_on, "failed",
5606 "concurrently", dls->n_download_failures,
5607 increment,
5608 download_status_get_next_attempt_at(dls),
5609 now);
5611 if (dls->increment_on == DL_SCHED_INCREMENT_ATTEMPT) {
5612 /* stop this schedule retrying on failure, it will launch concurrent
5613 * connections instead */
5614 return TIME_MAX;
5615 } else {
5616 return download_status_get_next_attempt_at(dls);
5620 /** Determine when the next download attempt should be made when using an
5621 * attempt-based (potentially concurrent) download schedule.
5622 * Called when an attempt to download <b>dls</b> is being initiated.
5623 * Increment the attempt count and set <b>dls</b>-\>next_attempt_at to an
5624 * appropriate time in the future and return it.
5625 * If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_FAILURE, don't increment
5626 * the attempts, and return a time in the far future (to avoid launching a
5627 * concurrent attempt). */
5628 time_t
5629 download_status_increment_attempt(download_status_t *dls, const char *item,
5630 time_t now)
5632 int delay = -1;
5633 int min_delay = 0, max_delay = INT_MAX;
5635 tor_assert(dls);
5637 /* dls wasn't reset before it was used */
5638 if (dls->next_attempt_at == 0) {
5639 download_status_reset(dls);
5642 if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
5643 /* this schedule should retry on failure, and not launch any concurrent
5644 attempts */
5645 log_warn(LD_BUG, "Tried to launch an attempt-based connection on a "
5646 "failure-based schedule.");
5647 return TIME_MAX;
5650 if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
5651 ++dls->n_download_attempts;
5653 const smartlist_t *schedule = find_dl_schedule(dls, get_options());
5654 find_dl_min_and_max_delay(dls, get_options(), &min_delay, &max_delay);
5655 delay = download_status_schedule_get_delay(dls, schedule,
5656 min_delay, max_delay, now);
5658 download_status_log_helper(item, dls->increment_on, "attempted",
5659 "on failure", dls->n_download_attempts,
5660 delay, download_status_get_next_attempt_at(dls),
5661 now);
5663 return download_status_get_next_attempt_at(dls);
5666 static time_t
5667 download_status_get_initial_delay_from_now(const download_status_t *dls)
5669 const smartlist_t *schedule = find_dl_schedule(dls, get_options());
5670 /* We use constant initial delays, even in exponential backoff
5671 * schedules. */
5672 return time(NULL) + *(int *)smartlist_get(schedule, 0);
5675 /** Reset <b>dls</b> so that it will be considered downloadable
5676 * immediately, and/or to show that we don't need it anymore.
5678 * Must be called to initialise a download schedule, otherwise the zeroth item
5679 * in the schedule will never be used.
5681 * (We find the zeroth element of the download schedule, and set
5682 * next_attempt_at to be the appropriate offset from 'now'. In most
5683 * cases this means setting it to 'now', so the item will be immediately
5684 * downloadable; in the case of bridge descriptors, the zeroth element
5685 * is an hour from now.) */
5686 void
5687 download_status_reset(download_status_t *dls)
5689 if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD
5690 || dls->n_download_attempts == IMPOSSIBLE_TO_DOWNLOAD)
5691 return; /* Don't reset this. */
5693 dls->n_download_failures = 0;
5694 dls->n_download_attempts = 0;
5695 dls->next_attempt_at = download_status_get_initial_delay_from_now(dls);
5696 dls->last_backoff_position = 0;
5697 dls->last_delay_used = 0;
5698 /* Don't reset dls->want_authority or dls->increment_on */
5701 /** Return the number of failures on <b>dls</b> since the last success (if
5702 * any). */
5704 download_status_get_n_failures(const download_status_t *dls)
5706 return dls->n_download_failures;
5709 /** Return the number of attempts to download <b>dls</b> since the last success
5710 * (if any). This can differ from download_status_get_n_failures() due to
5711 * outstanding concurrent attempts. */
5713 download_status_get_n_attempts(const download_status_t *dls)
5715 return dls->n_download_attempts;
5718 /** Return the next time to attempt to download <b>dls</b>. */
5719 time_t
5720 download_status_get_next_attempt_at(const download_status_t *dls)
5722 /* dls wasn't reset before it was used */
5723 if (dls->next_attempt_at == 0) {
5724 /* so give the answer we would have given if it had been */
5725 return download_status_get_initial_delay_from_now(dls);
5728 return dls->next_attempt_at;
5731 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
5732 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
5733 * either as descriptor digests or as identity digests based on
5734 * <b>was_descriptor_digests</b>).
5736 static void
5737 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
5738 int router_purpose,
5739 int was_extrainfo, int was_descriptor_digests)
5741 char digest[DIGEST_LEN];
5742 time_t now = time(NULL);
5743 int server = directory_fetches_from_authorities(get_options());
5744 if (!was_descriptor_digests) {
5745 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
5746 tor_assert(!was_extrainfo);
5747 connection_dir_retry_bridges(failed);
5749 return; /* FFFF should implement for other-than-router-purpose someday */
5751 SMARTLIST_FOREACH_BEGIN(failed, const char *, cp) {
5752 download_status_t *dls = NULL;
5753 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) != DIGEST_LEN) {
5754 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
5755 continue;
5757 if (was_extrainfo) {
5758 signed_descriptor_t *sd =
5759 router_get_by_extrainfo_digest(digest);
5760 if (sd)
5761 dls = &sd->ei_dl_status;
5762 } else {
5763 dls = router_get_dl_status_by_descriptor_digest(digest);
5765 if (!dls || dls->n_download_failures >=
5766 get_options()->TestingDescriptorMaxDownloadTries)
5767 continue;
5768 download_status_increment_failure(dls, status_code, cp, server, now);
5769 } SMARTLIST_FOREACH_END(cp);
5771 /* No need to relaunch descriptor downloads here: we already do it
5772 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
5775 /** Called when a connection to download microdescriptors has failed in whole
5776 * or in part. <b>failed</b> is a list of every microdesc digest we didn't
5777 * get. <b>status_code</b> is the http status code we received. Reschedule the
5778 * microdesc downloads as appropriate. */
5779 static void
5780 dir_microdesc_download_failed(smartlist_t *failed,
5781 int status_code)
5783 networkstatus_t *consensus
5784 = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
5785 routerstatus_t *rs;
5786 download_status_t *dls;
5787 time_t now = time(NULL);
5788 int server = directory_fetches_from_authorities(get_options());
5790 if (! consensus)
5791 return;
5792 SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
5793 rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
5794 if (!rs)
5795 continue;
5796 dls = &rs->dl_status;
5797 if (dls->n_download_failures >=
5798 get_options()->TestingMicrodescMaxDownloadTries)
5799 continue;
5801 char buf[BASE64_DIGEST256_LEN+1];
5802 digest256_to_base64(buf, d);
5803 download_status_increment_failure(dls, status_code, buf,
5804 server, now);
5806 } SMARTLIST_FOREACH_END(d);
5809 /** Helper. Compare two fp_pair_t objects, and return negative, 0, or
5810 * positive as appropriate. */
5811 static int
5812 compare_pairs_(const void **a, const void **b)
5814 const fp_pair_t *fp1 = *a, *fp2 = *b;
5815 int r;
5816 if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
5817 return r;
5818 else
5819 return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
5822 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
5823 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
5824 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
5825 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
5827 dir_split_resource_into_fingerprint_pairs(const char *res,
5828 smartlist_t *pairs_out)
5830 smartlist_t *pairs_tmp = smartlist_new();
5831 smartlist_t *pairs_result = smartlist_new();
5833 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
5834 if (smartlist_len(pairs_tmp)) {
5835 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
5836 size_t last_len = strlen(last);
5837 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
5838 last[last_len-2] = '\0';
5841 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
5842 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
5843 log_info(LD_DIR,
5844 "Skipping digest pair %s with non-standard length.", escaped(cp));
5845 } else if (cp[HEX_DIGEST_LEN] != '-') {
5846 log_info(LD_DIR,
5847 "Skipping digest pair %s with missing dash.", escaped(cp));
5848 } else {
5849 fp_pair_t pair;
5850 if (base16_decode(pair.first, DIGEST_LEN,
5851 cp, HEX_DIGEST_LEN) != DIGEST_LEN ||
5852 base16_decode(pair.second,DIGEST_LEN,
5853 cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN) != DIGEST_LEN) {
5854 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
5855 } else {
5856 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
5859 tor_free(cp);
5860 } SMARTLIST_FOREACH_END(cp);
5861 smartlist_free(pairs_tmp);
5863 /* Uniq-and-sort */
5864 smartlist_sort(pairs_result, compare_pairs_);
5865 smartlist_uniq(pairs_result, compare_pairs_, tor_free_);
5867 smartlist_add_all(pairs_out, pairs_result);
5868 smartlist_free(pairs_result);
5869 return 0;
5872 /** Given a directory <b>resource</b> request, containing zero
5873 * or more strings separated by plus signs, followed optionally by ".z", store
5874 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
5875 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
5877 * If (flags & DSR_HEX), then delete all elements that aren't hex digests, and
5878 * decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as
5879 * a separator, delete all the elements that aren't base64-encoded digests,
5880 * and decode the rest. If (flags & DSR_DIGEST256), these digests should be
5881 * 256 bits long; else they should be 160.
5883 * If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates.
5886 dir_split_resource_into_fingerprints(const char *resource,
5887 smartlist_t *fp_out, int *compressed_out,
5888 int flags)
5890 const int decode_hex = flags & DSR_HEX;
5891 const int decode_base64 = flags & DSR_BASE64;
5892 const int digests_are_256 = flags & DSR_DIGEST256;
5893 const int sort_uniq = flags & DSR_SORT_UNIQ;
5895 const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
5896 const int hex_digest_len = digests_are_256 ?
5897 HEX_DIGEST256_LEN : HEX_DIGEST_LEN;
5898 const int base64_digest_len = digests_are_256 ?
5899 BASE64_DIGEST256_LEN : BASE64_DIGEST_LEN;
5900 smartlist_t *fp_tmp = smartlist_new();
5902 tor_assert(!(decode_hex && decode_base64));
5903 tor_assert(fp_out);
5905 smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
5906 if (compressed_out)
5907 *compressed_out = 0;
5908 if (smartlist_len(fp_tmp)) {
5909 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
5910 size_t last_len = strlen(last);
5911 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
5912 last[last_len-2] = '\0';
5913 if (compressed_out)
5914 *compressed_out = 1;
5917 if (decode_hex || decode_base64) {
5918 const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
5919 int i;
5920 char *cp, *d = NULL;
5921 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
5922 cp = smartlist_get(fp_tmp, i);
5923 if (strlen(cp) != encoded_len) {
5924 log_info(LD_DIR,
5925 "Skipping digest %s with non-standard length.", escaped(cp));
5926 smartlist_del_keeporder(fp_tmp, i--);
5927 goto again;
5929 d = tor_malloc_zero(digest_len);
5930 if (decode_hex ?
5931 (base16_decode(d, digest_len, cp, hex_digest_len) != digest_len) :
5932 (base64_decode(d, digest_len, cp, base64_digest_len)
5933 != digest_len)) {
5934 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
5935 smartlist_del_keeporder(fp_tmp, i--);
5936 goto again;
5938 smartlist_set(fp_tmp, i, d);
5939 d = NULL;
5940 again:
5941 tor_free(cp);
5942 tor_free(d);
5945 if (sort_uniq) {
5946 if (decode_hex || decode_base64) {
5947 if (digests_are_256) {
5948 smartlist_sort_digests256(fp_tmp);
5949 smartlist_uniq_digests256(fp_tmp);
5950 } else {
5951 smartlist_sort_digests(fp_tmp);
5952 smartlist_uniq_digests(fp_tmp);
5954 } else {
5955 smartlist_sort_strings(fp_tmp);
5956 smartlist_uniq_strings(fp_tmp);
5959 smartlist_add_all(fp_out, fp_tmp);
5960 smartlist_free(fp_tmp);
5961 return 0;
5964 /** As dir_split_resource_into_fingerprints, but instead fills
5965 * <b>spool_out</b> with a list of spoolable_resource_t for the resource
5966 * identified through <b>source</b>. */
5968 dir_split_resource_into_spoolable(const char *resource,
5969 dir_spool_source_t source,
5970 smartlist_t *spool_out,
5971 int *compressed_out,
5972 int flags)
5974 smartlist_t *fingerprints = smartlist_new();
5976 tor_assert(flags & (DSR_HEX|DSR_BASE64));
5977 const size_t digest_len =
5978 (flags & DSR_DIGEST256) ? DIGEST256_LEN : DIGEST_LEN;
5980 int r = dir_split_resource_into_fingerprints(resource, fingerprints,
5981 compressed_out, flags);
5982 /* This is not a very efficient implementation XXXX */
5983 SMARTLIST_FOREACH_BEGIN(fingerprints, uint8_t *, digest) {
5984 spooled_resource_t *spooled =
5985 spooled_resource_new(source, digest, digest_len);
5986 if (spooled)
5987 smartlist_add(spool_out, spooled);
5988 tor_free(digest);
5989 } SMARTLIST_FOREACH_END(digest);
5991 smartlist_free(fingerprints);
5992 return r;