Implement Prop #260: Single Onion Services
[tor/appveyor.git] / src / or / directory.c
blob52b14b9baea09d3f83e0924d00ca460b8dbd2275
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2016, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "or.h"
7 #include "backtrace.h"
8 #include "buffers.h"
9 #include "circuitbuild.h"
10 #include "config.h"
11 #include "connection.h"
12 #include "connection_edge.h"
13 #include "control.h"
14 #include "directory.h"
15 #include "dirserv.h"
16 #include "dirvote.h"
17 #include "entrynodes.h"
18 #include "geoip.h"
19 #include "main.h"
20 #include "microdesc.h"
21 #include "networkstatus.h"
22 #include "nodelist.h"
23 #include "policies.h"
24 #include "relay.h"
25 #include "rendclient.h"
26 #include "rendcommon.h"
27 #include "rendservice.h"
28 #include "rephist.h"
29 #include "router.h"
30 #include "routerlist.h"
31 #include "routerparse.h"
32 #include "routerset.h"
33 #include "shared_random.h"
35 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
36 #ifndef OPENBSD
37 #include <malloc.h>
38 #endif
39 #endif
41 /**
42 * \file directory.c
43 * \brief Code to send and fetch directories and router
44 * descriptors via HTTP. Directories use dirserv.c to generate the
45 * results; clients use routers.c to parse them.
46 **/
48 /* In-points to directory.c:
50 * - directory_post_to_dirservers(), called from
51 * router_upload_dir_desc_to_dirservers() in router.c
52 * upload_service_descriptor() in rendservice.c
53 * - directory_get_from_dirserver(), called from
54 * rend_client_refetch_renddesc() in rendclient.c
55 * run_scheduled_events() in main.c
56 * do_hup() in main.c
57 * - connection_dir_process_inbuf(), called from
58 * connection_process_inbuf() in connection.c
59 * - connection_dir_finished_flushing(), called from
60 * connection_finished_flushing() in connection.c
61 * - connection_dir_finished_connecting(), called from
62 * connection_finished_connecting() in connection.c
64 static void directory_send_command(dir_connection_t *conn,
65 int purpose, int direct, const char *resource,
66 const char *payload, size_t payload_len,
67 time_t if_modified_since);
68 static int directory_handle_command(dir_connection_t *conn);
69 static int body_is_plausible(const char *body, size_t body_len, int purpose);
70 static char *http_get_header(const char *headers, const char *which);
71 static void http_set_address_origin(const char *headers, connection_t *conn);
72 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
73 static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn);
74 static void connection_dir_download_cert_failed(
75 dir_connection_t *conn, int status_code);
76 static void connection_dir_retry_bridges(smartlist_t *descs);
77 static void dir_routerdesc_download_failed(smartlist_t *failed,
78 int status_code,
79 int router_purpose,
80 int was_extrainfo,
81 int was_descriptor_digests);
82 static void dir_microdesc_download_failed(smartlist_t *failed,
83 int status_code);
84 static int client_likes_consensus(networkstatus_t *v, const char *want_url);
86 static void directory_initiate_command_rend(
87 const tor_addr_port_t *or_addr_port,
88 const tor_addr_port_t *dir_addr_port,
89 const char *digest,
90 uint8_t dir_purpose,
91 uint8_t router_purpose,
92 dir_indirection_t indirection,
93 const char *resource,
94 const char *payload,
95 size_t payload_len,
96 time_t if_modified_since,
97 const rend_data_t *rend_query);
99 static void connection_dir_close_consensus_fetches(
100 dir_connection_t *except_this_one, const char *resource);
102 /********* START VARIABLES **********/
104 /** How far in the future do we allow a directory server to tell us it is
105 * before deciding that one of us has the wrong time? */
106 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
108 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
110 /** HTTP cache control: how long do we tell proxies they can cache each
111 * kind of document we serve? */
112 #define FULL_DIR_CACHE_LIFETIME (60*60)
113 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
114 #define DIRPORTFRONTPAGE_CACHE_LIFETIME (20*60)
115 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
116 #define ROUTERDESC_CACHE_LIFETIME (30*60)
117 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
118 #define ROBOTS_CACHE_LIFETIME (24*60*60)
119 #define MICRODESC_CACHE_LIFETIME (48*60*60)
121 /********* END VARIABLES ************/
123 /** Return true iff the directory purpose <b>dir_purpose</b> (and if it's
124 * fetching descriptors, it's fetching them for <b>router_purpose</b>)
125 * must use an anonymous connection to a directory. */
127 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
129 if (get_options()->AllDirActionsPrivate)
130 return 1;
131 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
132 return 1; /* if no circuits yet, this might break bootstrapping, but it's
133 * needed to be safe. */
134 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
135 dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
136 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
137 dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
138 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
139 dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
140 dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
141 dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
142 dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
143 dir_purpose == DIR_PURPOSE_FETCH_MICRODESC)
144 return 0;
145 return 1;
148 /** Return a newly allocated string describing <b>auth</b>. Only describes
149 * authority features. */
150 STATIC char *
151 authdir_type_to_string(dirinfo_type_t auth)
153 char *result;
154 smartlist_t *lst = smartlist_new();
155 if (auth & V3_DIRINFO)
156 smartlist_add(lst, (void*)"V3");
157 if (auth & BRIDGE_DIRINFO)
158 smartlist_add(lst, (void*)"Bridge");
159 if (smartlist_len(lst)) {
160 result = smartlist_join_strings(lst, ", ", 0, NULL);
161 } else {
162 result = tor_strdup("[Not an authority]");
164 smartlist_free(lst);
165 return result;
168 /** Return a string describing a given directory connection purpose. */
169 STATIC const char *
170 dir_conn_purpose_to_string(int purpose)
172 switch (purpose)
174 case DIR_PURPOSE_UPLOAD_DIR:
175 return "server descriptor upload";
176 case DIR_PURPOSE_UPLOAD_VOTE:
177 return "server vote upload";
178 case DIR_PURPOSE_UPLOAD_SIGNATURES:
179 return "consensus signature upload";
180 case DIR_PURPOSE_FETCH_SERVERDESC:
181 return "server descriptor fetch";
182 case DIR_PURPOSE_FETCH_EXTRAINFO:
183 return "extra-info fetch";
184 case DIR_PURPOSE_FETCH_CONSENSUS:
185 return "consensus network-status fetch";
186 case DIR_PURPOSE_FETCH_CERTIFICATE:
187 return "authority cert fetch";
188 case DIR_PURPOSE_FETCH_STATUS_VOTE:
189 return "status vote fetch";
190 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
191 return "consensus signature fetch";
192 case DIR_PURPOSE_FETCH_RENDDESC_V2:
193 return "hidden-service v2 descriptor fetch";
194 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
195 return "hidden-service v2 descriptor upload";
196 case DIR_PURPOSE_FETCH_MICRODESC:
197 return "microdescriptor fetch";
200 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
201 return "(unknown)";
204 /** Return the requisite directory information types. */
205 STATIC dirinfo_type_t
206 dir_fetch_type(int dir_purpose, int router_purpose, const char *resource)
208 dirinfo_type_t type;
209 switch (dir_purpose) {
210 case DIR_PURPOSE_FETCH_EXTRAINFO:
211 type = EXTRAINFO_DIRINFO;
212 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
213 type |= BRIDGE_DIRINFO;
214 else
215 type |= V3_DIRINFO;
216 break;
217 case DIR_PURPOSE_FETCH_SERVERDESC:
218 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
219 type = BRIDGE_DIRINFO;
220 else
221 type = V3_DIRINFO;
222 break;
223 case DIR_PURPOSE_FETCH_STATUS_VOTE:
224 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
225 case DIR_PURPOSE_FETCH_CERTIFICATE:
226 type = V3_DIRINFO;
227 break;
228 case DIR_PURPOSE_FETCH_CONSENSUS:
229 type = V3_DIRINFO;
230 if (resource && !strcmp(resource, "microdesc"))
231 type |= MICRODESC_DIRINFO;
232 break;
233 case DIR_PURPOSE_FETCH_MICRODESC:
234 type = MICRODESC_DIRINFO;
235 break;
236 default:
237 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
238 type = NO_DIRINFO;
239 break;
241 return type;
244 /** Return true iff <b>identity_digest</b> is the digest of a router which
245 * says that it caches extrainfos. (If <b>is_authority</b> we always
246 * believe that to be true.) */
248 router_supports_extrainfo(const char *identity_digest, int is_authority)
250 const node_t *node = node_get_by_id(identity_digest);
252 if (node && node->ri) {
253 if (node->ri->caches_extra_info)
254 return 1;
256 if (is_authority) {
257 return 1;
259 return 0;
262 /** Return true iff any trusted directory authority has accepted our
263 * server descriptor.
265 * We consider any authority sufficient because waiting for all of
266 * them means it never happens while any authority is down; we don't
267 * go for something more complex in the middle (like \>1/3 or \>1/2 or
268 * \>=1/2) because that doesn't seem necessary yet.
271 directories_have_accepted_server_descriptor(void)
273 const smartlist_t *servers = router_get_trusted_dir_servers();
274 const or_options_t *options = get_options();
275 SMARTLIST_FOREACH(servers, dir_server_t *, d, {
276 if ((d->type & options->PublishServerDescriptor_) &&
277 d->has_accepted_serverdesc) {
278 return 1;
281 return 0;
284 /** Start a connection to every suitable directory authority, using
285 * connection purpose <b>dir_purpose</b> and uploading <b>payload</b>
286 * (of length <b>payload_len</b>). The dir_purpose should be one of
287 * 'DIR_PURPOSE_UPLOAD_{DIR|VOTE|SIGNATURES}'.
289 * <b>router_purpose</b> describes the type of descriptor we're
290 * publishing, if we're publishing a descriptor -- e.g. general or bridge.
292 * <b>type</b> specifies what sort of dir authorities (V3,
293 * BRIDGE, etc) we should upload to.
295 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
296 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
297 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
298 * to all authorities, and the extra-info document to all authorities that
299 * support it.
301 void
302 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
303 dirinfo_type_t type,
304 const char *payload,
305 size_t payload_len, size_t extrainfo_len)
307 const or_options_t *options = get_options();
308 dir_indirection_t indirection;
309 const smartlist_t *dirservers = router_get_trusted_dir_servers();
310 int found = 0;
311 const int exclude_self = (dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
312 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES);
313 tor_assert(dirservers);
314 /* This tries dirservers which we believe to be down, but ultimately, that's
315 * harmless, and we may as well err on the side of getting things uploaded.
317 SMARTLIST_FOREACH_BEGIN(dirservers, dir_server_t *, ds) {
318 routerstatus_t *rs = &(ds->fake_status);
319 size_t upload_len = payload_len;
321 if ((type & ds->type) == 0)
322 continue;
324 if (exclude_self && router_digest_is_me(ds->digest)) {
325 /* we don't upload to ourselves, but at least there's now at least
326 * one authority of this type that has what we wanted to upload. */
327 found = 1;
328 continue;
331 if (options->StrictNodes &&
332 routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) {
333 log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
334 "it's in our ExcludedNodes list and StrictNodes is set. "
335 "Skipping.",
336 ds->nickname,
337 dir_conn_purpose_to_string(dir_purpose));
338 continue;
341 found = 1; /* at least one authority of this type was listed */
342 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
343 ds->has_accepted_serverdesc = 0;
345 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
346 upload_len += extrainfo_len;
347 log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
348 (int) extrainfo_len);
350 if (purpose_needs_anonymity(dir_purpose, router_purpose)) {
351 indirection = DIRIND_ANONYMOUS;
352 } else if (!fascist_firewall_allows_dir_server(ds,
353 FIREWALL_DIR_CONNECTION,
354 0)) {
355 if (fascist_firewall_allows_dir_server(ds, FIREWALL_OR_CONNECTION, 0))
356 indirection = DIRIND_ONEHOP;
357 else
358 indirection = DIRIND_ANONYMOUS;
359 } else {
360 indirection = DIRIND_DIRECT_CONN;
362 directory_initiate_command_routerstatus(rs, dir_purpose,
363 router_purpose,
364 indirection,
365 NULL, payload, upload_len, 0);
366 } SMARTLIST_FOREACH_END(ds);
367 if (!found) {
368 char *s = authdir_type_to_string(type);
369 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
370 "of type '%s', but no authorities of that type listed!", s);
371 tor_free(s);
375 /** Return true iff, according to the values in <b>options</b>, we should be
376 * using directory guards for direct downloads of directory information. */
377 STATIC int
378 should_use_directory_guards(const or_options_t *options)
380 /* Public (non-bridge) servers never use directory guards. */
381 if (public_server_mode(options))
382 return 0;
383 /* If guards are disabled, or directory guards are disabled, we can't
384 * use directory guards.
386 if (!options->UseEntryGuards || !options->UseEntryGuardsAsDirGuards)
387 return 0;
388 /* If we're configured to fetch directory info aggressively or of a
389 * nonstandard type, don't use directory guards. */
390 if (options->DownloadExtraInfo || options->FetchDirInfoEarly ||
391 options->FetchDirInfoExtraEarly || options->FetchUselessDescriptors)
392 return 0;
393 return 1;
396 /** Pick an unconstrained directory server from among our guards, the latest
397 * networkstatus, or the fallback dirservers, for use in downloading
398 * information of type <b>type</b>, and return its routerstatus. */
399 static const routerstatus_t *
400 directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags,
401 uint8_t dir_purpose)
403 const routerstatus_t *rs = NULL;
404 const or_options_t *options = get_options();
406 if (options->UseBridges)
407 log_warn(LD_BUG, "Called when we have UseBridges set.");
409 if (should_use_directory_guards(options)) {
410 const node_t *node = choose_random_dirguard(type);
411 if (node)
412 rs = node->rs;
413 } else {
414 /* anybody with a non-zero dirport will do */
415 rs = router_pick_directory_server(type, pds_flags);
417 if (!rs) {
418 log_info(LD_DIR, "No router found for %s; falling back to "
419 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
420 rs = router_pick_fallback_dirserver(type, pds_flags);
423 return rs;
426 /** Start a connection to a random running directory server, using
427 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
428 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
429 * Use <b>pds_flags</b> as arguments to router_pick_directory_server()
430 * or router_pick_trusteddirserver().
432 MOCK_IMPL(void, directory_get_from_dirserver, (
433 uint8_t dir_purpose,
434 uint8_t router_purpose,
435 const char *resource,
436 int pds_flags,
437 download_want_authority_t want_authority))
439 const routerstatus_t *rs = NULL;
440 const or_options_t *options = get_options();
441 int prefer_authority = (directory_fetches_from_authorities(options)
442 || want_authority == DL_WANT_AUTHORITY);
443 int require_authority = 0;
444 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
445 dirinfo_type_t type = dir_fetch_type(dir_purpose, router_purpose, resource);
446 time_t if_modified_since = 0;
448 if (type == NO_DIRINFO)
449 return;
451 if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
452 int flav = FLAV_NS;
453 networkstatus_t *v;
454 if (resource)
455 flav = networkstatus_parse_flavor_name(resource);
457 /* DEFAULT_IF_MODIFIED_SINCE_DELAY is 1/20 of the default consensus
458 * period of 1 hour.
460 #define DEFAULT_IF_MODIFIED_SINCE_DELAY (180)
461 if (flav != -1) {
462 /* IF we have a parsed consensus of this type, we can do an
463 * if-modified-time based on it. */
464 v = networkstatus_get_latest_consensus_by_flavor(flav);
465 if (v) {
466 /* In networks with particularly short V3AuthVotingIntervals,
467 * ask for the consensus if it's been modified since half the
468 * V3AuthVotingInterval of the most recent consensus. */
469 time_t ims_delay = DEFAULT_IF_MODIFIED_SINCE_DELAY;
470 if (v->fresh_until > v->valid_after
471 && ims_delay > (v->fresh_until - v->valid_after)/2) {
472 ims_delay = (v->fresh_until - v->valid_after)/2;
474 if_modified_since = v->valid_after + ims_delay;
476 } else {
477 /* Otherwise it might be a consensus we don't parse, but which we
478 * do cache. Look at the cached copy, perhaps. */
479 cached_dir_t *cd = dirserv_get_consensus(resource);
480 /* We have no method of determining the voting interval from an
481 * unparsed consensus, so we use the default. */
482 if (cd)
483 if_modified_since = cd->published + DEFAULT_IF_MODIFIED_SINCE_DELAY;
487 if (!options->FetchServerDescriptors)
488 return;
490 if (!get_via_tor) {
491 if (options->UseBridges && !(type & BRIDGE_DIRINFO)) {
492 /* We want to ask a running bridge for which we have a descriptor.
494 * When we ask choose_random_entry() for a bridge, we specify what
495 * sort of dir fetch we'll be doing, so it won't return a bridge
496 * that can't answer our question.
498 /* XXX+++++ Not all bridges handle conditional consensus downloading,
499 * so, for now, never assume the server supports that. -PP
500 * Is that assumption still so in 2016? -NM */
501 const node_t *node = choose_random_dirguard(type);
502 if (node && node->ri) {
503 /* every bridge has a routerinfo. */
504 routerinfo_t *ri = node->ri;
505 /* clients always make OR connections to bridges */
506 tor_addr_port_t or_ap;
507 /* we are willing to use a non-preferred address if we need to */
508 fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0,
509 &or_ap);
510 directory_initiate_command(&or_ap.addr, or_ap.port,
511 NULL, 0, /*no dirport*/
512 ri->cache_info.identity_digest,
513 dir_purpose,
514 router_purpose,
515 DIRIND_ONEHOP,
516 resource, NULL, 0, if_modified_since);
517 } else
518 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
519 "nodes are available yet.");
520 return;
521 } else {
522 if (prefer_authority || (type & BRIDGE_DIRINFO)) {
523 /* only ask authdirservers, and don't ask myself */
524 rs = router_pick_trusteddirserver(type, pds_flags);
525 if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
526 PDS_NO_EXISTING_MICRODESC_FETCH))) {
527 /* We don't want to fetch from any authorities that we're currently
528 * fetching server descriptors from, and we got no match. Did we
529 * get no match because all the authorities have connections
530 * fetching server descriptors (in which case we should just
531 * return,) or because all the authorities are down or on fire or
532 * unreachable or something (in which case we should go on with
533 * our fallback code)? */
534 pds_flags &= ~(PDS_NO_EXISTING_SERVERDESC_FETCH|
535 PDS_NO_EXISTING_MICRODESC_FETCH);
536 rs = router_pick_trusteddirserver(type, pds_flags);
537 if (rs) {
538 log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
539 "are in use.");
540 return;
543 if (rs == NULL && require_authority) {
544 log_info(LD_DIR, "No authorities were available for %s: will try "
545 "later.", dir_conn_purpose_to_string(dir_purpose));
546 return;
549 if (!rs && !(type & BRIDGE_DIRINFO)) {
550 /* */
551 rs = directory_pick_generic_dirserver(type, pds_flags,
552 dir_purpose);
553 if (!rs)
554 get_via_tor = 1; /* last resort: try routing it via Tor */
559 if (get_via_tor) {
560 /* Never use fascistfirewall; we're going via Tor. */
561 pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
562 rs = router_pick_directory_server(type, pds_flags);
565 /* If we have any hope of building an indirect conn, we know some router
566 * descriptors. If (rs==NULL), we can't build circuits anyway, so
567 * there's no point in falling back to the authorities in this case. */
568 if (rs) {
569 const dir_indirection_t indirection =
570 get_via_tor ? DIRIND_ANONYMOUS : DIRIND_ONEHOP;
571 directory_initiate_command_routerstatus(rs, dir_purpose,
572 router_purpose,
573 indirection,
574 resource, NULL, 0,
575 if_modified_since);
576 } else {
577 log_notice(LD_DIR,
578 "While fetching directory info, "
579 "no running dirservers known. Will try again later. "
580 "(purpose %d)", dir_purpose);
581 if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
582 /* remember we tried them all and failed. */
583 directory_all_unreachable(time(NULL));
588 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
589 * directory authority other than ourself. Only for use by authorities when
590 * searching for missing information while voting. */
591 void
592 directory_get_from_all_authorities(uint8_t dir_purpose,
593 uint8_t router_purpose,
594 const char *resource)
596 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
597 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
599 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
600 dir_server_t *, ds) {
601 routerstatus_t *rs;
602 if (router_digest_is_me(ds->digest))
603 continue;
604 if (!(ds->type & V3_DIRINFO))
605 continue;
606 rs = &ds->fake_status;
607 directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
608 DIRIND_ONEHOP, resource, NULL,
609 0, 0);
610 } SMARTLIST_FOREACH_END(ds);
613 /** Return true iff <b>ind</b> requires a multihop circuit. */
614 static int
615 dirind_is_anon(dir_indirection_t ind)
617 return ind == DIRIND_ANON_DIRPORT || ind == DIRIND_ANONYMOUS;
620 /* Choose reachable OR and Dir addresses and ports from status, copying them
621 * into use_or_ap and use_dir_ap. If indirection is anonymous, then we're
622 * connecting via another relay, so choose the primary IPv4 address and ports.
624 * status should have at least one reachable address, if we can't choose a
625 * reachable address, warn and return -1. Otherwise, return 0.
627 static int
628 directory_choose_address_routerstatus(const routerstatus_t *status,
629 dir_indirection_t indirection,
630 tor_addr_port_t *use_or_ap,
631 tor_addr_port_t *use_dir_ap)
633 tor_assert(status != NULL);
634 tor_assert(use_or_ap != NULL);
635 tor_assert(use_dir_ap != NULL);
637 const or_options_t *options = get_options();
638 int have_or = 0, have_dir = 0;
640 /* We expect status to have at least one reachable address if we're
641 * connecting to it directly.
643 * Therefore, we can simply use the other address if the one we want isn't
644 * allowed by the firewall.
646 * (When Tor uploads and downloads a hidden service descriptor, it uses
647 * DIRIND_ANONYMOUS, except for Tor2Web, which uses DIRIND_ONEHOP.
648 * So this code will only modify the address for Tor2Web's HS descriptor
649 * fetches. Even Single Onion Servers (NYI) use DIRIND_ANONYMOUS, to avoid
650 * HSDirs denying service by rejecting descriptors.)
653 /* Initialise the OR / Dir addresses */
654 tor_addr_make_null(&use_or_ap->addr, AF_UNSPEC);
655 use_or_ap->port = 0;
656 tor_addr_make_null(&use_dir_ap->addr, AF_UNSPEC);
657 use_dir_ap->port = 0;
659 /* ORPort connections */
660 if (indirection == DIRIND_ANONYMOUS) {
661 if (status->addr) {
662 /* Since we're going to build a 3-hop circuit and ask the 2nd relay
663 * to extend to this address, always use the primary (IPv4) OR address */
664 tor_addr_from_ipv4h(&use_or_ap->addr, status->addr);
665 use_or_ap->port = status->or_port;
666 have_or = 1;
668 } else if (indirection == DIRIND_ONEHOP) {
669 /* We use an IPv6 address if we have one and we prefer it.
670 * Use the preferred address and port if they are reachable, otherwise,
671 * use the alternate address and port (if any).
673 have_or = fascist_firewall_choose_address_rs(status,
674 FIREWALL_OR_CONNECTION, 0,
675 use_or_ap);
678 /* DirPort connections
679 * DIRIND_ONEHOP uses ORPort, but may fall back to the DirPort on relays */
680 if (indirection == DIRIND_DIRECT_CONN ||
681 indirection == DIRIND_ANON_DIRPORT ||
682 (indirection == DIRIND_ONEHOP
683 && !directory_must_use_begindir(options))) {
684 have_dir = fascist_firewall_choose_address_rs(status,
685 FIREWALL_DIR_CONNECTION, 0,
686 use_dir_ap);
689 /* We rejected all addresses in the relay's status. This means we can't
690 * connect to it. */
691 if (!have_or && !have_dir) {
692 static int logged_backtrace = 0;
693 log_info(LD_BUG, "Rejected all OR and Dir addresses from %s when "
694 "launching an outgoing directory connection to: IPv4 %s OR %d "
695 "Dir %d IPv6 %s OR %d Dir %d", routerstatus_describe(status),
696 fmt_addr32(status->addr), status->or_port,
697 status->dir_port, fmt_addr(&status->ipv6_addr),
698 status->ipv6_orport, status->dir_port);
699 if (!logged_backtrace) {
700 log_backtrace(LOG_INFO, LD_BUG, "Addresses came from");
701 logged_backtrace = 1;
703 return -1;
706 return 0;
709 /** Same as directory_initiate_command_routerstatus(), but accepts
710 * rendezvous data to fetch a hidden service descriptor. */
711 void
712 directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
713 uint8_t dir_purpose,
714 uint8_t router_purpose,
715 dir_indirection_t indirection,
716 const char *resource,
717 const char *payload,
718 size_t payload_len,
719 time_t if_modified_since,
720 const rend_data_t *rend_query)
722 const or_options_t *options = get_options();
723 const node_t *node;
724 tor_addr_port_t use_or_ap, use_dir_ap;
725 const int anonymized_connection = dirind_is_anon(indirection);
727 tor_assert(status != NULL);
729 node = node_get_by_id(status->identity_digest);
731 /* XXX The below check is wrong: !node means it's not in the consensus,
732 * but we haven't checked if we have a descriptor for it -- and also,
733 * we only care about the descriptor if it's a begindir-style anonymized
734 * connection. */
735 if (!node && anonymized_connection) {
736 log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
737 "don't have its router descriptor.",
738 routerstatus_describe(status));
739 return;
742 if (options->ExcludeNodes && options->StrictNodes &&
743 routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
744 log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
745 "it's in our ExcludedNodes list and StrictNodes is set. "
746 "Skipping. This choice might make your Tor not work.",
747 routerstatus_describe(status),
748 dir_conn_purpose_to_string(dir_purpose));
749 return;
752 /* At this point, if we are a client making a direct connection to a
753 * directory server, we have selected a server that has at least one address
754 * allowed by ClientUseIPv4/6 and Reachable{"",OR,Dir}Addresses. This
755 * selection uses the preference in ClientPreferIPv6{OR,Dir}Port, if
756 * possible. (If UseBridges is set, clients always use IPv6, and prefer it
757 * by default.)
759 * Now choose an address that we can use to connect to the directory server.
761 if (directory_choose_address_routerstatus(status, indirection, &use_or_ap,
762 &use_dir_ap) < 0) {
763 return;
766 /* We don't retry the alternate OR/Dir address for the same directory if
767 * the address we choose fails (#6772).
768 * Instead, we'll retry another directory on failure. */
770 directory_initiate_command_rend(&use_or_ap, &use_dir_ap,
771 status->identity_digest,
772 dir_purpose, router_purpose,
773 indirection, resource,
774 payload, payload_len, if_modified_since,
775 rend_query);
778 /** Launch a new connection to the directory server <b>status</b> to
779 * upload or download a server or rendezvous
780 * descriptor. <b>dir_purpose</b> determines what
781 * kind of directory connection we're launching, and must be one of
782 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC_V2}. <b>router_purpose</b>
783 * specifies the descriptor purposes we have in mind (currently only
784 * used for FETCH_DIR).
786 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
787 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
789 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
790 * want to fetch.
792 MOCK_IMPL(void, directory_initiate_command_routerstatus,
793 (const routerstatus_t *status,
794 uint8_t dir_purpose,
795 uint8_t router_purpose,
796 dir_indirection_t indirection,
797 const char *resource,
798 const char *payload,
799 size_t payload_len,
800 time_t if_modified_since))
802 directory_initiate_command_routerstatus_rend(status, dir_purpose,
803 router_purpose,
804 indirection, resource,
805 payload, payload_len,
806 if_modified_since, NULL);
809 /** Return true iff <b>conn</b> is the client side of a directory connection
810 * we launched to ourself in order to determine the reachability of our
811 * dir_port. */
812 static int
813 directory_conn_is_self_reachability_test(dir_connection_t *conn)
815 if (conn->requested_resource &&
816 !strcmpstart(conn->requested_resource,"authority")) {
817 const routerinfo_t *me = router_get_my_routerinfo();
818 if (me &&
819 router_digest_is_me(conn->identity_digest) &&
820 tor_addr_eq_ipv4h(&conn->base_.addr, me->addr) && /*XXXX prop 118*/
821 me->dir_port == conn->base_.port)
822 return 1;
824 return 0;
827 /** Called when we are unable to complete the client's request to a directory
828 * server due to a network error: Mark the router as down and try again if
829 * possible.
831 static void
832 connection_dir_request_failed(dir_connection_t *conn)
834 if (directory_conn_is_self_reachability_test(conn)) {
835 return; /* this was a test fetch. don't retry. */
837 if (!entry_list_is_constrained(get_options()))
838 router_set_status(conn->identity_digest, 0); /* don't try this one again */
839 if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
840 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
841 log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
842 "directory server at '%s'; retrying",
843 conn->base_.address);
844 if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
845 connection_dir_bridge_routerdesc_failed(conn);
846 connection_dir_download_routerdesc_failed(conn);
847 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
848 if (conn->requested_resource)
849 networkstatus_consensus_download_failed(0, conn->requested_resource);
850 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
851 log_info(LD_DIR, "Giving up on certificate fetch from directory server "
852 "at '%s'; retrying",
853 conn->base_.address);
854 connection_dir_download_cert_failed(conn, 0);
855 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
856 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
857 conn->base_.address);
858 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
859 log_info(LD_DIR, "Giving up downloading votes from '%s'",
860 conn->base_.address);
861 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
862 log_info(LD_DIR, "Giving up on downloading microdescriptors from "
863 "directory server at '%s'; will retry", conn->base_.address);
864 connection_dir_download_routerdesc_failed(conn);
868 /** Helper: Attempt to fetch directly the descriptors of each bridge
869 * listed in <b>failed</b>.
871 static void
872 connection_dir_retry_bridges(smartlist_t *descs)
874 char digest[DIGEST_LEN];
875 SMARTLIST_FOREACH(descs, const char *, cp,
877 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) != DIGEST_LEN) {
878 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
879 escaped(cp));
880 continue;
882 retry_bridge_descriptor_fetch_directly(digest);
886 /** Called when an attempt to download one or more router descriptors
887 * or extra-info documents on connection <b>conn</b> failed.
889 static void
890 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
892 /* No need to increment the failure count for routerdescs, since
893 * it's not their fault. */
895 /* No need to relaunch descriptor downloads here: we already do it
896 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
897 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
898 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
899 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
901 (void) conn;
904 /** Called when an attempt to download a bridge's routerdesc from
905 * one of the authorities failed due to a network error. If
906 * possible attempt to download descriptors from the bridge directly.
908 static void
909 connection_dir_bridge_routerdesc_failed(dir_connection_t *conn)
911 smartlist_t *which = NULL;
913 /* Requests for bridge descriptors are in the form 'fp/', so ignore
914 anything else. */
915 if (!conn->requested_resource || strcmpstart(conn->requested_resource,"fp/"))
916 return;
918 which = smartlist_new();
919 dir_split_resource_into_fingerprints(conn->requested_resource
920 + strlen("fp/"),
921 which, NULL, 0);
923 tor_assert(conn->base_.purpose != DIR_PURPOSE_FETCH_EXTRAINFO);
924 if (smartlist_len(which)) {
925 connection_dir_retry_bridges(which);
926 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
928 smartlist_free(which);
931 /** Called when an attempt to fetch a certificate fails. */
932 static void
933 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
935 const char *fp_pfx = "fp/";
936 const char *fpsk_pfx = "fp-sk/";
937 smartlist_t *failed;
938 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
940 if (!conn->requested_resource)
941 return;
942 failed = smartlist_new();
944 * We have two cases download by fingerprint (resource starts
945 * with "fp/") or download by fingerprint/signing key pair
946 * (resource starts with "fp-sk/").
948 if (!strcmpstart(conn->requested_resource, fp_pfx)) {
949 /* Download by fingerprint case */
950 dir_split_resource_into_fingerprints(conn->requested_resource +
951 strlen(fp_pfx),
952 failed, NULL, DSR_HEX);
953 SMARTLIST_FOREACH_BEGIN(failed, char *, cp) {
954 /* Null signing key digest indicates download by fp only */
955 authority_cert_dl_failed(cp, NULL, status);
956 tor_free(cp);
957 } SMARTLIST_FOREACH_END(cp);
958 } else if (!strcmpstart(conn->requested_resource, fpsk_pfx)) {
959 /* Download by (fp,sk) pairs */
960 dir_split_resource_into_fingerprint_pairs(conn->requested_resource +
961 strlen(fpsk_pfx), failed);
962 SMARTLIST_FOREACH_BEGIN(failed, fp_pair_t *, cp) {
963 authority_cert_dl_failed(cp->first, cp->second, status);
964 tor_free(cp);
965 } SMARTLIST_FOREACH_END(cp);
966 } else {
967 log_warn(LD_DIR,
968 "Don't know what to do with failure for cert fetch %s",
969 conn->requested_resource);
972 smartlist_free(failed);
974 update_certificate_downloads(time(NULL));
977 /* Should this tor instance only use begindir for all its directory requests?
980 directory_must_use_begindir(const or_options_t *options)
982 /* Clients, onion services, and bridges must use begindir,
983 * relays and authorities do not have to */
984 return !public_server_mode(options);
987 /** Evaluate the situation and decide if we should use an encrypted
988 * "begindir-style" connection for this directory request.
989 * 1) If or_port is 0, or it's a direct conn and or_port is firewalled
990 * or we're a dir mirror, no.
991 * 2) If we prefer to avoid begindir conns, and we're not fetching or
992 * publishing a bridge relay descriptor, no.
993 * 3) Else yes.
994 * If returning 0, return in *reason why we can't use begindir.
995 * reason must not be NULL.
997 static int
998 directory_command_should_use_begindir(const or_options_t *options,
999 const tor_addr_t *addr,
1000 int or_port, uint8_t router_purpose,
1001 dir_indirection_t indirection,
1002 const char **reason)
1004 (void) router_purpose;
1005 tor_assert(reason);
1006 *reason = NULL;
1008 /* Reasons why we can't possibly use begindir */
1009 if (!or_port) {
1010 *reason = "directory with unknown ORPort";
1011 return 0; /* We don't know an ORPort -- no chance. */
1013 if (indirection == DIRIND_DIRECT_CONN ||
1014 indirection == DIRIND_ANON_DIRPORT) {
1015 *reason = "DirPort connection";
1016 return 0;
1018 if (indirection == DIRIND_ONEHOP) {
1019 /* We're firewalled and want a direct OR connection */
1020 if (!fascist_firewall_allows_address_addr(addr, or_port,
1021 FIREWALL_OR_CONNECTION, 0, 0)) {
1022 *reason = "ORPort not reachable";
1023 return 0;
1026 /* Reasons why we want to avoid using begindir */
1027 if (indirection == DIRIND_ONEHOP) {
1028 if (!directory_must_use_begindir(options)) {
1029 *reason = "in relay mode";
1030 return 0;
1033 /* DIRIND_ONEHOP on a client, or DIRIND_ANONYMOUS
1035 *reason = "(using begindir)";
1036 return 1;
1039 /** Helper for directory_initiate_command_rend: send the
1040 * command to a server whose OR address/port is <b>or_addr</b>/<b>or_port</b>,
1041 * whose directory address/port is <b>dir_addr</b>/<b>dir_port</b>, whose
1042 * identity key digest is <b>digest</b>, with purposes <b>dir_purpose</b> and
1043 * <b>router_purpose</b>, making an (in)direct connection as specified in
1044 * <b>indirection</b>, with command <b>resource</b>, <b>payload</b> of
1045 * <b>payload_len</b>, and asking for a result only <b>if_modified_since</b>.
1047 void
1048 directory_initiate_command(const tor_addr_t *or_addr, uint16_t or_port,
1049 const tor_addr_t *dir_addr, uint16_t dir_port,
1050 const char *digest,
1051 uint8_t dir_purpose, uint8_t router_purpose,
1052 dir_indirection_t indirection, const char *resource,
1053 const char *payload, size_t payload_len,
1054 time_t if_modified_since)
1056 tor_addr_port_t or_ap, dir_ap;
1058 /* Use the null tor_addr and 0 port if the address or port isn't valid. */
1059 if (tor_addr_port_is_valid(or_addr, or_port, 0)) {
1060 tor_addr_copy(&or_ap.addr, or_addr);
1061 or_ap.port = or_port;
1062 } else {
1063 /* the family doesn't matter here, so make it IPv4 */
1064 tor_addr_make_null(&or_ap.addr, AF_INET);
1065 or_ap.port = or_port = 0;
1068 if (tor_addr_port_is_valid(dir_addr, dir_port, 0)) {
1069 tor_addr_copy(&dir_ap.addr, dir_addr);
1070 dir_ap.port = dir_port;
1071 } else {
1072 /* the family doesn't matter here, so make it IPv4 */
1073 tor_addr_make_null(&dir_ap.addr, AF_INET);
1074 dir_ap.port = dir_port = 0;
1077 directory_initiate_command_rend(&or_ap, &dir_ap,
1078 digest, dir_purpose,
1079 router_purpose, indirection,
1080 resource, payload, payload_len,
1081 if_modified_since, NULL);
1084 /** Return non-zero iff a directory connection with purpose
1085 * <b>dir_purpose</b> reveals sensitive information about a Tor
1086 * instance's client activities. (Such connections must be performed
1087 * through normal three-hop Tor circuits.) */
1089 is_sensitive_dir_purpose(uint8_t dir_purpose)
1091 return ((dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2) ||
1092 (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
1093 (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
1096 /** Same as directory_initiate_command(), but accepts rendezvous data to
1097 * fetch a hidden service descriptor, and takes its address & port arguments
1098 * as tor_addr_port_t. */
1099 static void
1100 directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
1101 const tor_addr_port_t *dir_addr_port,
1102 const char *digest,
1103 uint8_t dir_purpose, uint8_t router_purpose,
1104 dir_indirection_t indirection,
1105 const char *resource,
1106 const char *payload, size_t payload_len,
1107 time_t if_modified_since,
1108 const rend_data_t *rend_query)
1110 tor_assert(or_addr_port);
1111 tor_assert(dir_addr_port);
1112 tor_assert(or_addr_port->port || dir_addr_port->port);
1113 tor_assert(digest);
1115 dir_connection_t *conn;
1116 const or_options_t *options = get_options();
1117 int socket_error = 0;
1118 const char *begindir_reason = NULL;
1119 /* Should the connection be to a relay's OR port (and inside that we will
1120 * send our directory request)? */
1121 const int use_begindir = directory_command_should_use_begindir(options,
1122 &or_addr_port->addr, or_addr_port->port,
1123 router_purpose, indirection,
1124 &begindir_reason);
1125 /* Will the connection go via a three-hop Tor circuit? Note that this
1126 * is separate from whether it will use_begindir. */
1127 const int anonymized_connection = dirind_is_anon(indirection);
1129 /* What is the address we want to make the directory request to? If
1130 * we're making a begindir request this is the ORPort of the relay
1131 * we're contacting; if not a begindir request, this is its DirPort.
1132 * Note that if anonymized_connection is true, we won't be initiating
1133 * a connection directly to this address. */
1134 tor_addr_t addr;
1135 tor_addr_copy(&addr, &(use_begindir ? or_addr_port : dir_addr_port)->addr);
1136 uint16_t port = (use_begindir ? or_addr_port : dir_addr_port)->port;
1138 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
1139 anonymized_connection, use_begindir);
1141 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
1143 if (is_sensitive_dir_purpose(dir_purpose)) {
1144 tor_assert(anonymized_connection ||
1145 rend_non_anonymous_mode_enabled(options));
1148 /* use encrypted begindir connections for everything except relays
1149 * this provides better protection for directory fetches */
1150 if (!use_begindir && directory_must_use_begindir(options)) {
1151 log_warn(LD_BUG, "Client could not use begindir connection: %s",
1152 begindir_reason ? begindir_reason : "(NULL)");
1153 return;
1156 /* ensure that we don't make direct connections when a SOCKS server is
1157 * configured. */
1158 if (!anonymized_connection && !use_begindir && !options->HTTPProxy &&
1159 (options->Socks4Proxy || options->Socks5Proxy)) {
1160 log_warn(LD_DIR, "Cannot connect to a directory server through a "
1161 "SOCKS proxy!");
1162 return;
1165 /* Make sure that the destination addr and port we picked is viable. */
1166 if (!port || tor_addr_is_null(&addr)) {
1167 static int logged_backtrace = 0;
1168 log_warn(LD_DIR,
1169 "Cannot make an outgoing %sconnection without %sPort.",
1170 use_begindir ? "begindir " : "",
1171 use_begindir ? "an OR" : "a Dir");
1172 if (!logged_backtrace) {
1173 log_backtrace(LOG_INFO, LD_BUG, "Address came from");
1174 logged_backtrace = 1;
1176 return;
1179 conn = dir_connection_new(tor_addr_family(&addr));
1181 /* set up conn so it's got all the data we need to remember */
1182 tor_addr_copy(&conn->base_.addr, &addr);
1183 conn->base_.port = port;
1184 conn->base_.address = tor_addr_to_str_dup(&addr);
1185 memcpy(conn->identity_digest, digest, DIGEST_LEN);
1187 conn->base_.purpose = dir_purpose;
1188 conn->router_purpose = router_purpose;
1190 /* give it an initial state */
1191 conn->base_.state = DIR_CONN_STATE_CONNECTING;
1193 /* decide whether we can learn our IP address from this conn */
1194 /* XXXX This is a bad name for this field now. */
1195 conn->dirconn_direct = !anonymized_connection;
1197 /* copy rendezvous data, if any */
1198 if (rend_query)
1199 conn->rend_data = rend_data_dup(rend_query);
1201 if (!anonymized_connection && !use_begindir) {
1202 /* then we want to connect to dirport directly */
1204 if (options->HTTPProxy) {
1205 tor_addr_copy(&addr, &options->HTTPProxyAddr);
1206 port = options->HTTPProxyPort;
1209 switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr,
1210 port, &socket_error)) {
1211 case -1:
1212 connection_mark_for_close(TO_CONN(conn));
1213 return;
1214 case 1:
1215 /* start flushing conn */
1216 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
1217 /* fall through */
1218 case 0:
1219 /* queue the command on the outbuf */
1220 directory_send_command(conn, dir_purpose, 1, resource,
1221 payload, payload_len,
1222 if_modified_since);
1223 connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT);
1224 /* writable indicates finish, readable indicates broken link,
1225 error indicates broken link in windowsland. */
1227 } else {
1228 /* We will use a Tor circuit (maybe 1-hop, maybe 3-hop, maybe with
1229 * begindir, maybe not with begindir) */
1231 entry_connection_t *linked_conn;
1233 /* Anonymized tunneled connections can never share a circuit.
1234 * One-hop directory connections can share circuits with each other
1235 * but nothing else. */
1236 int iso_flags = anonymized_connection ? ISO_STREAM : ISO_SESSIONGRP;
1238 /* If it's an anonymized connection, remember the fact that we
1239 * wanted it for later: maybe we'll want it again soon. */
1240 if (anonymized_connection && use_begindir)
1241 rep_hist_note_used_internal(time(NULL), 0, 1);
1242 else if (anonymized_connection && !use_begindir)
1243 rep_hist_note_used_port(time(NULL), conn->base_.port);
1245 /* make an AP connection
1246 * populate it and add it at the right state
1247 * hook up both sides
1249 linked_conn =
1250 connection_ap_make_link(TO_CONN(conn),
1251 conn->base_.address, conn->base_.port,
1252 digest,
1253 SESSION_GROUP_DIRCONN, iso_flags,
1254 use_begindir, !anonymized_connection);
1255 if (!linked_conn) {
1256 log_warn(LD_NET,"Making tunnel to dirserver failed.");
1257 connection_mark_for_close(TO_CONN(conn));
1258 return;
1261 if (connection_add(TO_CONN(conn)) < 0) {
1262 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
1263 connection_mark_for_close(TO_CONN(conn));
1264 return;
1266 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
1267 /* queue the command on the outbuf */
1268 directory_send_command(conn, dir_purpose, 0, resource,
1269 payload, payload_len,
1270 if_modified_since);
1272 connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
1273 connection_start_reading(ENTRY_TO_CONN(linked_conn));
1277 /** Return true iff anything we say on <b>conn</b> is being encrypted before
1278 * we send it to the client/server. */
1280 connection_dir_is_encrypted(dir_connection_t *conn)
1282 /* Right now it's sufficient to see if conn is or has been linked, since
1283 * the only thing it could be linked to is an edge connection on a
1284 * circuit, and the only way it could have been unlinked is at the edge
1285 * connection getting closed.
1287 return TO_CONN(conn)->linked;
1290 /** Helper for sorting
1292 * sort strings alphabetically
1294 static int
1295 compare_strs_(const void **a, const void **b)
1297 const char *s1 = *a, *s2 = *b;
1298 return strcmp(s1, s2);
1301 #define CONDITIONAL_CONSENSUS_FPR_LEN 3
1302 #if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
1303 #error "conditional consensus fingerprint length is larger than digest length"
1304 #endif
1306 /** Return the URL we should use for a consensus download.
1308 * This url depends on whether or not the server we go to
1309 * is sufficiently new to support conditional consensus downloading,
1310 * i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
1312 * If 'resource' is provided, it is the name of a consensus flavor to request.
1314 static char *
1315 directory_get_consensus_url(const char *resource)
1317 char *url = NULL;
1318 const char *hyphen, *flavor;
1319 if (resource==NULL || strcmp(resource, "ns")==0) {
1320 flavor = ""; /* Request ns consensuses as "", so older servers will work*/
1321 hyphen = "";
1322 } else {
1323 flavor = resource;
1324 hyphen = "-";
1328 char *authority_id_list;
1329 smartlist_t *authority_digests = smartlist_new();
1331 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
1332 dir_server_t *, ds) {
1333 char *hex;
1334 if (!(ds->type & V3_DIRINFO))
1335 continue;
1337 hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
1338 base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
1339 ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN);
1340 smartlist_add(authority_digests, hex);
1341 } SMARTLIST_FOREACH_END(ds);
1342 smartlist_sort(authority_digests, compare_strs_);
1343 authority_id_list = smartlist_join_strings(authority_digests,
1344 "+", 0, NULL);
1346 tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s/%s.z",
1347 hyphen, flavor, authority_id_list);
1349 SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
1350 smartlist_free(authority_digests);
1351 tor_free(authority_id_list);
1353 return url;
1357 * Copies the ipv6 from source to destination, subject to buffer size limit
1358 * size. If decorate is true, makes sure the copied address is decorated.
1360 static void
1361 copy_ipv6_address(char* destination, const char* source, size_t len,
1362 int decorate) {
1363 tor_assert(destination);
1364 tor_assert(source);
1366 if (decorate && source[0] != '[') {
1367 tor_snprintf(destination, len, "[%s]", source);
1368 } else {
1369 strlcpy(destination, source, len);
1373 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
1374 * are as in directory_initiate_command().
1376 static void
1377 directory_send_command(dir_connection_t *conn,
1378 int purpose, int direct, const char *resource,
1379 const char *payload, size_t payload_len,
1380 time_t if_modified_since)
1382 char proxystring[256];
1383 char hoststring[128];
1384 /* NEEDS to be the same size hoststring.
1385 Will be decorated with brackets around it if it is ipv6. */
1386 char decorated_address[128];
1387 smartlist_t *headers = smartlist_new();
1388 char *url;
1389 char request[8192];
1390 const char *httpcommand = NULL;
1392 tor_assert(conn);
1393 tor_assert(conn->base_.type == CONN_TYPE_DIR);
1395 tor_free(conn->requested_resource);
1396 if (resource)
1397 conn->requested_resource = tor_strdup(resource);
1399 /* decorate the ip address if it is ipv6 */
1400 if (strchr(conn->base_.address, ':')) {
1401 copy_ipv6_address(decorated_address, conn->base_.address,
1402 sizeof(decorated_address), 1);
1403 } else {
1404 strlcpy(decorated_address, conn->base_.address, sizeof(decorated_address));
1407 /* come up with a string for which Host: we want */
1408 if (conn->base_.port == 80) {
1409 strlcpy(hoststring, decorated_address, sizeof(hoststring));
1410 } else {
1411 tor_snprintf(hoststring, sizeof(hoststring), "%s:%d",
1412 decorated_address, conn->base_.port);
1415 /* Format if-modified-since */
1416 if (if_modified_since) {
1417 char b[RFC1123_TIME_LEN+1];
1418 format_rfc1123_time(b, if_modified_since);
1419 smartlist_add_asprintf(headers, "If-Modified-Since: %s\r\n", b);
1422 /* come up with some proxy lines, if we're using one. */
1423 if (direct && get_options()->HTTPProxy) {
1424 char *base64_authenticator=NULL;
1425 const char *authenticator = get_options()->HTTPProxyAuthenticator;
1427 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
1428 if (authenticator) {
1429 base64_authenticator = alloc_http_authenticator(authenticator);
1430 if (!base64_authenticator)
1431 log_warn(LD_BUG, "Encoding http authenticator failed");
1433 if (base64_authenticator) {
1434 smartlist_add_asprintf(headers,
1435 "Proxy-Authorization: Basic %s\r\n",
1436 base64_authenticator);
1437 tor_free(base64_authenticator);
1439 } else {
1440 proxystring[0] = 0;
1443 switch (purpose) {
1444 case DIR_PURPOSE_FETCH_CONSENSUS:
1445 /* resource is optional. If present, it's a flavor name */
1446 tor_assert(!payload);
1447 httpcommand = "GET";
1448 url = directory_get_consensus_url(resource);
1449 log_info(LD_DIR, "Downloading consensus from %s using %s",
1450 hoststring, url);
1451 break;
1452 case DIR_PURPOSE_FETCH_CERTIFICATE:
1453 tor_assert(resource);
1454 tor_assert(!payload);
1455 httpcommand = "GET";
1456 tor_asprintf(&url, "/tor/keys/%s", resource);
1457 break;
1458 case DIR_PURPOSE_FETCH_STATUS_VOTE:
1459 tor_assert(resource);
1460 tor_assert(!payload);
1461 httpcommand = "GET";
1462 tor_asprintf(&url, "/tor/status-vote/next/%s.z", resource);
1463 break;
1464 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
1465 tor_assert(!resource);
1466 tor_assert(!payload);
1467 httpcommand = "GET";
1468 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
1469 break;
1470 case DIR_PURPOSE_FETCH_SERVERDESC:
1471 tor_assert(resource);
1472 httpcommand = "GET";
1473 tor_asprintf(&url, "/tor/server/%s", resource);
1474 break;
1475 case DIR_PURPOSE_FETCH_EXTRAINFO:
1476 tor_assert(resource);
1477 httpcommand = "GET";
1478 tor_asprintf(&url, "/tor/extra/%s", resource);
1479 break;
1480 case DIR_PURPOSE_FETCH_MICRODESC:
1481 tor_assert(resource);
1482 httpcommand = "GET";
1483 tor_asprintf(&url, "/tor/micro/%s", resource);
1484 break;
1485 case DIR_PURPOSE_UPLOAD_DIR: {
1486 const char *why = router_get_descriptor_gen_reason();
1487 tor_assert(!resource);
1488 tor_assert(payload);
1489 httpcommand = "POST";
1490 url = tor_strdup("/tor/");
1491 if (why) {
1492 smartlist_add_asprintf(headers, "X-Desc-Gen-Reason: %s\r\n", why);
1494 break;
1496 case DIR_PURPOSE_UPLOAD_VOTE:
1497 tor_assert(!resource);
1498 tor_assert(payload);
1499 httpcommand = "POST";
1500 url = tor_strdup("/tor/post/vote");
1501 break;
1502 case DIR_PURPOSE_UPLOAD_SIGNATURES:
1503 tor_assert(!resource);
1504 tor_assert(payload);
1505 httpcommand = "POST";
1506 url = tor_strdup("/tor/post/consensus-signature");
1507 break;
1508 case DIR_PURPOSE_FETCH_RENDDESC_V2:
1509 tor_assert(resource);
1510 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
1511 tor_assert(!payload);
1512 httpcommand = "GET";
1513 tor_asprintf(&url, "/tor/rendezvous2/%s", resource);
1514 break;
1515 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
1516 tor_assert(!resource);
1517 tor_assert(payload);
1518 httpcommand = "POST";
1519 url = tor_strdup("/tor/rendezvous2/publish");
1520 break;
1521 default:
1522 tor_assert(0);
1523 return;
1526 /* warn in the non-tunneled case */
1527 if (direct && (strlen(proxystring) + strlen(url) >= 4096)) {
1528 log_warn(LD_BUG,
1529 "Squid does not like URLs longer than 4095 bytes, and this "
1530 "one is %d bytes long: %s%s",
1531 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
1534 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
1535 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1536 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
1537 tor_free(url);
1539 if (!strcmp(httpcommand, "POST") || payload) {
1540 smartlist_add_asprintf(headers, "Content-Length: %lu\r\n",
1541 payload ? (unsigned long)payload_len : 0);
1545 char *header = smartlist_join_strings(headers, "", 0, NULL);
1546 tor_snprintf(request, sizeof(request), " HTTP/1.0\r\nHost: %s\r\n%s\r\n",
1547 hoststring, header);
1548 tor_free(header);
1551 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1553 if (payload) {
1554 /* then send the payload afterwards too */
1555 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
1558 SMARTLIST_FOREACH(headers, char *, h, tor_free(h));
1559 smartlist_free(headers);
1562 /** Parse an HTTP request string <b>headers</b> of the form
1563 * \verbatim
1564 * "\%s [http[s]://]\%s HTTP/1..."
1565 * \endverbatim
1566 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
1567 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
1568 * so it does. Return 0.
1569 * Otherwise, return -1.
1571 STATIC int
1572 parse_http_url(const char *headers, char **url)
1574 char *s, *start, *tmp;
1576 s = (char *)eat_whitespace_no_nl(headers);
1577 if (!*s) return -1;
1578 s = (char *)find_whitespace(s); /* get past GET/POST */
1579 if (!*s) return -1;
1580 s = (char *)eat_whitespace_no_nl(s);
1581 if (!*s) return -1;
1582 start = s; /* this is it, assuming it's valid */
1583 s = (char *)find_whitespace(start);
1584 if (!*s) return -1;
1586 /* tolerate the http[s] proxy style of putting the hostname in the url */
1587 if (s-start >= 4 && !strcmpstart(start,"http")) {
1588 tmp = start + 4;
1589 if (*tmp == 's')
1590 tmp++;
1591 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
1592 tmp = strchr(tmp+3, '/');
1593 if (tmp && tmp < s) {
1594 log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
1595 start = tmp;
1600 /* Check if the header is well formed (next sequence
1601 * should be HTTP/1.X\r\n). Assumes we're supporting 1.0? */
1603 unsigned minor_ver;
1604 char ch;
1605 char *e = (char *)eat_whitespace_no_nl(s);
1606 if (2 != tor_sscanf(e, "HTTP/1.%u%c", &minor_ver, &ch)) {
1607 return -1;
1609 if (ch != '\r')
1610 return -1;
1613 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
1614 *url = tor_malloc(s - start + 5);
1615 strlcpy(*url,"/tor", s-start+5);
1616 strlcat((*url)+4, start, s-start+1);
1617 } else {
1618 *url = tor_strndup(start, s-start);
1620 return 0;
1623 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1624 * <b>which</b>. The key should be given with a terminating colon and space;
1625 * this function copies everything after, up to but not including the
1626 * following \\r\\n. */
1627 static char *
1628 http_get_header(const char *headers, const char *which)
1630 const char *cp = headers;
1631 while (cp) {
1632 if (!strcasecmpstart(cp, which)) {
1633 char *eos;
1634 cp += strlen(which);
1635 if ((eos = strchr(cp,'\r')))
1636 return tor_strndup(cp, eos-cp);
1637 else
1638 return tor_strdup(cp);
1640 cp = strchr(cp, '\n');
1641 if (cp)
1642 ++cp;
1644 return NULL;
1647 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1648 * <b>conn</b>-\>address to describe our best guess of the address that
1649 * originated this HTTP request. */
1650 static void
1651 http_set_address_origin(const char *headers, connection_t *conn)
1653 char *fwd;
1655 fwd = http_get_header(headers, "Forwarded-For: ");
1656 if (!fwd)
1657 fwd = http_get_header(headers, "X-Forwarded-For: ");
1658 if (fwd) {
1659 tor_addr_t toraddr;
1660 if (tor_addr_parse(&toraddr,fwd) == -1 ||
1661 tor_addr_is_internal(&toraddr,0)) {
1662 log_debug(LD_DIR, "Ignoring local/internal IP %s", escaped(fwd));
1663 tor_free(fwd);
1664 return;
1667 tor_free(conn->address);
1668 conn->address = tor_strdup(fwd);
1669 tor_free(fwd);
1673 /** Parse an HTTP response string <b>headers</b> of the form
1674 * \verbatim
1675 * "HTTP/1.\%d \%d\%s\r\n...".
1676 * \endverbatim
1678 * If it's well-formed, assign the status code to *<b>code</b> and
1679 * return 0. Otherwise, return -1.
1681 * On success: If <b>date</b> is provided, set *date to the Date
1682 * header in the http headers, or 0 if no such header is found. If
1683 * <b>compression</b> is provided, set *<b>compression</b> to the
1684 * compression method given in the Content-Encoding header, or 0 if no
1685 * such header is found, or -1 if the value of the header is not
1686 * recognized. If <b>reason</b> is provided, strdup the reason string
1687 * into it.
1690 parse_http_response(const char *headers, int *code, time_t *date,
1691 compress_method_t *compression, char **reason)
1693 unsigned n1, n2;
1694 char datestr[RFC1123_TIME_LEN+1];
1695 smartlist_t *parsed_headers;
1696 tor_assert(headers);
1697 tor_assert(code);
1699 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1701 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
1702 (n1 != 0 && n1 != 1) ||
1703 (n2 < 100 || n2 >= 600)) {
1704 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1705 return -1;
1707 *code = n2;
1709 parsed_headers = smartlist_new();
1710 smartlist_split_string(parsed_headers, headers, "\n",
1711 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1712 if (reason) {
1713 smartlist_t *status_line_elements = smartlist_new();
1714 tor_assert(smartlist_len(parsed_headers));
1715 smartlist_split_string(status_line_elements,
1716 smartlist_get(parsed_headers, 0),
1717 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1718 tor_assert(smartlist_len(status_line_elements) <= 3);
1719 if (smartlist_len(status_line_elements) == 3) {
1720 *reason = smartlist_get(status_line_elements, 2);
1721 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1723 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1724 smartlist_free(status_line_elements);
1726 if (date) {
1727 *date = 0;
1728 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1729 if (!strcmpstart(s, "Date: ")) {
1730 strlcpy(datestr, s+6, sizeof(datestr));
1731 /* This will do nothing on failure, so we don't need to check
1732 the result. We shouldn't warn, since there are many other valid
1733 date formats besides the one we use. */
1734 parse_rfc1123_time(datestr, date);
1735 break;
1738 if (compression) {
1739 const char *enc = NULL;
1740 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1741 if (!strcmpstart(s, "Content-Encoding: ")) {
1742 enc = s+18; break;
1744 if (!enc || !strcmp(enc, "identity")) {
1745 *compression = NO_METHOD;
1746 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1747 *compression = ZLIB_METHOD;
1748 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1749 *compression = GZIP_METHOD;
1750 } else {
1751 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1752 escaped(enc));
1753 *compression = UNKNOWN_METHOD;
1756 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1757 smartlist_free(parsed_headers);
1759 return 0;
1762 /** Return true iff <b>body</b> doesn't start with a plausible router or
1763 * network-status or microdescriptor opening. This is a sign of possible
1764 * compression. */
1765 static int
1766 body_is_plausible(const char *body, size_t len, int purpose)
1768 int i;
1769 if (len == 0)
1770 return 1; /* empty bodies don't need decompression */
1771 if (len < 32)
1772 return 0;
1773 if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
1774 return (!strcmpstart(body,"onion-key"));
1776 if (1) {
1777 if (!strcmpstart(body,"router") ||
1778 !strcmpstart(body,"network-status"))
1779 return 1;
1780 for (i=0;i<32;++i) {
1781 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1782 return 0;
1785 return 1;
1788 /** Called when we've just fetched a bunch of router descriptors in
1789 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1790 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1791 * is true, or identity digests otherwise. Parse the descriptors, validate
1792 * them, and annotate them as having purpose <b>purpose</b> and as having been
1793 * downloaded from <b>source</b>.
1795 * Return the number of routers actually added. */
1796 static int
1797 load_downloaded_routers(const char *body, smartlist_t *which,
1798 int descriptor_digests,
1799 int router_purpose,
1800 const char *source)
1802 char buf[256];
1803 char time_buf[ISO_TIME_LEN+1];
1804 int added = 0;
1805 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1806 format_iso_time(time_buf, time(NULL));
1807 tor_assert(source);
1809 if (tor_snprintf(buf, sizeof(buf),
1810 "@downloaded-at %s\n"
1811 "@source %s\n"
1812 "%s%s%s", time_buf, escaped(source),
1813 !general ? "@purpose " : "",
1814 !general ? router_purpose_to_string(router_purpose) : "",
1815 !general ? "\n" : "")<0)
1816 return added;
1818 added = router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1819 descriptor_digests, buf);
1820 if (added && general)
1821 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
1822 count_loading_descriptors_progress());
1823 return added;
1826 /** We are a client, and we've finished reading the server's
1827 * response. Parse it and act appropriately.
1829 * If we're still happy with using this directory server in the future, return
1830 * 0. Otherwise return -1; and the caller should consider trying the request
1831 * again.
1833 * The caller will take care of marking the connection for close.
1835 static int
1836 connection_dir_client_reached_eof(dir_connection_t *conn)
1838 char *body;
1839 char *headers;
1840 char *reason = NULL;
1841 size_t body_len = 0;
1842 int status_code;
1843 time_t date_header = 0;
1844 long apparent_skew;
1845 compress_method_t compression;
1846 int plausible;
1847 int skewed = 0;
1848 int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1849 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
1850 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
1851 time_t now = time(NULL);
1852 int src_code;
1854 switch (connection_fetch_from_buf_http(TO_CONN(conn),
1855 &headers, MAX_HEADERS_SIZE,
1856 &body, &body_len, MAX_DIR_DL_SIZE,
1857 allow_partial)) {
1858 case -1: /* overflow */
1859 log_warn(LD_PROTOCOL,
1860 "'fetch' response too large (server '%s:%d'). Closing.",
1861 conn->base_.address, conn->base_.port);
1862 return -1;
1863 case 0:
1864 log_info(LD_HTTP,
1865 "'fetch' response not all here, but we're at eof. Closing.");
1866 return -1;
1867 /* case 1, fall through */
1870 if (parse_http_response(headers, &status_code, &date_header,
1871 &compression, &reason) < 0) {
1872 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1873 conn->base_.address, conn->base_.port);
1874 tor_free(body); tor_free(headers);
1875 return -1;
1877 if (!reason) reason = tor_strdup("[no reason given]");
1879 log_debug(LD_DIR,
1880 "Received response from directory server '%s:%d': %d %s "
1881 "(purpose: %d)",
1882 conn->base_.address, conn->base_.port, status_code,
1883 escaped(reason),
1884 conn->base_.purpose);
1886 /* now check if it's got any hints for us about our IP address. */
1887 if (conn->dirconn_direct) {
1888 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1889 if (guess) {
1890 router_new_address_suggestion(guess, conn);
1891 tor_free(guess);
1895 if (date_header > 0) {
1896 /* The date header was written very soon after we sent our request,
1897 * so compute the skew as the difference between sending the request
1898 * and the date header. (We used to check now-date_header, but that's
1899 * inaccurate if we spend a lot of time downloading.)
1901 apparent_skew = conn->base_.timestamp_lastwritten - date_header;
1902 if (labs(apparent_skew)>ALLOW_DIRECTORY_TIME_SKEW) {
1903 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1904 clock_skew_warning(TO_CONN(conn), apparent_skew, trusted, LD_HTTP,
1905 "directory", "DIRSERV");
1906 skewed = 1; /* don't check the recommended-versions line */
1907 } else {
1908 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1909 "we are %ld seconds skewed. (That's okay.)", apparent_skew);
1912 (void) skewed; /* skewed isn't used yet. */
1914 if (status_code == 503) {
1915 routerstatus_t *rs;
1916 dir_server_t *ds;
1917 const char *id_digest = conn->identity_digest;
1918 log_info(LD_DIR,"Received http status code %d (%s) from server "
1919 "'%s:%d'. I'll try again soon.",
1920 status_code, escaped(reason), conn->base_.address,
1921 conn->base_.port);
1922 if ((rs = router_get_mutable_consensus_status_by_id(id_digest)))
1923 rs->last_dir_503_at = now;
1924 if ((ds = router_get_fallback_dirserver_by_digest(id_digest)))
1925 ds->fake_status.last_dir_503_at = now;
1927 tor_free(body); tor_free(headers); tor_free(reason);
1928 return -1;
1931 plausible = body_is_plausible(body, body_len, conn->base_.purpose);
1932 if (compression != NO_METHOD || !plausible) {
1933 char *new_body = NULL;
1934 size_t new_len = 0;
1935 compress_method_t guessed = detect_compression_method(body, body_len);
1936 if (compression == UNKNOWN_METHOD || guessed != compression) {
1937 /* Tell the user if we don't believe what we're told about compression.*/
1938 const char *description1, *description2;
1939 if (compression == ZLIB_METHOD)
1940 description1 = "as deflated";
1941 else if (compression == GZIP_METHOD)
1942 description1 = "as gzipped";
1943 else if (compression == NO_METHOD)
1944 description1 = "as uncompressed";
1945 else
1946 description1 = "with an unknown Content-Encoding";
1947 if (guessed == ZLIB_METHOD)
1948 description2 = "deflated";
1949 else if (guessed == GZIP_METHOD)
1950 description2 = "gzipped";
1951 else if (!plausible)
1952 description2 = "confusing binary junk";
1953 else
1954 description2 = "uncompressed";
1956 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1957 "but it seems to be %s.%s",
1958 conn->base_.address, conn->base_.port, description1,
1959 description2,
1960 (compression>0 && guessed>0)?" Trying both.":"");
1962 /* Try declared compression first if we can. */
1963 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1964 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1965 !allow_partial, LOG_PROTOCOL_WARN);
1966 /* Okay, if that didn't work, and we think that it was compressed
1967 * differently, try that. */
1968 if (!new_body &&
1969 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1970 compression != guessed)
1971 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1972 !allow_partial, LOG_PROTOCOL_WARN);
1973 /* If we're pretty sure that we have a compressed directory, and
1974 * we didn't manage to uncompress it, then warn and bail. */
1975 if (!plausible && !new_body) {
1976 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1977 "Unable to decompress HTTP body (server '%s:%d').",
1978 conn->base_.address, conn->base_.port);
1979 tor_free(body); tor_free(headers); tor_free(reason);
1980 return -1;
1982 if (new_body) {
1983 tor_free(body);
1984 body = new_body;
1985 body_len = new_len;
1989 if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1990 int r;
1991 const char *flavname = conn->requested_resource;
1992 if (status_code != 200) {
1993 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1994 tor_log(severity, LD_DIR,
1995 "Received http status code %d (%s) from server "
1996 "'%s:%d' while fetching consensus directory.",
1997 status_code, escaped(reason), conn->base_.address,
1998 conn->base_.port);
1999 tor_free(body); tor_free(headers); tor_free(reason);
2000 networkstatus_consensus_download_failed(status_code, flavname);
2001 return -1;
2003 log_info(LD_DIR,"Received consensus directory (size %d) from server "
2004 "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
2005 if ((r=networkstatus_set_current_consensus(body, flavname, 0,
2006 conn->identity_digest))<0) {
2007 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
2008 "Unable to load %s consensus directory downloaded from "
2009 "server '%s:%d'. I'll try again soon.",
2010 flavname, conn->base_.address, conn->base_.port);
2011 tor_free(body); tor_free(headers); tor_free(reason);
2012 networkstatus_consensus_download_failed(0, flavname);
2013 return -1;
2016 /* If we launched other fetches for this consensus, cancel them. */
2017 connection_dir_close_consensus_fetches(conn, flavname);
2019 /* launches router downloads as needed */
2020 routers_update_all_from_networkstatus(now, 3);
2021 update_microdescs_from_networkstatus(now);
2022 update_microdesc_downloads(now);
2023 directory_info_has_arrived(now, 0, 0);
2024 if (authdir_mode_v3(get_options())) {
2025 sr_act_post_consensus(
2026 networkstatus_get_latest_consensus_by_flavor(FLAV_NS));
2028 log_info(LD_DIR, "Successfully loaded consensus.");
2031 if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
2032 if (status_code != 200) {
2033 log_warn(LD_DIR,
2034 "Received http status code %d (%s) from server "
2035 "'%s:%d' while fetching \"/tor/keys/%s\".",
2036 status_code, escaped(reason), conn->base_.address,
2037 conn->base_.port, conn->requested_resource);
2038 connection_dir_download_cert_failed(conn, status_code);
2039 tor_free(body); tor_free(headers); tor_free(reason);
2040 return -1;
2042 log_info(LD_DIR,"Received authority certificates (size %d) from server "
2043 "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
2046 * Tell trusted_dirs_load_certs_from_string() whether it was by fp
2047 * or fp-sk pair.
2049 src_code = -1;
2050 if (!strcmpstart(conn->requested_resource, "fp/")) {
2051 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST;
2052 } else if (!strcmpstart(conn->requested_resource, "fp-sk/")) {
2053 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST;
2056 if (src_code != -1) {
2057 if (trusted_dirs_load_certs_from_string(body, src_code, 1,
2058 conn->identity_digest)<0) {
2059 log_warn(LD_DIR, "Unable to parse fetched certificates");
2060 /* if we fetched more than one and only some failed, the successful
2061 * ones got flushed to disk so it's safe to call this on them */
2062 connection_dir_download_cert_failed(conn, status_code);
2063 } else {
2064 directory_info_has_arrived(now, 0, 0);
2065 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
2067 } else {
2068 log_warn(LD_DIR,
2069 "Couldn't figure out what to do with fetched certificates for "
2070 "unknown resource %s",
2071 conn->requested_resource);
2072 connection_dir_download_cert_failed(conn, status_code);
2075 if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
2076 const char *msg;
2077 int st;
2078 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
2079 (int)body_len, conn->base_.address, conn->base_.port);
2080 if (status_code != 200) {
2081 log_warn(LD_DIR,
2082 "Received http status code %d (%s) from server "
2083 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
2084 status_code, escaped(reason), conn->base_.address,
2085 conn->base_.port, conn->requested_resource);
2086 tor_free(body); tor_free(headers); tor_free(reason);
2087 return -1;
2089 dirvote_add_vote(body, &msg, &st);
2090 if (st > 299) {
2091 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
2092 } else {
2093 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
2096 if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
2097 const char *msg = NULL;
2098 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
2099 (int)body_len, conn->base_.address, conn->base_.port);
2100 if (status_code != 200) {
2101 log_warn(LD_DIR,
2102 "Received http status code %d (%s) from server '%s:%d' while fetching "
2103 "\"/tor/status-vote/next/consensus-signatures.z\".",
2104 status_code, escaped(reason), conn->base_.address,
2105 conn->base_.port);
2106 tor_free(body); tor_free(headers); tor_free(reason);
2107 return -1;
2109 if (dirvote_add_signatures(body, conn->base_.address, &msg)<0) {
2110 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
2111 conn->base_.address, conn->base_.port, msg?msg:"???");
2115 if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
2116 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
2117 int was_ei = conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
2118 smartlist_t *which = NULL;
2119 int n_asked_for = 0;
2120 int descriptor_digests = conn->requested_resource &&
2121 !strcmpstart(conn->requested_resource,"d/");
2122 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
2123 was_ei ? "extra server info" : "server info",
2124 (int)body_len, conn->base_.address, conn->base_.port);
2125 if (conn->requested_resource &&
2126 (!strcmpstart(conn->requested_resource,"d/") ||
2127 !strcmpstart(conn->requested_resource,"fp/"))) {
2128 which = smartlist_new();
2129 dir_split_resource_into_fingerprints(conn->requested_resource +
2130 (descriptor_digests ? 2 : 3),
2131 which, NULL, 0);
2132 n_asked_for = smartlist_len(which);
2134 if (status_code != 200) {
2135 int dir_okay = status_code == 404 ||
2136 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
2137 /* 404 means that it didn't have them; no big deal.
2138 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
2139 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
2140 "Received http status code %d (%s) from server '%s:%d' "
2141 "while fetching \"/tor/server/%s\". I'll try again soon.",
2142 status_code, escaped(reason), conn->base_.address,
2143 conn->base_.port, conn->requested_resource);
2144 if (!which) {
2145 connection_dir_download_routerdesc_failed(conn);
2146 } else {
2147 dir_routerdesc_download_failed(which, status_code,
2148 conn->router_purpose,
2149 was_ei, descriptor_digests);
2150 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2151 smartlist_free(which);
2153 tor_free(body); tor_free(headers); tor_free(reason);
2154 return dir_okay ? 0 : -1;
2156 /* Learn the routers, assuming we requested by fingerprint or "all"
2157 * or "authority".
2159 * We use "authority" to fetch our own descriptor for
2160 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
2161 * the output of "authority" requests unless we are using bridges,
2162 * since otherwise they'll be the response from reachability tests,
2163 * and we don't really want to add that to our routerlist. */
2164 if (which || (conn->requested_resource &&
2165 (!strcmpstart(conn->requested_resource, "all") ||
2166 (!strcmpstart(conn->requested_resource, "authority") &&
2167 get_options()->UseBridges)))) {
2168 /* as we learn from them, we remove them from 'which' */
2169 if (was_ei) {
2170 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
2171 descriptor_digests);
2172 } else {
2173 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
2174 // descriptor_digests, conn->router_purpose);
2175 if (load_downloaded_routers(body, which, descriptor_digests,
2176 conn->router_purpose,
2177 conn->base_.address))
2178 directory_info_has_arrived(now, 0, 0);
2181 if (which) { /* mark remaining ones as failed */
2182 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
2183 n_asked_for-smartlist_len(which), n_asked_for,
2184 was_ei ? "extra-info documents" : "router descriptors",
2185 conn->base_.address, (int)conn->base_.port);
2186 if (smartlist_len(which)) {
2187 dir_routerdesc_download_failed(which, status_code,
2188 conn->router_purpose,
2189 was_ei, descriptor_digests);
2191 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2192 smartlist_free(which);
2194 if (directory_conn_is_self_reachability_test(conn))
2195 router_dirport_found_reachable();
2197 if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
2198 smartlist_t *which = NULL;
2199 log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
2200 "size %d) from server '%s:%d'",
2201 status_code, (int)body_len, conn->base_.address,
2202 conn->base_.port);
2203 tor_assert(conn->requested_resource &&
2204 !strcmpstart(conn->requested_resource, "d/"));
2205 which = smartlist_new();
2206 dir_split_resource_into_fingerprints(conn->requested_resource+2,
2207 which, NULL,
2208 DSR_DIGEST256|DSR_BASE64);
2209 if (status_code != 200) {
2210 log_info(LD_DIR, "Received status code %d (%s) from server "
2211 "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again "
2212 "soon.",
2213 status_code, escaped(reason), conn->base_.address,
2214 (int)conn->base_.port, conn->requested_resource);
2215 dir_microdesc_download_failed(which, status_code);
2216 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2217 smartlist_free(which);
2218 tor_free(body); tor_free(headers); tor_free(reason);
2219 return 0;
2220 } else {
2221 smartlist_t *mds;
2222 mds = microdescs_add_to_cache(get_microdesc_cache(),
2223 body, body+body_len, SAVED_NOWHERE, 0,
2224 now, which);
2225 if (smartlist_len(which)) {
2226 /* Mark remaining ones as failed. */
2227 dir_microdesc_download_failed(which, status_code);
2229 if (mds && smartlist_len(mds)) {
2230 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
2231 count_loading_descriptors_progress());
2232 directory_info_has_arrived(now, 0, 1);
2234 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2235 smartlist_free(which);
2236 smartlist_free(mds);
2240 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_DIR) {
2241 switch (status_code) {
2242 case 200: {
2243 dir_server_t *ds =
2244 router_get_trusteddirserver_by_digest(conn->identity_digest);
2245 char *rejected_hdr = http_get_header(headers,
2246 "X-Descriptor-Not-New: ");
2247 if (rejected_hdr) {
2248 if (!strcmp(rejected_hdr, "Yes")) {
2249 log_info(LD_GENERAL,
2250 "Authority '%s' declined our descriptor (not new)",
2251 ds->nickname);
2252 /* XXXX use this information; be sure to upload next one
2253 * sooner. -NM */
2254 /* XXXX++ On further thought, the task above implies that we're
2255 * basing our regenerate-descriptor time on when we uploaded the
2256 * last descriptor, not on the published time of the last
2257 * descriptor. If those are different, that's a bad thing to
2258 * do. -NM */
2260 tor_free(rejected_hdr);
2262 log_info(LD_GENERAL,"eof (status 200) after uploading server "
2263 "descriptor: finished.");
2264 control_event_server_status(
2265 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
2266 conn->base_.address, conn->base_.port);
2268 ds->has_accepted_serverdesc = 1;
2269 if (directories_have_accepted_server_descriptor())
2270 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
2272 break;
2273 case 400:
2274 log_warn(LD_GENERAL,"http status 400 (%s) response from "
2275 "dirserver '%s:%d'. Please correct.",
2276 escaped(reason), conn->base_.address, conn->base_.port);
2277 control_event_server_status(LOG_WARN,
2278 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
2279 conn->base_.address, conn->base_.port, escaped(reason));
2280 break;
2281 default:
2282 log_warn(LD_GENERAL,
2283 "http status %d (%s) reason unexpected while uploading "
2284 "descriptor to server '%s:%d').",
2285 status_code, escaped(reason), conn->base_.address,
2286 conn->base_.port);
2287 break;
2289 /* return 0 in all cases, since we don't want to mark any
2290 * dirservers down just because they don't like us. */
2293 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
2294 switch (status_code) {
2295 case 200: {
2296 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
2297 conn->base_.address, conn->base_.port);
2299 break;
2300 case 400:
2301 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
2302 "vote to dirserver '%s:%d'. Please correct.",
2303 escaped(reason), conn->base_.address, conn->base_.port);
2304 break;
2305 default:
2306 log_warn(LD_GENERAL,
2307 "http status %d (%s) reason unexpected while uploading "
2308 "vote to server '%s:%d').",
2309 status_code, escaped(reason), conn->base_.address,
2310 conn->base_.port);
2311 break;
2313 /* return 0 in all cases, since we don't want to mark any
2314 * dirservers down just because they don't like us. */
2317 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
2318 switch (status_code) {
2319 case 200: {
2320 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
2321 conn->base_.address, conn->base_.port);
2323 break;
2324 case 400:
2325 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
2326 "signatures to dirserver '%s:%d'. Please correct.",
2327 escaped(reason), conn->base_.address, conn->base_.port);
2328 break;
2329 default:
2330 log_warn(LD_GENERAL,
2331 "http status %d (%s) reason unexpected while uploading "
2332 "signatures to server '%s:%d').",
2333 status_code, escaped(reason), conn->base_.address,
2334 conn->base_.port);
2335 break;
2337 /* return 0 in all cases, since we don't want to mark any
2338 * dirservers down just because they don't like us. */
2341 if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
2342 #define SEND_HS_DESC_FAILED_EVENT(reason) ( \
2343 control_event_hs_descriptor_failed(conn->rend_data, \
2344 conn->identity_digest, \
2345 reason) )
2346 #define SEND_HS_DESC_FAILED_CONTENT() ( \
2347 control_event_hs_descriptor_content(conn->rend_data->onion_address, \
2348 conn->requested_resource, \
2349 conn->identity_digest, \
2350 NULL) )
2351 tor_assert(conn->rend_data);
2352 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
2353 "(%s))",
2354 (int)body_len, status_code, escaped(reason));
2355 switch (status_code) {
2356 case 200:
2358 rend_cache_entry_t *entry = NULL;
2360 if (rend_cache_store_v2_desc_as_client(body,
2361 conn->requested_resource, conn->rend_data, &entry) < 0) {
2362 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
2363 "Retrying at another directory.");
2364 /* We'll retry when connection_about_to_close_connection()
2365 * cleans this dir conn up. */
2366 SEND_HS_DESC_FAILED_EVENT("BAD_DESC");
2367 SEND_HS_DESC_FAILED_CONTENT();
2368 } else {
2369 char service_id[REND_SERVICE_ID_LEN_BASE32 + 1];
2370 /* Should never be NULL here if we found the descriptor. */
2371 tor_assert(entry);
2372 rend_get_service_id(entry->parsed->pk, service_id);
2374 /* success. notify pending connections about this. */
2375 log_info(LD_REND, "Successfully fetched v2 rendezvous "
2376 "descriptor.");
2377 control_event_hs_descriptor_received(service_id,
2378 conn->rend_data,
2379 conn->identity_digest);
2380 control_event_hs_descriptor_content(service_id,
2381 conn->requested_resource,
2382 conn->identity_digest,
2383 body);
2384 conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
2385 rend_client_desc_trynow(service_id);
2386 memwipe(service_id, 0, sizeof(service_id));
2388 break;
2390 case 404:
2391 /* Not there. We'll retry when
2392 * connection_about_to_close_connection() cleans this conn up. */
2393 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
2394 "Retrying at another directory.");
2395 SEND_HS_DESC_FAILED_EVENT("NOT_FOUND");
2396 SEND_HS_DESC_FAILED_CONTENT();
2397 break;
2398 case 400:
2399 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
2400 "http status 400 (%s). Dirserver didn't like our "
2401 "v2 rendezvous query? Retrying at another directory.",
2402 escaped(reason));
2403 SEND_HS_DESC_FAILED_EVENT("QUERY_REJECTED");
2404 SEND_HS_DESC_FAILED_CONTENT();
2405 break;
2406 default:
2407 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
2408 "http status %d (%s) response unexpected while "
2409 "fetching v2 hidden service descriptor (server '%s:%d'). "
2410 "Retrying at another directory.",
2411 status_code, escaped(reason), conn->base_.address,
2412 conn->base_.port);
2413 SEND_HS_DESC_FAILED_EVENT("UNEXPECTED");
2414 SEND_HS_DESC_FAILED_CONTENT();
2415 break;
2419 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
2420 #define SEND_HS_DESC_UPLOAD_FAILED_EVENT(reason) ( \
2421 control_event_hs_descriptor_upload_failed( \
2422 conn->identity_digest, \
2423 conn->rend_data->onion_address, \
2424 reason) )
2425 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
2426 "(%s))",
2427 status_code, escaped(reason));
2428 /* Without the rend data, we'll have a problem identifying what has been
2429 * uploaded for which service. */
2430 tor_assert(conn->rend_data);
2431 switch (status_code) {
2432 case 200:
2433 log_info(LD_REND,
2434 "Uploading rendezvous descriptor: finished with status "
2435 "200 (%s)", escaped(reason));
2436 control_event_hs_descriptor_uploaded(conn->identity_digest,
2437 conn->rend_data->onion_address);
2438 rend_service_desc_has_uploaded(conn->rend_data);
2439 break;
2440 case 400:
2441 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
2442 "'%s:%d'. Malformed rendezvous descriptor?",
2443 escaped(reason), conn->base_.address, conn->base_.port);
2444 SEND_HS_DESC_UPLOAD_FAILED_EVENT("UPLOAD_REJECTED");
2445 break;
2446 default:
2447 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
2448 "'%s:%d').",
2449 status_code, escaped(reason), conn->base_.address,
2450 conn->base_.port);
2451 SEND_HS_DESC_UPLOAD_FAILED_EVENT("UNEXPECTED");
2452 break;
2455 tor_free(body); tor_free(headers); tor_free(reason);
2456 return 0;
2459 /** Called when a directory connection reaches EOF. */
2461 connection_dir_reached_eof(dir_connection_t *conn)
2463 int retval;
2464 if (conn->base_.state != DIR_CONN_STATE_CLIENT_READING) {
2465 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
2466 conn->base_.state);
2467 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
2468 connection_mark_for_close(TO_CONN(conn));
2469 return -1;
2472 retval = connection_dir_client_reached_eof(conn);
2473 if (retval == 0) /* success */
2474 conn->base_.state = DIR_CONN_STATE_CLIENT_FINISHED;
2475 connection_mark_for_close(TO_CONN(conn));
2476 return retval;
2479 /** If any directory object is arriving, and it's over 10MB large, we're
2480 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
2481 * ask for more than 96 router descriptors at a time.)
2483 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
2485 #define MAX_VOTE_DL_SIZE (MAX_DIRECTORY_OBJECT_SIZE * 5)
2487 /** Read handler for directory connections. (That's connections <em>to</em>
2488 * directory servers and connections <em>at</em> directory servers.)
2491 connection_dir_process_inbuf(dir_connection_t *conn)
2493 size_t max_size;
2494 tor_assert(conn);
2495 tor_assert(conn->base_.type == CONN_TYPE_DIR);
2497 /* Directory clients write, then read data until they receive EOF;
2498 * directory servers read data until they get an HTTP command, then
2499 * write their response (when it's finished flushing, they mark for
2500 * close).
2503 /* If we're on the dirserver side, look for a command. */
2504 if (conn->base_.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
2505 if (directory_handle_command(conn) < 0) {
2506 connection_mark_for_close(TO_CONN(conn));
2507 return -1;
2509 return 0;
2512 max_size =
2513 (TO_CONN(conn)->purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) ?
2514 MAX_VOTE_DL_SIZE : MAX_DIRECTORY_OBJECT_SIZE;
2516 if (connection_get_inbuf_len(TO_CONN(conn)) > max_size) {
2517 log_warn(LD_HTTP,
2518 "Too much data received from directory connection (%s): "
2519 "denial of service attempt, or you need to upgrade?",
2520 conn->base_.address);
2521 connection_mark_for_close(TO_CONN(conn));
2522 return -1;
2525 if (!conn->base_.inbuf_reached_eof)
2526 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
2527 return 0;
2530 /** Called when we're about to finally unlink and free a directory connection:
2531 * perform necessary accounting and cleanup */
2532 void
2533 connection_dir_about_to_close(dir_connection_t *dir_conn)
2535 connection_t *conn = TO_CONN(dir_conn);
2537 if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
2538 /* It's a directory connection and connecting or fetching
2539 * failed: forget about this router, and maybe try again. */
2540 connection_dir_request_failed(dir_conn);
2542 /* If we were trying to fetch a v2 rend desc and did not succeed,
2543 * retry as needed. (If a fetch is successful, the connection state
2544 * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 to mark that
2545 * refetching is unnecessary.) */
2546 if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
2547 dir_conn->rend_data &&
2548 strlen(dir_conn->rend_data->onion_address) == REND_SERVICE_ID_LEN_BASE32)
2549 rend_client_refetch_v2_renddesc(dir_conn->rend_data);
2552 /** Create an http response for the client <b>conn</b> out of
2553 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
2555 static void
2556 write_http_status_line(dir_connection_t *conn, int status,
2557 const char *reason_phrase)
2559 char buf[256];
2560 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
2561 status, reason_phrase ? reason_phrase : "OK") < 0) {
2562 log_warn(LD_BUG,"status line too long.");
2563 return;
2565 log_debug(LD_DIRSERV,"Wrote status 'HTTP/1.0 %d %s'", status, reason_phrase);
2566 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
2569 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
2570 * with <b>type</b> as the Content-Type.
2572 * If <b>length</b> is nonnegative, it is the Content-Length.
2573 * If <b>encoding</b> is provided, it is the Content-Encoding.
2574 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
2575 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
2576 static void
2577 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
2578 const char *type, const char *encoding,
2579 const char *extra_headers,
2580 long cache_lifetime)
2582 char date[RFC1123_TIME_LEN+1];
2583 char tmp[1024];
2584 char *cp;
2585 time_t now = time(NULL);
2587 tor_assert(conn);
2589 format_rfc1123_time(date, now);
2590 cp = tmp;
2591 tor_snprintf(cp, sizeof(tmp),
2592 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
2593 date);
2594 cp += strlen(tmp);
2595 if (type) {
2596 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
2597 cp += strlen(cp);
2599 if (!is_local_addr(&conn->base_.addr)) {
2600 /* Don't report the source address for a nearby/private connection.
2601 * Otherwise we tend to mis-report in cases where incoming ports are
2602 * being forwarded to a Tor server running behind the firewall. */
2603 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2604 X_ADDRESS_HEADER "%s\r\n", conn->base_.address);
2605 cp += strlen(cp);
2607 if (encoding) {
2608 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2609 "Content-Encoding: %s\r\n", encoding);
2610 cp += strlen(cp);
2612 if (length >= 0) {
2613 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2614 "Content-Length: %ld\r\n", (long)length);
2615 cp += strlen(cp);
2617 if (cache_lifetime > 0) {
2618 char expbuf[RFC1123_TIME_LEN+1];
2619 format_rfc1123_time(expbuf, (time_t)(now + cache_lifetime));
2620 /* We could say 'Cache-control: max-age=%d' here if we start doing
2621 * http/1.1 */
2622 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2623 "Expires: %s\r\n", expbuf);
2624 cp += strlen(cp);
2625 } else if (cache_lifetime == 0) {
2626 /* We could say 'Cache-control: no-cache' here if we start doing
2627 * http/1.1 */
2628 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2629 cp += strlen(cp);
2631 if (extra_headers) {
2632 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2633 cp += strlen(cp);
2635 if (sizeof(tmp)-(cp-tmp) > 3)
2636 memcpy(cp, "\r\n", 3);
2637 else
2638 tor_assert(0);
2639 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2642 /** As write_http_response_header_impl, but sets encoding and content-typed
2643 * based on whether the response will be <b>compressed</b> or not. */
2644 static void
2645 write_http_response_header(dir_connection_t *conn, ssize_t length,
2646 int compressed, long cache_lifetime)
2648 write_http_response_header_impl(conn, length,
2649 compressed?"application/octet-stream":"text/plain",
2650 compressed?"deflate":"identity",
2651 NULL,
2652 cache_lifetime);
2655 /** Decide whether a client would accept the consensus we have.
2657 * Clients can say they only want a consensus if it's signed by more
2658 * than half the authorities in a list. They pass this list in
2659 * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
2661 * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
2662 * of the full authority identity digest. (Only strings of even length,
2663 * i.e. encodings of full bytes, are handled correctly. In the case
2664 * of an odd number of hex digits the last one is silently ignored.)
2666 * Returns 1 if more than half of the requested authorities signed the
2667 * consensus, 0 otherwise.
2670 client_likes_consensus(networkstatus_t *v, const char *want_url)
2672 smartlist_t *want_authorities = smartlist_new();
2673 int need_at_least;
2674 int have = 0;
2676 dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0);
2677 need_at_least = smartlist_len(want_authorities)/2+1;
2678 SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, d) {
2679 char want_digest[DIGEST_LEN];
2680 size_t want_len = strlen(d)/2;
2681 if (want_len > DIGEST_LEN)
2682 want_len = DIGEST_LEN;
2684 if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2)
2685 != (int) want_len) {
2686 log_fn(LOG_PROTOCOL_WARN, LD_DIR,
2687 "Failed to decode requested authority digest %s.", escaped(d));
2688 continue;
2691 SMARTLIST_FOREACH_BEGIN(v->voters, networkstatus_voter_info_t *, vi) {
2692 if (smartlist_len(vi->sigs) &&
2693 tor_memeq(vi->identity_digest, want_digest, want_len)) {
2694 have++;
2695 break;
2697 } SMARTLIST_FOREACH_END(vi);
2699 /* early exit, if we already have enough */
2700 if (have >= need_at_least)
2701 break;
2702 } SMARTLIST_FOREACH_END(d);
2704 SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
2705 smartlist_free(want_authorities);
2706 return (have >= need_at_least);
2709 /** Return the compression level we should use for sending a compressed
2710 * response of size <b>n_bytes</b>. */
2711 STATIC zlib_compression_level_t
2712 choose_compression_level(ssize_t n_bytes)
2714 if (! have_been_under_memory_pressure()) {
2715 return HIGH_COMPRESSION; /* we have plenty of RAM. */
2716 } else if (n_bytes < 0) {
2717 return HIGH_COMPRESSION; /* unknown; might be big. */
2718 } else if (n_bytes < 1024) {
2719 return LOW_COMPRESSION;
2720 } else if (n_bytes < 2048) {
2721 return MEDIUM_COMPRESSION;
2722 } else {
2723 return HIGH_COMPRESSION;
2727 /** Information passed to handle a GET request. */
2728 typedef struct get_handler_args_t {
2729 /** True if the client asked for compressed data. */
2730 int compressed;
2731 /** If nonzero, the time included an if-modified-since header with this
2732 * value. */
2733 time_t if_modified_since;
2734 /** String containing the requested URL or resource. */
2735 const char *url;
2736 /** String containing the HTTP headers */
2737 const char *headers;
2738 } get_handler_args_t;
2740 /** Entry for handling an HTTP GET request.
2742 * This entry matches a request if "string" is equal to the requested
2743 * resource, or if "is_prefix" is true and "string" is a prefix of the
2744 * requested resource.
2746 * The 'handler' function is called to handle the request. It receives
2747 * an arguments structure, and must return 0 on success or -1 if we should
2748 * close the connection.
2750 typedef struct url_table_ent_s {
2751 const char *string;
2752 int is_prefix;
2753 int (*handler)(dir_connection_t *conn, const get_handler_args_t *args);
2754 } url_table_ent_t;
2756 static int handle_get_frontpage(dir_connection_t *conn,
2757 const get_handler_args_t *args);
2758 static int handle_get_current_consensus(dir_connection_t *conn,
2759 const get_handler_args_t *args);
2760 static int handle_get_status_vote(dir_connection_t *conn,
2761 const get_handler_args_t *args);
2762 static int handle_get_microdesc(dir_connection_t *conn,
2763 const get_handler_args_t *args);
2764 static int handle_get_descriptor(dir_connection_t *conn,
2765 const get_handler_args_t *args);
2766 static int handle_get_keys(dir_connection_t *conn,
2767 const get_handler_args_t *args);
2768 static int handle_get_rendezvous2(dir_connection_t *conn,
2769 const get_handler_args_t *args);
2770 static int handle_get_robots(dir_connection_t *conn,
2771 const get_handler_args_t *args);
2772 static int handle_get_networkstatus_bridges(dir_connection_t *conn,
2773 const get_handler_args_t *args);
2775 /** Table for handling GET requests. */
2776 static const url_table_ent_t url_table[] = {
2777 { "/tor/", 0, handle_get_frontpage },
2778 { "/tor/status-vote/current/consensus", 1, handle_get_current_consensus },
2779 { "/tor/status-vote/current/", 1, handle_get_status_vote },
2780 { "/tor/status-vote/next/", 1, handle_get_status_vote },
2781 { "/tor/micro/d/", 1, handle_get_microdesc },
2782 { "/tor/server/", 1, handle_get_descriptor },
2783 { "/tor/extra/", 1, handle_get_descriptor },
2784 { "/tor/keys/", 1, handle_get_keys },
2785 { "/tor/rendezvous2/", 1, handle_get_rendezvous2 },
2786 { "/tor/robots.txt", 0, handle_get_robots },
2787 { "/tor/networkstatus-bridges", 0, handle_get_networkstatus_bridges },
2788 { NULL, 0, NULL },
2791 /** Helper function: called when a dirserver gets a complete HTTP GET
2792 * request. Look for a request for a directory or for a rendezvous
2793 * service descriptor. On finding one, write a response into
2794 * conn-\>outbuf. If the request is unrecognized, send a 404.
2795 * Return 0 if we handled this successfully, or -1 if we need to close
2796 * the connection. */
2797 STATIC int
2798 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2799 const char *req_body, size_t req_body_len)
2801 char *url, *url_mem, *header;
2802 time_t if_modified_since = 0;
2803 int compressed;
2804 size_t url_len;
2806 /* We ignore the body of a GET request. */
2807 (void)req_body;
2808 (void)req_body_len;
2810 log_debug(LD_DIRSERV,"Received GET command.");
2812 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
2814 if (parse_http_url(headers, &url) < 0) {
2815 write_http_status_line(conn, 400, "Bad request");
2816 return 0;
2818 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2819 struct tm tm;
2820 if (parse_http_time(header, &tm) == 0) {
2821 if (tor_timegm(&tm, &if_modified_since)<0) {
2822 if_modified_since = 0;
2823 } else {
2824 log_debug(LD_DIRSERV, "If-Modified-Since is '%s'.", escaped(header));
2827 /* The correct behavior on a malformed If-Modified-Since header is to
2828 * act as if no If-Modified-Since header had been given. */
2829 tor_free(header);
2831 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
2833 url_mem = url;
2834 url_len = strlen(url);
2835 compressed = url_len > 2 && !strcmp(url+url_len-2, ".z");
2836 if (compressed) {
2837 url[url_len-2] = '\0';
2838 url_len -= 2;
2841 get_handler_args_t args;
2842 args.url = url;
2843 args.headers = headers;
2844 args.if_modified_since = if_modified_since;
2845 args.compressed = compressed;
2847 int i, result = -1;
2848 for (i = 0; url_table[i].string; ++i) {
2849 int match;
2850 if (url_table[i].is_prefix) {
2851 match = !strcmpstart(url, url_table[i].string);
2852 } else {
2853 match = !strcmp(url, url_table[i].string);
2855 if (match) {
2856 result = url_table[i].handler(conn, &args);
2857 goto done;
2861 /* we didn't recognize the url */
2862 write_http_status_line(conn, 404, "Not found");
2863 result = 0;
2865 done:
2866 tor_free(url_mem);
2867 return result;
2870 /** Helper function for GET / or GET /tor/
2872 static int
2873 handle_get_frontpage(dir_connection_t *conn, const get_handler_args_t *args)
2875 (void) args; /* unused */
2876 const char *frontpage = get_dirportfrontpage();
2878 if (frontpage) {
2879 size_t dlen;
2880 dlen = strlen(frontpage);
2881 /* Let's return a disclaimer page (users shouldn't use V1 anymore,
2882 and caches don't fetch '/', so this is safe). */
2884 /* [We don't check for write_bucket_low here, since we want to serve
2885 * this page no matter what.] */
2886 write_http_response_header_impl(conn, dlen, "text/html", "identity",
2887 NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
2888 connection_write_to_buf(frontpage, dlen, TO_CONN(conn));
2889 } else {
2890 write_http_status_line(conn, 404, "Not found");
2892 return 0;
2895 /** Helper function for GET /tor/status-vote/current/consensus
2897 static int
2898 handle_get_current_consensus(dir_connection_t *conn,
2899 const get_handler_args_t *args)
2901 const char *url = args->url;
2902 const int compressed = args->compressed;
2903 const time_t if_modified_since = args->if_modified_since;
2906 /* v3 network status fetch. */
2907 smartlist_t *dir_fps = smartlist_new();
2908 long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2910 if (1) {
2911 networkstatus_t *v;
2912 time_t now = time(NULL);
2913 const char *want_fps = NULL;
2914 char *flavor = NULL;
2915 int flav = FLAV_NS;
2916 #define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/"
2917 #define CONSENSUS_FLAVORED_PREFIX "/tor/status-vote/current/consensus-"
2918 /* figure out the flavor if any, and who we wanted to sign the thing */
2919 if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) {
2920 const char *f, *cp;
2921 f = url + strlen(CONSENSUS_FLAVORED_PREFIX);
2922 cp = strchr(f, '/');
2923 if (cp) {
2924 want_fps = cp+1;
2925 flavor = tor_strndup(f, cp-f);
2926 } else {
2927 flavor = tor_strdup(f);
2929 flav = networkstatus_parse_flavor_name(flavor);
2930 if (flav < 0)
2931 flav = FLAV_NS;
2932 } else {
2933 if (!strcmpstart(url, CONSENSUS_URL_PREFIX))
2934 want_fps = url+strlen(CONSENSUS_URL_PREFIX);
2937 v = networkstatus_get_latest_consensus_by_flavor(flav);
2939 if (v && want_fps &&
2940 !client_likes_consensus(v, want_fps)) {
2941 write_http_status_line(conn, 404, "Consensus not signed by sufficient "
2942 "number of requested authorities");
2943 smartlist_free(dir_fps);
2944 geoip_note_ns_response(GEOIP_REJECT_NOT_ENOUGH_SIGS);
2945 tor_free(flavor);
2946 goto done;
2950 char *fp = tor_malloc_zero(DIGEST_LEN);
2951 if (flavor)
2952 strlcpy(fp, flavor, DIGEST_LEN);
2953 tor_free(flavor);
2954 smartlist_add(dir_fps, fp);
2956 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2959 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2960 write_http_status_line(conn, 503, "Network status object unavailable");
2961 smartlist_free(dir_fps);
2962 geoip_note_ns_response(GEOIP_REJECT_UNAVAILABLE);
2963 goto done;
2966 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2967 write_http_status_line(conn, 404, "Not found");
2968 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2969 smartlist_free(dir_fps);
2970 geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
2971 goto done;
2972 } else if (!smartlist_len(dir_fps)) {
2973 write_http_status_line(conn, 304, "Not modified");
2974 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2975 smartlist_free(dir_fps);
2976 geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
2977 goto done;
2980 size_t dlen = dirserv_estimate_data_size(dir_fps, 0, compressed);
2981 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2982 log_debug(LD_DIRSERV,
2983 "Client asked for network status lists, but we've been "
2984 "writing too many bytes lately. Sending 503 Dir busy.");
2985 write_http_status_line(conn, 503, "Directory busy, try again later");
2986 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2987 smartlist_free(dir_fps);
2989 geoip_note_ns_response(GEOIP_REJECT_BUSY);
2990 goto done;
2993 if (1) {
2994 tor_addr_t addr;
2995 if (tor_addr_parse(&addr, (TO_CONN(conn))->address) >= 0) {
2996 geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS,
2997 &addr, NULL,
2998 time(NULL));
2999 geoip_note_ns_response(GEOIP_SUCCESS);
3000 /* Note that a request for a network status has started, so that we
3001 * can measure the download time later on. */
3002 if (conn->dirreq_id)
3003 geoip_start_dirreq(conn->dirreq_id, dlen, DIRREQ_TUNNELED);
3004 else
3005 geoip_start_dirreq(TO_CONN(conn)->global_identifier, dlen,
3006 DIRREQ_DIRECT);
3010 write_http_response_header(conn, -1, compressed,
3011 smartlist_len(dir_fps) == 1 ? lifetime : 0);
3012 conn->fingerprint_stack = dir_fps;
3013 if (! compressed)
3014 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
3016 /* Prime the connection with some data. */
3017 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
3018 connection_dirserv_flushed_some(conn);
3019 goto done;
3022 done:
3023 return 0;
3026 /** Helper function for GET /tor/status-vote/{current,next}/...
3028 static int
3029 handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
3031 const char *url = args->url;
3032 const int compressed = args->compressed;
3034 int current;
3035 ssize_t body_len = 0;
3036 ssize_t estimated_len = 0;
3037 smartlist_t *items = smartlist_new();
3038 smartlist_t *dir_items = smartlist_new();
3039 int lifetime = 60; /* XXXX?? should actually use vote intervals. */
3040 url += strlen("/tor/status-vote/");
3041 current = !strcmpstart(url, "current/");
3042 url = strchr(url, '/');
3043 tor_assert(url);
3044 ++url;
3045 if (!strcmp(url, "consensus")) {
3046 const char *item;
3047 tor_assert(!current); /* we handle current consensus specially above,
3048 * since it wants to be spooled. */
3049 if ((item = dirvote_get_pending_consensus(FLAV_NS)))
3050 smartlist_add(items, (char*)item);
3051 } else if (!current && !strcmp(url, "consensus-signatures")) {
3052 /* XXXX the spec says that we should implement
3053 * current/consensus-signatures too. It doesn't seem to be needed,
3054 * though. */
3055 const char *item;
3056 if ((item=dirvote_get_pending_detached_signatures()))
3057 smartlist_add(items, (char*)item);
3058 } else if (!strcmp(url, "authority")) {
3059 const cached_dir_t *d;
3060 int flags = DGV_BY_ID |
3061 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
3062 if ((d=dirvote_get_vote(NULL, flags)))
3063 smartlist_add(dir_items, (cached_dir_t*)d);
3064 } else {
3065 const cached_dir_t *d;
3066 smartlist_t *fps = smartlist_new();
3067 int flags;
3068 if (!strcmpstart(url, "d/")) {
3069 url += 2;
3070 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
3071 } else {
3072 flags = DGV_BY_ID |
3073 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
3075 dir_split_resource_into_fingerprints(url, fps, NULL,
3076 DSR_HEX|DSR_SORT_UNIQ);
3077 SMARTLIST_FOREACH(fps, char *, fp, {
3078 if ((d = dirvote_get_vote(fp, flags)))
3079 smartlist_add(dir_items, (cached_dir_t*)d);
3080 tor_free(fp);
3082 smartlist_free(fps);
3084 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
3085 write_http_status_line(conn, 404, "Not found");
3086 goto vote_done;
3088 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
3089 body_len += compressed ? d->dir_z_len : d->dir_len);
3090 estimated_len += body_len;
3091 SMARTLIST_FOREACH(items, const char *, item, {
3092 size_t ln = strlen(item);
3093 if (compressed) {
3094 estimated_len += ln/2;
3095 } else {
3096 body_len += ln; estimated_len += ln;
3100 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
3101 write_http_status_line(conn, 503, "Directory busy, try again later");
3102 goto vote_done;
3104 write_http_response_header(conn, body_len ? body_len : -1, compressed,
3105 lifetime);
3107 if (smartlist_len(items)) {
3108 if (compressed) {
3109 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD,
3110 choose_compression_level(estimated_len));
3111 SMARTLIST_FOREACH(items, const char *, c,
3112 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
3113 connection_write_to_buf_zlib("", 0, conn, 1);
3114 } else {
3115 SMARTLIST_FOREACH(items, const char *, c,
3116 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
3118 } else {
3119 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
3120 connection_write_to_buf(compressed ? d->dir_z : d->dir,
3121 compressed ? d->dir_z_len : d->dir_len,
3122 TO_CONN(conn)));
3124 vote_done:
3125 smartlist_free(items);
3126 smartlist_free(dir_items);
3127 goto done;
3129 done:
3130 return 0;
3133 /** Helper function for GET /tor/micro/d/...
3135 static int
3136 handle_get_microdesc(dir_connection_t *conn, const get_handler_args_t *args)
3138 const char *url = args->url;
3139 const int compressed = args->compressed;
3141 smartlist_t *fps = smartlist_new();
3143 dir_split_resource_into_fingerprints(url+strlen("/tor/micro/d/"),
3144 fps, NULL,
3145 DSR_DIGEST256|DSR_BASE64|DSR_SORT_UNIQ);
3147 if (!dirserv_have_any_microdesc(fps)) {
3148 write_http_status_line(conn, 404, "Not found");
3149 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
3150 smartlist_free(fps);
3151 goto done;
3153 size_t dlen = dirserv_estimate_microdesc_size(fps, compressed);
3154 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
3155 log_info(LD_DIRSERV,
3156 "Client asked for server descriptors, but we've been "
3157 "writing too many bytes lately. Sending 503 Dir busy.");
3158 write_http_status_line(conn, 503, "Directory busy, try again later");
3159 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
3160 smartlist_free(fps);
3161 goto done;
3164 write_http_response_header(conn, -1, compressed, MICRODESC_CACHE_LIFETIME);
3165 conn->dir_spool_src = DIR_SPOOL_MICRODESC;
3166 conn->fingerprint_stack = fps;
3168 if (compressed)
3169 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD,
3170 choose_compression_level(dlen));
3172 connection_dirserv_flushed_some(conn);
3173 goto done;
3176 done:
3177 return 0;
3180 /** Helper function for GET /tor/{server,extra}/...
3182 static int
3183 handle_get_descriptor(dir_connection_t *conn, const get_handler_args_t *args)
3185 const char *url = args->url;
3186 const int compressed = args->compressed;
3187 const or_options_t *options = get_options();
3188 if (!strcmpstart(url,"/tor/server/") ||
3189 (!options->BridgeAuthoritativeDir &&
3190 !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
3191 size_t dlen;
3192 int res;
3193 const char *msg;
3194 int cache_lifetime = 0;
3195 int is_extra = !strcmpstart(url,"/tor/extra/");
3196 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
3197 conn->fingerprint_stack = smartlist_new();
3198 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
3199 &msg,
3200 !connection_dir_is_encrypted(conn),
3201 is_extra);
3203 if (!strcmpstart(url, "fp/")) {
3204 if (smartlist_len(conn->fingerprint_stack) == 1)
3205 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
3206 } else if (!strcmpstart(url, "authority")) {
3207 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
3208 } else if (!strcmpstart(url, "all")) {
3209 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
3210 } else if (!strcmpstart(url, "d/")) {
3211 if (smartlist_len(conn->fingerprint_stack) == 1)
3212 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
3214 if (!strcmpstart(url, "d/"))
3215 conn->dir_spool_src =
3216 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
3217 else
3218 conn->dir_spool_src =
3219 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
3221 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
3222 conn->dir_spool_src)) {
3223 res = -1;
3224 msg = "Not found";
3227 if (res < 0)
3228 write_http_status_line(conn, 404, msg);
3229 else {
3230 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
3231 1, compressed);
3232 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
3233 log_info(LD_DIRSERV,
3234 "Client asked for server descriptors, but we've been "
3235 "writing too many bytes lately. Sending 503 Dir busy.");
3236 write_http_status_line(conn, 503, "Directory busy, try again later");
3237 conn->dir_spool_src = DIR_SPOOL_NONE;
3238 goto done;
3240 write_http_response_header(conn, -1, compressed, cache_lifetime);
3241 if (compressed)
3242 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD,
3243 choose_compression_level(dlen));
3244 /* Prime the connection with some data. */
3245 connection_dirserv_flushed_some(conn);
3247 goto done;
3249 done:
3250 return 0;
3253 /** Helper function for GET /tor/keys/...
3255 static int
3256 handle_get_keys(dir_connection_t *conn, const get_handler_args_t *args)
3258 const char *url = args->url;
3259 const int compressed = args->compressed;
3260 const time_t if_modified_since = args->if_modified_since;
3262 smartlist_t *certs = smartlist_new();
3263 ssize_t len = -1;
3264 if (!strcmp(url, "/tor/keys/all")) {
3265 authority_cert_get_all(certs);
3266 } else if (!strcmp(url, "/tor/keys/authority")) {
3267 authority_cert_t *cert = get_my_v3_authority_cert();
3268 if (cert)
3269 smartlist_add(certs, cert);
3270 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
3271 smartlist_t *fps = smartlist_new();
3272 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
3273 fps, NULL,
3274 DSR_HEX|DSR_SORT_UNIQ);
3275 SMARTLIST_FOREACH(fps, char *, d, {
3276 authority_cert_t *c = authority_cert_get_newest_by_id(d);
3277 if (c) smartlist_add(certs, c);
3278 tor_free(d);
3280 smartlist_free(fps);
3281 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
3282 smartlist_t *fps = smartlist_new();
3283 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
3284 fps, NULL,
3285 DSR_HEX|DSR_SORT_UNIQ);
3286 SMARTLIST_FOREACH(fps, char *, d, {
3287 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
3288 if (c) smartlist_add(certs, c);
3289 tor_free(d);
3291 smartlist_free(fps);
3292 } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
3293 smartlist_t *fp_sks = smartlist_new();
3294 dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
3295 fp_sks);
3296 SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
3297 authority_cert_t *c = authority_cert_get_by_digests(pair->first,
3298 pair->second);
3299 if (c) smartlist_add(certs, c);
3300 tor_free(pair);
3302 smartlist_free(fp_sks);
3303 } else {
3304 write_http_status_line(conn, 400, "Bad request");
3305 goto keys_done;
3307 if (!smartlist_len(certs)) {
3308 write_http_status_line(conn, 404, "Not found");
3309 goto keys_done;
3311 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3312 if (c->cache_info.published_on < if_modified_since)
3313 SMARTLIST_DEL_CURRENT(certs, c));
3314 if (!smartlist_len(certs)) {
3315 write_http_status_line(conn, 304, "Not modified");
3316 goto keys_done;
3318 len = 0;
3319 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3320 len += c->cache_info.signed_descriptor_len);
3322 if (global_write_bucket_low(TO_CONN(conn), compressed?len/2:len, 2)) {
3323 write_http_status_line(conn, 503, "Directory busy, try again later");
3324 goto keys_done;
3327 write_http_response_header(conn, compressed?-1:len, compressed, 60*60);
3328 if (compressed) {
3329 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD,
3330 choose_compression_level(len));
3331 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3332 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
3333 c->cache_info.signed_descriptor_len,
3334 conn, 0));
3335 connection_write_to_buf_zlib("", 0, conn, 1);
3336 } else {
3337 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3338 connection_write_to_buf(c->cache_info.signed_descriptor_body,
3339 c->cache_info.signed_descriptor_len,
3340 TO_CONN(conn)));
3342 keys_done:
3343 smartlist_free(certs);
3344 goto done;
3346 done:
3347 return 0;
3350 /** Helper function for GET /tor/rendezvous2/
3352 static int
3353 handle_get_rendezvous2(dir_connection_t *conn, const get_handler_args_t *args)
3355 const char *url = args->url;
3356 if (connection_dir_is_encrypted(conn)) {
3357 /* Handle v2 rendezvous descriptor fetch request. */
3358 const char *descp;
3359 const char *query = url + strlen("/tor/rendezvous2/");
3360 if (rend_valid_descriptor_id(query)) {
3361 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
3362 safe_str(escaped(query)));
3363 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
3364 case 1: /* valid */
3365 write_http_response_header(conn, strlen(descp), 0, 0);
3366 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
3367 break;
3368 case 0: /* well-formed but not present */
3369 write_http_status_line(conn, 404, "Not found");
3370 break;
3371 case -1: /* not well-formed */
3372 write_http_status_line(conn, 400, "Bad request");
3373 break;
3375 } else { /* not well-formed */
3376 write_http_status_line(conn, 400, "Bad request");
3378 goto done;
3379 } else {
3380 /* Not encrypted! */
3381 write_http_status_line(conn, 404, "Not found");
3383 done:
3384 return 0;
3387 /** Helper function for GET /tor/networkstatus-bridges
3389 static int
3390 handle_get_networkstatus_bridges(dir_connection_t *conn,
3391 const get_handler_args_t *args)
3393 const char *headers = args->headers;
3395 const or_options_t *options = get_options();
3396 if (options->BridgeAuthoritativeDir &&
3397 options->BridgePassword_AuthDigest_ &&
3398 connection_dir_is_encrypted(conn)) {
3399 char *status;
3400 char digest[DIGEST256_LEN];
3402 char *header = http_get_header(headers, "Authorization: Basic ");
3403 if (header)
3404 crypto_digest256(digest, header, strlen(header), DIGEST_SHA256);
3406 /* now make sure the password is there and right */
3407 if (!header ||
3408 tor_memneq(digest,
3409 options->BridgePassword_AuthDigest_, DIGEST256_LEN)) {
3410 write_http_status_line(conn, 404, "Not found");
3411 tor_free(header);
3412 goto done;
3414 tor_free(header);
3416 /* all happy now. send an answer. */
3417 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
3418 size_t dlen = strlen(status);
3419 write_http_response_header(conn, dlen, 0, 0);
3420 connection_write_to_buf(status, dlen, TO_CONN(conn));
3421 tor_free(status);
3422 goto done;
3424 done:
3425 return 0;
3428 /** Helper function for GET robots.txt or /tor/robots.txt */
3429 static int
3430 handle_get_robots(dir_connection_t *conn, const get_handler_args_t *args)
3432 (void)args;
3434 const char robots[] = "User-agent: *\r\nDisallow: /\r\n";
3435 size_t len = strlen(robots);
3436 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
3437 connection_write_to_buf(robots, len, TO_CONN(conn));
3439 return 0;
3442 /** Helper function: called when a dirserver gets a complete HTTP POST
3443 * request. Look for an uploaded server descriptor or rendezvous
3444 * service descriptor. On finding one, process it and write a
3445 * response into conn-\>outbuf. If the request is unrecognized, send a
3446 * 400. Always return 0. */
3447 static int
3448 directory_handle_command_post(dir_connection_t *conn, const char *headers,
3449 const char *body, size_t body_len)
3451 char *url = NULL;
3452 const or_options_t *options = get_options();
3454 log_debug(LD_DIRSERV,"Received POST command.");
3456 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
3458 if (!public_server_mode(options)) {
3459 log_info(LD_DIR, "Rejected dir post request from %s "
3460 "since we're not a public relay.", conn->base_.address);
3461 write_http_status_line(conn, 503, "Not acting as a public relay");
3462 goto done;
3465 if (parse_http_url(headers, &url) < 0) {
3466 write_http_status_line(conn, 400, "Bad request");
3467 return 0;
3469 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
3471 /* Handle v2 rendezvous service publish request. */
3472 if (connection_dir_is_encrypted(conn) &&
3473 !strcmpstart(url,"/tor/rendezvous2/publish")) {
3474 if (rend_cache_store_v2_desc_as_dir(body) < 0) {
3475 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
3476 (int)body_len, conn->base_.address);
3477 write_http_status_line(conn, 400,
3478 "Invalid v2 service descriptor rejected");
3479 } else {
3480 write_http_status_line(conn, 200, "Service descriptor (v2) stored");
3481 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
3483 goto done;
3486 if (!authdir_mode(options)) {
3487 /* we just provide cached directories; we don't want to
3488 * receive anything. */
3489 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
3490 "accept posted server descriptors");
3491 goto done;
3494 if (authdir_mode_handles_descs(options, -1) &&
3495 !strcmp(url,"/tor/")) { /* server descriptor post */
3496 const char *msg = "[None]";
3497 uint8_t purpose = authdir_mode_bridge(options) ?
3498 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
3499 was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
3500 conn->base_.address, &msg);
3501 tor_assert(msg);
3503 if (r == ROUTER_ADDED_NOTIFY_GENERATOR) {
3504 /* Accepted with a message. */
3505 log_info(LD_DIRSERV,
3506 "Problematic router descriptor or extra-info from %s "
3507 "(\"%s\").",
3508 conn->base_.address, msg);
3509 write_http_status_line(conn, 400, msg);
3510 } else if (r == ROUTER_ADDED_SUCCESSFULLY) {
3511 write_http_status_line(conn, 200, msg);
3512 } else if (WRA_WAS_OUTDATED(r)) {
3513 write_http_response_header_impl(conn, -1, NULL, NULL,
3514 "X-Descriptor-Not-New: Yes\r\n", -1);
3515 } else {
3516 log_info(LD_DIRSERV,
3517 "Rejected router descriptor or extra-info from %s "
3518 "(\"%s\").",
3519 conn->base_.address, msg);
3520 write_http_status_line(conn, 400, msg);
3522 goto done;
3525 if (authdir_mode_v3(options) &&
3526 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
3527 const char *msg = "OK";
3528 int status;
3529 if (dirvote_add_vote(body, &msg, &status)) {
3530 write_http_status_line(conn, status, "Vote stored");
3531 } else {
3532 tor_assert(msg);
3533 log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").",
3534 conn->base_.address, msg);
3535 write_http_status_line(conn, status, msg);
3537 goto done;
3540 if (authdir_mode_v3(options) &&
3541 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
3542 const char *msg = NULL;
3543 if (dirvote_add_signatures(body, conn->base_.address, &msg)>=0) {
3544 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
3545 } else {
3546 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
3547 conn->base_.address, msg?msg:"???");
3548 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
3550 goto done;
3553 /* we didn't recognize the url */
3554 write_http_status_line(conn, 404, "Not found");
3556 done:
3557 tor_free(url);
3558 return 0;
3561 /** Called when a dirserver receives data on a directory connection;
3562 * looks for an HTTP request. If the request is complete, remove it
3563 * from the inbuf, try to process it; otherwise, leave it on the
3564 * buffer. Return a 0 on success, or -1 on error.
3566 static int
3567 directory_handle_command(dir_connection_t *conn)
3569 char *headers=NULL, *body=NULL;
3570 size_t body_len=0;
3571 int r;
3573 tor_assert(conn);
3574 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3576 switch (connection_fetch_from_buf_http(TO_CONN(conn),
3577 &headers, MAX_HEADERS_SIZE,
3578 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
3579 case -1: /* overflow */
3580 log_warn(LD_DIRSERV,
3581 "Request too large from address '%s' to DirPort. Closing.",
3582 safe_str(conn->base_.address));
3583 return -1;
3584 case 0:
3585 log_debug(LD_DIRSERV,"command not all here yet.");
3586 return 0;
3587 /* case 1, fall through */
3590 http_set_address_origin(headers, TO_CONN(conn));
3591 // we should escape headers here as well,
3592 // but we can't call escaped() twice, as it uses the same buffer
3593 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, escaped(body));
3595 if (!strncasecmp(headers,"GET",3))
3596 r = directory_handle_command_get(conn, headers, body, body_len);
3597 else if (!strncasecmp(headers,"POST",4))
3598 r = directory_handle_command_post(conn, headers, body, body_len);
3599 else {
3600 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
3601 "Got headers %s with unknown command. Closing.",
3602 escaped(headers));
3603 r = -1;
3606 tor_free(headers); tor_free(body);
3607 return r;
3610 /** Write handler for directory connections; called when all data has
3611 * been flushed. Close the connection or wait for a response as
3612 * appropriate.
3615 connection_dir_finished_flushing(dir_connection_t *conn)
3617 tor_assert(conn);
3618 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3620 /* Note that we have finished writing the directory response. For direct
3621 * connections this means we're done; for tunneled connections it's only
3622 * an intermediate step. */
3623 if (conn->dirreq_id)
3624 geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
3625 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3626 else
3627 geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
3628 DIRREQ_DIRECT,
3629 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3630 switch (conn->base_.state) {
3631 case DIR_CONN_STATE_CONNECTING:
3632 case DIR_CONN_STATE_CLIENT_SENDING:
3633 log_debug(LD_DIR,"client finished sending command.");
3634 conn->base_.state = DIR_CONN_STATE_CLIENT_READING;
3635 return 0;
3636 case DIR_CONN_STATE_SERVER_WRITING:
3637 if (conn->dir_spool_src != DIR_SPOOL_NONE) {
3638 log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
3639 connection_mark_for_close(TO_CONN(conn));
3640 } else {
3641 log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
3642 connection_mark_for_close(TO_CONN(conn));
3644 return 0;
3645 default:
3646 log_warn(LD_BUG,"called in unexpected state %d.",
3647 conn->base_.state);
3648 tor_fragile_assert();
3649 return -1;
3651 return 0;
3654 /* We just got a new consensus! If there are other in-progress requests
3655 * for this consensus flavor (for example because we launched several in
3656 * parallel), cancel them.
3658 * We do this check here (not just in
3659 * connection_ap_handshake_attach_circuit()) to handle the edge case where
3660 * a consensus fetch begins and ends before some other one tries to attach to
3661 * a circuit, in which case the other one won't know that we're all happy now.
3663 * Don't mark the conn that just gave us the consensus -- otherwise we
3664 * would end up double-marking it when it cleans itself up.
3666 static void
3667 connection_dir_close_consensus_fetches(dir_connection_t *except_this_one,
3668 const char *resource)
3670 smartlist_t *conns_to_close =
3671 connection_dir_list_by_purpose_and_resource(DIR_PURPOSE_FETCH_CONSENSUS,
3672 resource);
3673 SMARTLIST_FOREACH_BEGIN(conns_to_close, dir_connection_t *, d) {
3674 if (d == except_this_one)
3675 continue;
3676 log_info(LD_DIR, "Closing consensus fetch (to %s) since one "
3677 "has just arrived.", TO_CONN(d)->address);
3678 connection_mark_for_close(TO_CONN(d));
3679 } SMARTLIST_FOREACH_END(d);
3680 smartlist_free(conns_to_close);
3683 /** Connected handler for directory connections: begin sending data to the
3684 * server, and return 0.
3685 * Only used when connections don't immediately connect. */
3687 connection_dir_finished_connecting(dir_connection_t *conn)
3689 tor_assert(conn);
3690 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3691 tor_assert(conn->base_.state == DIR_CONN_STATE_CONNECTING);
3693 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
3694 conn->base_.address,conn->base_.port);
3696 /* start flushing conn */
3697 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
3698 return 0;
3701 /** Decide which download schedule we want to use based on descriptor type
3702 * in <b>dls</b> and <b>options</b>.
3703 * Then return a list of int pointers defining download delays in seconds.
3704 * Helper function for download_status_increment_failure(),
3705 * download_status_reset(), and download_status_increment_attempt(). */
3706 STATIC const smartlist_t *
3707 find_dl_schedule(download_status_t *dls, const or_options_t *options)
3709 const int dir_server = dir_server_mode(options);
3710 const int multi_d = networkstatus_consensus_can_use_multiple_directories(
3711 options);
3712 const int we_are_bootstrapping = networkstatus_consensus_is_bootstrapping(
3713 time(NULL));
3714 const int use_fallbacks = networkstatus_consensus_can_use_extra_fallbacks(
3715 options);
3716 switch (dls->schedule) {
3717 case DL_SCHED_GENERIC:
3718 if (dir_server) {
3719 return options->TestingServerDownloadSchedule;
3720 } else {
3721 return options->TestingClientDownloadSchedule;
3723 case DL_SCHED_CONSENSUS:
3724 if (!multi_d) {
3725 return options->TestingServerConsensusDownloadSchedule;
3726 } else {
3727 if (we_are_bootstrapping) {
3728 if (!use_fallbacks) {
3729 /* A bootstrapping client without extra fallback directories */
3730 return
3731 options->ClientBootstrapConsensusAuthorityOnlyDownloadSchedule;
3732 } else if (dls->want_authority) {
3733 /* A bootstrapping client with extra fallback directories, but
3734 * connecting to an authority */
3735 return
3736 options->ClientBootstrapConsensusAuthorityDownloadSchedule;
3737 } else {
3738 /* A bootstrapping client connecting to extra fallback directories
3740 return
3741 options->ClientBootstrapConsensusFallbackDownloadSchedule;
3743 } else {
3744 return options->TestingClientConsensusDownloadSchedule;
3747 case DL_SCHED_BRIDGE:
3748 return options->TestingBridgeDownloadSchedule;
3749 default:
3750 tor_assert(0);
3753 /* Impossible, but gcc will fail with -Werror without a `return`. */
3754 return NULL;
3757 /** Decide which minimum and maximum delay step we want to use based on
3758 * descriptor type in <b>dls</b> and <b>options</b>.
3759 * Helper function for download_status_schedule_get_delay(). */
3760 STATIC void
3761 find_dl_min_and_max_delay(download_status_t *dls, const or_options_t *options,
3762 int *min, int *max)
3764 tor_assert(dls);
3765 tor_assert(options);
3766 tor_assert(min);
3767 tor_assert(max);
3770 * For now, just use the existing schedule config stuff and pick the
3771 * first/last entries off to get min/max delay for backoff purposes
3773 const smartlist_t *schedule = find_dl_schedule(dls, options);
3774 tor_assert(schedule != NULL && smartlist_len(schedule) >= 2);
3775 *min = *((int *)(smartlist_get(schedule, 0)));
3776 *max = *((int *)((smartlist_get(schedule, smartlist_len(schedule) - 1))));
3779 /** Advance one delay step. The algorithm is to use the previous delay to
3780 * compute an increment, we construct a value uniformly at random between
3781 * delay and MAX(delay*2,delay+1). We then clamp that value to be no larger
3782 * than max_delay, and return it.
3784 * Requires that delay is less than INT_MAX, and delay is in [0,max_delay].
3786 STATIC int
3787 next_random_exponential_delay(int delay, int max_delay)
3789 /* Check preconditions */
3790 if (BUG(delay > max_delay))
3791 delay = max_delay;
3792 if (BUG(delay == INT_MAX))
3793 delay -= 1; /* prevent overflow */
3794 if (BUG(delay < 0))
3795 delay = 0;
3797 /* How much are we willing to add to the delay? */
3798 int max_increment;
3800 if (delay)
3801 max_increment = delay; /* no more than double. */
3802 else
3803 max_increment = 1; /* we're always willing to slow down a little. */
3805 /* the + 1 here is so that we include the end of the interval */
3806 int increment = crypto_rand_int(max_increment+1);
3808 if (increment < max_delay - delay)
3809 return delay + increment;
3810 else
3811 return max_delay;
3814 /** Find the current delay for dls based on schedule or min_delay/
3815 * max_delay if we're using exponential backoff. If dls->backoff is
3816 * DL_SCHED_RANDOM_EXPONENTIAL, we must have 0 <= min_delay <= max_delay <=
3817 * INT_MAX, but schedule may be set to NULL; otherwise schedule is required.
3818 * This function sets dls->next_attempt_at based on now, and returns the delay.
3819 * Helper for download_status_increment_failure and
3820 * download_status_increment_attempt. */
3821 STATIC int
3822 download_status_schedule_get_delay(download_status_t *dls,
3823 const smartlist_t *schedule,
3824 int min_delay, int max_delay,
3825 time_t now)
3827 tor_assert(dls);
3828 /* We don't need a schedule if we're using random exponential backoff */
3829 tor_assert(dls->backoff == DL_SCHED_RANDOM_EXPONENTIAL ||
3830 schedule != NULL);
3831 /* If we're using random exponential backoff, we do need min/max delay */
3832 tor_assert(dls->backoff != DL_SCHED_RANDOM_EXPONENTIAL ||
3833 (min_delay >= 0 && max_delay >= min_delay));
3835 int delay = INT_MAX;
3836 uint8_t dls_schedule_position = (dls->increment_on
3837 == DL_SCHED_INCREMENT_ATTEMPT
3838 ? dls->n_download_attempts
3839 : dls->n_download_failures);
3841 if (dls->backoff == DL_SCHED_DETERMINISTIC) {
3842 if (dls_schedule_position < smartlist_len(schedule))
3843 delay = *(int *)smartlist_get(schedule, dls_schedule_position);
3844 else if (dls_schedule_position == IMPOSSIBLE_TO_DOWNLOAD)
3845 delay = INT_MAX;
3846 else
3847 delay = *(int *)smartlist_get(schedule, smartlist_len(schedule) - 1);
3848 } else if (dls->backoff == DL_SCHED_RANDOM_EXPONENTIAL) {
3849 /* Check if we missed a reset somehow */
3850 if (dls->last_backoff_position > dls_schedule_position) {
3851 dls->last_backoff_position = 0;
3852 dls->last_delay_used = 0;
3855 if (dls_schedule_position > 0) {
3856 delay = dls->last_delay_used;
3858 while (dls->last_backoff_position < dls_schedule_position) {
3859 /* Do one increment step */
3860 delay = next_random_exponential_delay(delay, max_delay);
3861 /* Update our position */
3862 ++(dls->last_backoff_position);
3864 } else {
3865 /* If we're just starting out, use the minimum delay */
3866 delay = min_delay;
3869 /* Clamp it within min/max if we have them */
3870 if (min_delay >= 0 && delay < min_delay) delay = min_delay;
3871 if (max_delay != INT_MAX && delay > max_delay) delay = max_delay;
3873 /* Store it for next time */
3874 dls->last_backoff_position = dls_schedule_position;
3875 dls->last_delay_used = delay;
3878 /* A negative delay makes no sense. Knowing that delay is
3879 * non-negative allows us to safely do the wrapping check below. */
3880 tor_assert(delay >= 0);
3882 /* Avoid now+delay overflowing INT_MAX, by comparing with a subtraction
3883 * that won't overflow (since delay is non-negative). */
3884 if (delay < INT_MAX && now <= INT_MAX - delay) {
3885 dls->next_attempt_at = now+delay;
3886 } else {
3887 dls->next_attempt_at = TIME_MAX;
3890 return delay;
3893 /* Log a debug message about item, which increments on increment_action, has
3894 * incremented dls_n_download_increments times. The message varies based on
3895 * was_schedule_incremented (if not, not_incremented_response is logged), and
3896 * the values of increment, dls_next_attempt_at, and now.
3897 * Helper for download_status_increment_failure and
3898 * download_status_increment_attempt. */
3899 static void
3900 download_status_log_helper(const char *item, int was_schedule_incremented,
3901 const char *increment_action,
3902 const char *not_incremented_response,
3903 uint8_t dls_n_download_increments, int increment,
3904 time_t dls_next_attempt_at, time_t now)
3906 if (item) {
3907 if (!was_schedule_incremented)
3908 log_debug(LD_DIR, "%s %s %d time(s); I'll try again %s.",
3909 item, increment_action, (int)dls_n_download_increments,
3910 not_incremented_response);
3911 else if (increment == 0)
3912 log_debug(LD_DIR, "%s %s %d time(s); I'll try again immediately.",
3913 item, increment_action, (int)dls_n_download_increments);
3914 else if (dls_next_attempt_at < TIME_MAX)
3915 log_debug(LD_DIR, "%s %s %d time(s); I'll try again in %d seconds.",
3916 item, increment_action, (int)dls_n_download_increments,
3917 (int)(dls_next_attempt_at-now));
3918 else
3919 log_debug(LD_DIR, "%s %s %d time(s); Giving up for a while.",
3920 item, increment_action, (int)dls_n_download_increments);
3924 /** Determine when a failed download attempt should be retried.
3925 * Called when an attempt to download <b>dls</b> has failed with HTTP status
3926 * <b>status_code</b>. Increment the failure count (if the code indicates a
3927 * real failure, or if we're a server) and set <b>dls</b>-\>next_attempt_at to
3928 * an appropriate time in the future and return it.
3929 * If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_ATTEMPT, increment the
3930 * failure count, and return a time in the far future for the next attempt (to
3931 * avoid an immediate retry). */
3932 time_t
3933 download_status_increment_failure(download_status_t *dls, int status_code,
3934 const char *item, int server, time_t now)
3936 int increment = -1;
3937 int min_delay = 0, max_delay = INT_MAX;
3939 tor_assert(dls);
3941 /* only count the failure if it's permanent, or we're a server */
3942 if (status_code != 503 || server) {
3943 if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1)
3944 ++dls->n_download_failures;
3947 if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
3948 /* We don't find out that a failure-based schedule has attempted a
3949 * connection until that connection fails.
3950 * We'll never find out about successful connections, but this doesn't
3951 * matter, because schedules are reset after a successful download.
3953 if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
3954 ++dls->n_download_attempts;
3956 /* only return a failure retry time if this schedule increments on failures
3958 const smartlist_t *schedule = find_dl_schedule(dls, get_options());
3959 find_dl_min_and_max_delay(dls, get_options(), &min_delay, &max_delay);
3960 increment = download_status_schedule_get_delay(dls, schedule,
3961 min_delay, max_delay, now);
3964 download_status_log_helper(item, !dls->increment_on, "failed",
3965 "concurrently", dls->n_download_failures,
3966 increment, dls->next_attempt_at, now);
3968 if (dls->increment_on == DL_SCHED_INCREMENT_ATTEMPT) {
3969 /* stop this schedule retrying on failure, it will launch concurrent
3970 * connections instead */
3971 return TIME_MAX;
3972 } else {
3973 return dls->next_attempt_at;
3977 /** Determine when the next download attempt should be made when using an
3978 * attempt-based (potentially concurrent) download schedule.
3979 * Called when an attempt to download <b>dls</b> is being initiated.
3980 * Increment the attempt count and set <b>dls</b>-\>next_attempt_at to an
3981 * appropriate time in the future and return it.
3982 * If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_FAILURE, don't increment
3983 * the attempts, and return a time in the far future (to avoid launching a
3984 * concurrent attempt). */
3985 time_t
3986 download_status_increment_attempt(download_status_t *dls, const char *item,
3987 time_t now)
3989 int delay = -1;
3990 int min_delay = 0, max_delay = INT_MAX;
3992 tor_assert(dls);
3994 if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
3995 /* this schedule should retry on failure, and not launch any concurrent
3996 attempts */
3997 log_info(LD_BUG, "Tried to launch an attempt-based connection on a "
3998 "failure-based schedule.");
3999 return TIME_MAX;
4002 if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
4003 ++dls->n_download_attempts;
4005 const smartlist_t *schedule = find_dl_schedule(dls, get_options());
4006 find_dl_min_and_max_delay(dls, get_options(), &min_delay, &max_delay);
4007 delay = download_status_schedule_get_delay(dls, schedule,
4008 min_delay, max_delay, now);
4010 download_status_log_helper(item, dls->increment_on, "attempted",
4011 "on failure", dls->n_download_attempts,
4012 delay, dls->next_attempt_at, now);
4014 return dls->next_attempt_at;
4017 /** Reset <b>dls</b> so that it will be considered downloadable
4018 * immediately, and/or to show that we don't need it anymore.
4020 * Must be called to initialise a download schedule, otherwise the zeroth item
4021 * in the schedule will never be used.
4023 * (We find the zeroth element of the download schedule, and set
4024 * next_attempt_at to be the appropriate offset from 'now'. In most
4025 * cases this means setting it to 'now', so the item will be immediately
4026 * downloadable; in the case of bridge descriptors, the zeroth element
4027 * is an hour from now.) */
4028 void
4029 download_status_reset(download_status_t *dls)
4031 if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD
4032 || dls->n_download_attempts == IMPOSSIBLE_TO_DOWNLOAD)
4033 return; /* Don't reset this. */
4035 const smartlist_t *schedule = find_dl_schedule(dls, get_options());
4037 dls->n_download_failures = 0;
4038 dls->n_download_attempts = 0;
4039 dls->next_attempt_at = time(NULL) + *(int *)smartlist_get(schedule, 0);
4040 dls->last_backoff_position = 0;
4041 dls->last_delay_used = 0;
4042 /* Don't reset dls->want_authority or dls->increment_on */
4045 /** Return the number of failures on <b>dls</b> since the last success (if
4046 * any). */
4048 download_status_get_n_failures(const download_status_t *dls)
4050 return dls->n_download_failures;
4053 /** Return the number of attempts to download <b>dls</b> since the last success
4054 * (if any). This can differ from download_status_get_n_failures() due to
4055 * outstanding concurrent attempts. */
4057 download_status_get_n_attempts(const download_status_t *dls)
4059 return dls->n_download_attempts;
4062 /** Return the next time to attempt to download <b>dls</b>. */
4063 time_t
4064 download_status_get_next_attempt_at(const download_status_t *dls)
4066 return dls->next_attempt_at;
4069 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
4070 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
4071 * either as descriptor digests or as identity digests based on
4072 * <b>was_descriptor_digests</b>).
4074 static void
4075 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
4076 int router_purpose,
4077 int was_extrainfo, int was_descriptor_digests)
4079 char digest[DIGEST_LEN];
4080 time_t now = time(NULL);
4081 int server = directory_fetches_from_authorities(get_options());
4082 if (!was_descriptor_digests) {
4083 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
4084 tor_assert(!was_extrainfo);
4085 connection_dir_retry_bridges(failed);
4087 return; /* FFFF should implement for other-than-router-purpose someday */
4089 SMARTLIST_FOREACH_BEGIN(failed, const char *, cp) {
4090 download_status_t *dls = NULL;
4091 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) != DIGEST_LEN) {
4092 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
4093 continue;
4095 if (was_extrainfo) {
4096 signed_descriptor_t *sd =
4097 router_get_by_extrainfo_digest(digest);
4098 if (sd)
4099 dls = &sd->ei_dl_status;
4100 } else {
4101 dls = router_get_dl_status_by_descriptor_digest(digest);
4103 if (!dls || dls->n_download_failures >=
4104 get_options()->TestingDescriptorMaxDownloadTries)
4105 continue;
4106 download_status_increment_failure(dls, status_code, cp, server, now);
4107 } SMARTLIST_FOREACH_END(cp);
4109 /* No need to relaunch descriptor downloads here: we already do it
4110 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
4113 /** Called when a connection to download microdescriptors has failed in whole
4114 * or in part. <b>failed</b> is a list of every microdesc digest we didn't
4115 * get. <b>status_code</b> is the http status code we received. Reschedule the
4116 * microdesc downloads as appropriate. */
4117 static void
4118 dir_microdesc_download_failed(smartlist_t *failed,
4119 int status_code)
4121 networkstatus_t *consensus
4122 = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
4123 routerstatus_t *rs;
4124 download_status_t *dls;
4125 time_t now = time(NULL);
4126 int server = directory_fetches_from_authorities(get_options());
4128 if (! consensus)
4129 return;
4130 SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
4131 rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
4132 if (!rs)
4133 continue;
4134 dls = &rs->dl_status;
4135 if (dls->n_download_failures >=
4136 get_options()->TestingMicrodescMaxDownloadTries)
4137 continue;
4139 char buf[BASE64_DIGEST256_LEN+1];
4140 digest256_to_base64(buf, d);
4141 download_status_increment_failure(dls, status_code, buf,
4142 server, now);
4144 } SMARTLIST_FOREACH_END(d);
4147 /** Helper. Compare two fp_pair_t objects, and return negative, 0, or
4148 * positive as appropriate. */
4149 static int
4150 compare_pairs_(const void **a, const void **b)
4152 const fp_pair_t *fp1 = *a, *fp2 = *b;
4153 int r;
4154 if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
4155 return r;
4156 else
4157 return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
4160 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
4161 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
4162 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
4163 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
4165 dir_split_resource_into_fingerprint_pairs(const char *res,
4166 smartlist_t *pairs_out)
4168 smartlist_t *pairs_tmp = smartlist_new();
4169 smartlist_t *pairs_result = smartlist_new();
4171 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
4172 if (smartlist_len(pairs_tmp)) {
4173 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
4174 size_t last_len = strlen(last);
4175 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
4176 last[last_len-2] = '\0';
4179 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
4180 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
4181 log_info(LD_DIR,
4182 "Skipping digest pair %s with non-standard length.", escaped(cp));
4183 } else if (cp[HEX_DIGEST_LEN] != '-') {
4184 log_info(LD_DIR,
4185 "Skipping digest pair %s with missing dash.", escaped(cp));
4186 } else {
4187 fp_pair_t pair;
4188 if (base16_decode(pair.first, DIGEST_LEN,
4189 cp, HEX_DIGEST_LEN) != DIGEST_LEN ||
4190 base16_decode(pair.second,DIGEST_LEN,
4191 cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN) != DIGEST_LEN) {
4192 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
4193 } else {
4194 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
4197 tor_free(cp);
4198 } SMARTLIST_FOREACH_END(cp);
4199 smartlist_free(pairs_tmp);
4201 /* Uniq-and-sort */
4202 smartlist_sort(pairs_result, compare_pairs_);
4203 smartlist_uniq(pairs_result, compare_pairs_, tor_free_);
4205 smartlist_add_all(pairs_out, pairs_result);
4206 smartlist_free(pairs_result);
4207 return 0;
4210 /** Given a directory <b>resource</b> request, containing zero
4211 * or more strings separated by plus signs, followed optionally by ".z", store
4212 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
4213 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
4215 * If (flags & DSR_HEX), then delete all elements that aren't hex digests, and
4216 * decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as
4217 * a separator, delete all the elements that aren't base64-encoded digests,
4218 * and decode the rest. If (flags & DSR_DIGEST256), these digests should be
4219 * 256 bits long; else they should be 160.
4221 * If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates.
4224 dir_split_resource_into_fingerprints(const char *resource,
4225 smartlist_t *fp_out, int *compressed_out,
4226 int flags)
4228 const int decode_hex = flags & DSR_HEX;
4229 const int decode_base64 = flags & DSR_BASE64;
4230 const int digests_are_256 = flags & DSR_DIGEST256;
4231 const int sort_uniq = flags & DSR_SORT_UNIQ;
4233 const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
4234 const int hex_digest_len = digests_are_256 ?
4235 HEX_DIGEST256_LEN : HEX_DIGEST_LEN;
4236 const int base64_digest_len = digests_are_256 ?
4237 BASE64_DIGEST256_LEN : BASE64_DIGEST_LEN;
4238 smartlist_t *fp_tmp = smartlist_new();
4240 tor_assert(!(decode_hex && decode_base64));
4241 tor_assert(fp_out);
4243 smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
4244 if (compressed_out)
4245 *compressed_out = 0;
4246 if (smartlist_len(fp_tmp)) {
4247 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
4248 size_t last_len = strlen(last);
4249 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
4250 last[last_len-2] = '\0';
4251 if (compressed_out)
4252 *compressed_out = 1;
4255 if (decode_hex || decode_base64) {
4256 const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
4257 int i;
4258 char *cp, *d = NULL;
4259 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
4260 cp = smartlist_get(fp_tmp, i);
4261 if (strlen(cp) != encoded_len) {
4262 log_info(LD_DIR,
4263 "Skipping digest %s with non-standard length.", escaped(cp));
4264 smartlist_del_keeporder(fp_tmp, i--);
4265 goto again;
4267 d = tor_malloc_zero(digest_len);
4268 if (decode_hex ?
4269 (base16_decode(d, digest_len, cp, hex_digest_len) != digest_len) :
4270 (base64_decode(d, digest_len, cp, base64_digest_len)
4271 != digest_len)) {
4272 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
4273 smartlist_del_keeporder(fp_tmp, i--);
4274 goto again;
4276 smartlist_set(fp_tmp, i, d);
4277 d = NULL;
4278 again:
4279 tor_free(cp);
4280 tor_free(d);
4283 if (sort_uniq) {
4284 if (decode_hex || decode_base64) {
4285 if (digests_are_256) {
4286 smartlist_sort_digests256(fp_tmp);
4287 smartlist_uniq_digests256(fp_tmp);
4288 } else {
4289 smartlist_sort_digests(fp_tmp);
4290 smartlist_uniq_digests(fp_tmp);
4292 } else {
4293 smartlist_sort_strings(fp_tmp);
4294 smartlist_uniq_strings(fp_tmp);
4297 smartlist_add_all(fp_out, fp_tmp);
4298 smartlist_free(fp_tmp);
4299 return 0;