Add Coccinelle patch for replacing NULL/non-NULL tt_assert().
[tor.git] / src / or / directory.c
blob57dfdd9cacc279b7952dcf804e0ed02a520f283b
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2017, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #define DIRECTORY_PRIVATE
8 #include "or.h"
9 #include "backtrace.h"
10 #include "bridges.h"
11 #include "buffers.h"
12 #include "circuitbuild.h"
13 #include "config.h"
14 #include "connection.h"
15 #include "connection_edge.h"
16 #include "conscache.h"
17 #include "consdiff.h"
18 #include "consdiffmgr.h"
19 #include "control.h"
20 #include "compat.h"
21 #include "directory.h"
22 #include "dirserv.h"
23 #include "dirvote.h"
24 #include "entrynodes.h"
25 #include "geoip.h"
26 #include "hs_cache.h"
27 #include "hs_common.h"
28 #include "hs_client.h"
29 #include "main.h"
30 #include "microdesc.h"
31 #include "networkstatus.h"
32 #include "nodelist.h"
33 #include "policies.h"
34 #include "relay.h"
35 #include "rendclient.h"
36 #include "rendcommon.h"
37 #include "rendservice.h"
38 #include "rephist.h"
39 #include "router.h"
40 #include "routerlist.h"
41 #include "routerparse.h"
42 #include "routerset.h"
43 #include "shared_random.h"
45 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
46 #if !defined(OpenBSD)
47 #include <malloc.h>
48 #endif
49 #endif
51 /**
52 * \file directory.c
53 * \brief Code to send and fetch information from directory authorities and
54 * caches via HTTP.
56 * Directory caches and authorities use dirserv.c to generate the results of a
57 * query and stream them to the connection; clients use routerparse.c to parse
58 * them.
60 * Every directory request has a dir_connection_t on the client side and on
61 * the server side. In most cases, the dir_connection_t object is a linked
62 * connection, tunneled through an edge_connection_t so that it can be a
63 * stream on the Tor network. The only non-tunneled connections are those
64 * that are used to upload material (descriptors and votes) to authorities.
65 * Among tunneled connections, some use one-hop circuits, and others use
66 * multi-hop circuits for anonymity.
68 * Directory requests are launched by calling
69 * directory_initiate_request(). This
70 * launch the connection, will construct an HTTP request with
71 * directory_send_command(), send the and wait for a response. The client
72 * later handles the response with connection_dir_client_reached_eof(),
73 * which passes the information received to another part of Tor.
75 * On the server side, requests are read in directory_handle_command(),
76 * which dispatches first on the request type (GET or POST), and then on
77 * the URL requested. GET requests are processed with a table-based
78 * dispatcher in url_table[]. The process of handling larger GET requests
79 * is complicated because we need to avoid allocating a copy of all the
80 * data to be sent to the client in one huge buffer. Instead, we spool the
81 * data into the buffer using logic in connection_dirserv_flushed_some() in
82 * dirserv.c. (TODO: If we extended buf.c to have a zero-copy
83 * reference-based buffer type, we could remove most of that code, at the
84 * cost of a bit more reference counting.)
85 **/
87 /* In-points to directory.c:
89 * - directory_post_to_dirservers(), called from
90 * router_upload_dir_desc_to_dirservers() in router.c
91 * upload_service_descriptor() in rendservice.c
92 * - directory_get_from_dirserver(), called from
93 * rend_client_refetch_renddesc() in rendclient.c
94 * run_scheduled_events() in main.c
95 * do_hup() in main.c
96 * - connection_dir_process_inbuf(), called from
97 * connection_process_inbuf() in connection.c
98 * - connection_dir_finished_flushing(), called from
99 * connection_finished_flushing() in connection.c
100 * - connection_dir_finished_connecting(), called from
101 * connection_finished_connecting() in connection.c
103 static void directory_send_command(dir_connection_t *conn,
104 int direct,
105 const directory_request_t *request);
106 static int body_is_plausible(const char *body, size_t body_len, int purpose);
107 static char *http_get_header(const char *headers, const char *which);
108 static void http_set_address_origin(const char *headers, connection_t *conn);
109 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
110 static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn);
111 static void connection_dir_download_cert_failed(
112 dir_connection_t *conn, int status_code);
113 static void connection_dir_retry_bridges(smartlist_t *descs);
114 static void dir_routerdesc_download_failed(smartlist_t *failed,
115 int status_code,
116 int router_purpose,
117 int was_extrainfo,
118 int was_descriptor_digests);
119 static void dir_microdesc_download_failed(smartlist_t *failed,
120 int status_code);
121 static int client_likes_consensus(const struct consensus_cache_entry_t *ent,
122 const char *want_url);
124 static void connection_dir_close_consensus_fetches(
125 dir_connection_t *except_this_one, const char *resource);
127 /********* START VARIABLES **********/
129 /** How far in the future do we allow a directory server to tell us it is
130 * before deciding that one of us has the wrong time? */
131 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
133 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
134 #define X_OR_DIFF_FROM_CONSENSUS_HEADER "X-Or-Diff-From-Consensus: "
136 /** HTTP cache control: how long do we tell proxies they can cache each
137 * kind of document we serve? */
138 #define FULL_DIR_CACHE_LIFETIME (60*60)
139 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
140 #define DIRPORTFRONTPAGE_CACHE_LIFETIME (20*60)
141 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
142 #define ROUTERDESC_CACHE_LIFETIME (30*60)
143 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
144 #define ROBOTS_CACHE_LIFETIME (24*60*60)
145 #define MICRODESC_CACHE_LIFETIME (48*60*60)
147 /********* END VARIABLES ************/
149 /** Return false if the directory purpose <b>dir_purpose</b>
150 * does not require an anonymous (three-hop) connection.
152 * Return true 1) by default, 2) if all directory actions have
153 * specifically been configured to be over an anonymous connection,
154 * or 3) if the router is a bridge */
156 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
157 const char *resource)
159 if (get_options()->AllDirActionsPrivate)
160 return 1;
162 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
163 if (dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC
164 && resource && !strcmp(resource, "authority.z")) {
165 /* We are asking a bridge for its own descriptor. That doesn't need
166 anonymity. */
167 return 0;
169 /* Assume all other bridge stuff needs anonymity. */
170 return 1; /* if no circuits yet, this might break bootstrapping, but it's
171 * needed to be safe. */
174 switch (dir_purpose)
176 case DIR_PURPOSE_UPLOAD_DIR:
177 case DIR_PURPOSE_UPLOAD_VOTE:
178 case DIR_PURPOSE_UPLOAD_SIGNATURES:
179 case DIR_PURPOSE_FETCH_STATUS_VOTE:
180 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
181 case DIR_PURPOSE_FETCH_CONSENSUS:
182 case DIR_PURPOSE_FETCH_CERTIFICATE:
183 case DIR_PURPOSE_FETCH_SERVERDESC:
184 case DIR_PURPOSE_FETCH_EXTRAINFO:
185 case DIR_PURPOSE_FETCH_MICRODESC:
186 return 0;
187 case DIR_PURPOSE_HAS_FETCHED_HSDESC:
188 case DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2:
189 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
190 case DIR_PURPOSE_FETCH_RENDDESC_V2:
191 case DIR_PURPOSE_FETCH_HSDESC:
192 case DIR_PURPOSE_UPLOAD_HSDESC:
193 return 1;
194 case DIR_PURPOSE_SERVER:
195 default:
196 log_warn(LD_BUG, "Called with dir_purpose=%d, router_purpose=%d",
197 dir_purpose, router_purpose);
198 tor_assert_nonfatal_unreached();
199 return 1; /* Assume it needs anonymity; better safe than sorry. */
203 /** Return a newly allocated string describing <b>auth</b>. Only describes
204 * authority features. */
205 STATIC char *
206 authdir_type_to_string(dirinfo_type_t auth)
208 char *result;
209 smartlist_t *lst = smartlist_new();
210 if (auth & V3_DIRINFO)
211 smartlist_add(lst, (void*)"V3");
212 if (auth & BRIDGE_DIRINFO)
213 smartlist_add(lst, (void*)"Bridge");
214 if (smartlist_len(lst)) {
215 result = smartlist_join_strings(lst, ", ", 0, NULL);
216 } else {
217 result = tor_strdup("[Not an authority]");
219 smartlist_free(lst);
220 return result;
223 /** Return a string describing a given directory connection purpose. */
224 STATIC const char *
225 dir_conn_purpose_to_string(int purpose)
227 switch (purpose)
229 case DIR_PURPOSE_UPLOAD_DIR:
230 return "server descriptor upload";
231 case DIR_PURPOSE_UPLOAD_VOTE:
232 return "server vote upload";
233 case DIR_PURPOSE_UPLOAD_SIGNATURES:
234 return "consensus signature upload";
235 case DIR_PURPOSE_FETCH_SERVERDESC:
236 return "server descriptor fetch";
237 case DIR_PURPOSE_FETCH_EXTRAINFO:
238 return "extra-info fetch";
239 case DIR_PURPOSE_FETCH_CONSENSUS:
240 return "consensus network-status fetch";
241 case DIR_PURPOSE_FETCH_CERTIFICATE:
242 return "authority cert fetch";
243 case DIR_PURPOSE_FETCH_STATUS_VOTE:
244 return "status vote fetch";
245 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
246 return "consensus signature fetch";
247 case DIR_PURPOSE_FETCH_RENDDESC_V2:
248 return "hidden-service v2 descriptor fetch";
249 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
250 return "hidden-service v2 descriptor upload";
251 case DIR_PURPOSE_FETCH_HSDESC:
252 return "hidden-service descriptor fetch";
253 case DIR_PURPOSE_UPLOAD_HSDESC:
254 return "hidden-service descriptor upload";
255 case DIR_PURPOSE_FETCH_MICRODESC:
256 return "microdescriptor fetch";
259 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
260 return "(unknown)";
263 /** Return the requisite directory information types. */
264 STATIC dirinfo_type_t
265 dir_fetch_type(int dir_purpose, int router_purpose, const char *resource)
267 dirinfo_type_t type;
268 switch (dir_purpose) {
269 case DIR_PURPOSE_FETCH_EXTRAINFO:
270 type = EXTRAINFO_DIRINFO;
271 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
272 type |= BRIDGE_DIRINFO;
273 else
274 type |= V3_DIRINFO;
275 break;
276 case DIR_PURPOSE_FETCH_SERVERDESC:
277 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
278 type = BRIDGE_DIRINFO;
279 else
280 type = V3_DIRINFO;
281 break;
282 case DIR_PURPOSE_FETCH_STATUS_VOTE:
283 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
284 case DIR_PURPOSE_FETCH_CERTIFICATE:
285 type = V3_DIRINFO;
286 break;
287 case DIR_PURPOSE_FETCH_CONSENSUS:
288 type = V3_DIRINFO;
289 if (resource && !strcmp(resource, "microdesc"))
290 type |= MICRODESC_DIRINFO;
291 break;
292 case DIR_PURPOSE_FETCH_MICRODESC:
293 type = MICRODESC_DIRINFO;
294 break;
295 default:
296 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
297 type = NO_DIRINFO;
298 break;
300 return type;
303 /** Return true iff <b>identity_digest</b> is the digest of a router which
304 * says that it caches extrainfos. (If <b>is_authority</b> we always
305 * believe that to be true.) */
307 router_supports_extrainfo(const char *identity_digest, int is_authority)
309 const node_t *node = node_get_by_id(identity_digest);
311 if (node && node->ri) {
312 if (node->ri->caches_extra_info)
313 return 1;
315 if (is_authority) {
316 return 1;
318 return 0;
321 /** Return true iff any trusted directory authority has accepted our
322 * server descriptor.
324 * We consider any authority sufficient because waiting for all of
325 * them means it never happens while any authority is down; we don't
326 * go for something more complex in the middle (like \>1/3 or \>1/2 or
327 * \>=1/2) because that doesn't seem necessary yet.
330 directories_have_accepted_server_descriptor(void)
332 const smartlist_t *servers = router_get_trusted_dir_servers();
333 const or_options_t *options = get_options();
334 SMARTLIST_FOREACH(servers, dir_server_t *, d, {
335 if ((d->type & options->PublishServerDescriptor_) &&
336 d->has_accepted_serverdesc) {
337 return 1;
340 return 0;
343 /** Start a connection to every suitable directory authority, using
344 * connection purpose <b>dir_purpose</b> and uploading <b>payload</b>
345 * (of length <b>payload_len</b>). The dir_purpose should be one of
346 * 'DIR_PURPOSE_UPLOAD_{DIR|VOTE|SIGNATURES}'.
348 * <b>router_purpose</b> describes the type of descriptor we're
349 * publishing, if we're publishing a descriptor -- e.g. general or bridge.
351 * <b>type</b> specifies what sort of dir authorities (V3,
352 * BRIDGE, etc) we should upload to.
354 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
355 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
356 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
357 * to all authorities, and the extra-info document to all authorities that
358 * support it.
360 void
361 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
362 dirinfo_type_t type,
363 const char *payload,
364 size_t payload_len, size_t extrainfo_len)
366 const or_options_t *options = get_options();
367 dir_indirection_t indirection;
368 const smartlist_t *dirservers = router_get_trusted_dir_servers();
369 int found = 0;
370 const int exclude_self = (dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
371 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES);
372 tor_assert(dirservers);
373 /* This tries dirservers which we believe to be down, but ultimately, that's
374 * harmless, and we may as well err on the side of getting things uploaded.
376 SMARTLIST_FOREACH_BEGIN(dirservers, dir_server_t *, ds) {
377 routerstatus_t *rs = &(ds->fake_status);
378 size_t upload_len = payload_len;
380 if ((type & ds->type) == 0)
381 continue;
383 if (exclude_self && router_digest_is_me(ds->digest)) {
384 /* we don't upload to ourselves, but at least there's now at least
385 * one authority of this type that has what we wanted to upload. */
386 found = 1;
387 continue;
390 if (options->StrictNodes &&
391 routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) {
392 log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
393 "it's in our ExcludedNodes list and StrictNodes is set. "
394 "Skipping.",
395 ds->nickname,
396 dir_conn_purpose_to_string(dir_purpose));
397 continue;
400 found = 1; /* at least one authority of this type was listed */
401 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
402 ds->has_accepted_serverdesc = 0;
404 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
405 upload_len += extrainfo_len;
406 log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
407 (int) extrainfo_len);
409 if (purpose_needs_anonymity(dir_purpose, router_purpose, NULL)) {
410 indirection = DIRIND_ANONYMOUS;
411 } else if (!fascist_firewall_allows_dir_server(ds,
412 FIREWALL_DIR_CONNECTION,
413 0)) {
414 if (fascist_firewall_allows_dir_server(ds, FIREWALL_OR_CONNECTION, 0))
415 indirection = DIRIND_ONEHOP;
416 else
417 indirection = DIRIND_ANONYMOUS;
418 } else {
419 indirection = DIRIND_DIRECT_CONN;
422 directory_request_t *req = directory_request_new(dir_purpose);
423 directory_request_set_routerstatus(req, rs);
424 directory_request_set_router_purpose(req, router_purpose);
425 directory_request_set_indirection(req, indirection);
426 directory_request_set_payload(req, payload, upload_len);
427 directory_initiate_request(req);
428 directory_request_free(req);
429 } SMARTLIST_FOREACH_END(ds);
430 if (!found) {
431 char *s = authdir_type_to_string(type);
432 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
433 "of type '%s', but no authorities of that type listed!", s);
434 tor_free(s);
438 /** Return true iff, according to the values in <b>options</b>, we should be
439 * using directory guards for direct downloads of directory information. */
440 STATIC int
441 should_use_directory_guards(const or_options_t *options)
443 /* Public (non-bridge) servers never use directory guards. */
444 if (public_server_mode(options))
445 return 0;
446 /* If guards are disabled, we can't use directory guards.
448 if (!options->UseEntryGuards)
449 return 0;
450 /* If we're configured to fetch directory info aggressively or of a
451 * nonstandard type, don't use directory guards. */
452 if (options->DownloadExtraInfo || options->FetchDirInfoEarly ||
453 options->FetchDirInfoExtraEarly || options->FetchUselessDescriptors)
454 return 0;
455 return 1;
458 /** Pick an unconstrained directory server from among our guards, the latest
459 * networkstatus, or the fallback dirservers, for use in downloading
460 * information of type <b>type</b>, and return its routerstatus. */
461 static const routerstatus_t *
462 directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags,
463 uint8_t dir_purpose,
464 circuit_guard_state_t **guard_state_out)
466 const routerstatus_t *rs = NULL;
467 const or_options_t *options = get_options();
469 if (options->UseBridges)
470 log_warn(LD_BUG, "Called when we have UseBridges set.");
472 if (should_use_directory_guards(options)) {
473 const node_t *node = guards_choose_dirguard(guard_state_out);
474 if (node)
475 rs = node->rs;
476 } else {
477 /* anybody with a non-zero dirport will do */
478 rs = router_pick_directory_server(type, pds_flags);
480 if (!rs) {
481 log_info(LD_DIR, "No router found for %s; falling back to "
482 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
483 rs = router_pick_fallback_dirserver(type, pds_flags);
486 return rs;
490 * Set the extra fields in <b>req</b> that are used when requesting a
491 * consensus of type <b>resource</b>.
493 * Right now, these fields are if-modified-since and x-or-diff-from-consensus.
495 static void
496 dir_consensus_request_set_additional_headers(directory_request_t *req,
497 const char *resource)
499 time_t if_modified_since = 0;
500 uint8_t or_diff_from[DIGEST256_LEN];
501 int or_diff_from_is_set = 0;
503 /* DEFAULT_IF_MODIFIED_SINCE_DELAY is 1/20 of the default consensus
504 * period of 1 hour.
506 const int DEFAULT_IF_MODIFIED_SINCE_DELAY = 180;
507 const int32_t DEFAULT_TRY_DIFF_FOR_CONSENSUS_NEWER = 72;
508 const int32_t MIN_TRY_DIFF_FOR_CONSENSUS_NEWER = 0;
509 const int32_t MAX_TRY_DIFF_FOR_CONSENSUS_NEWER = 8192;
510 const char TRY_DIFF_FOR_CONSENSUS_NEWER_NAME[] =
511 "try-diff-for-consensus-newer-than";
513 int flav = FLAV_NS;
514 if (resource)
515 flav = networkstatus_parse_flavor_name(resource);
517 int32_t max_age_for_diff = 3600 *
518 networkstatus_get_param(NULL,
519 TRY_DIFF_FOR_CONSENSUS_NEWER_NAME,
520 DEFAULT_TRY_DIFF_FOR_CONSENSUS_NEWER,
521 MIN_TRY_DIFF_FOR_CONSENSUS_NEWER,
522 MAX_TRY_DIFF_FOR_CONSENSUS_NEWER);
524 if (flav != -1) {
525 /* IF we have a parsed consensus of this type, we can do an
526 * if-modified-time based on it. */
527 networkstatus_t *v;
528 v = networkstatus_get_latest_consensus_by_flavor(flav);
529 if (v) {
530 /* In networks with particularly short V3AuthVotingIntervals,
531 * ask for the consensus if it's been modified since half the
532 * V3AuthVotingInterval of the most recent consensus. */
533 time_t ims_delay = DEFAULT_IF_MODIFIED_SINCE_DELAY;
534 if (v->fresh_until > v->valid_after
535 && ims_delay > (v->fresh_until - v->valid_after)/2) {
536 ims_delay = (v->fresh_until - v->valid_after)/2;
538 if_modified_since = v->valid_after + ims_delay;
539 if (v->valid_after >= approx_time() - max_age_for_diff) {
540 memcpy(or_diff_from, v->digest_sha3_as_signed, DIGEST256_LEN);
541 or_diff_from_is_set = 1;
544 } else {
545 /* Otherwise it might be a consensus we don't parse, but which we
546 * do cache. Look at the cached copy, perhaps. */
547 cached_dir_t *cd = dirserv_get_consensus(resource);
548 /* We have no method of determining the voting interval from an
549 * unparsed consensus, so we use the default. */
550 if (cd) {
551 if_modified_since = cd->published + DEFAULT_IF_MODIFIED_SINCE_DELAY;
552 if (cd->published >= approx_time() - max_age_for_diff) {
553 memcpy(or_diff_from, cd->digest_sha3_as_signed, DIGEST256_LEN);
554 or_diff_from_is_set = 1;
559 if (if_modified_since > 0)
560 directory_request_set_if_modified_since(req, if_modified_since);
561 if (or_diff_from_is_set) {
562 char hex[HEX_DIGEST256_LEN + 1];
563 base16_encode(hex, sizeof(hex),
564 (const char*)or_diff_from, sizeof(or_diff_from));
565 directory_request_add_header(req, X_OR_DIFF_FROM_CONSENSUS_HEADER, hex);
569 /** Start a connection to a random running directory server, using
570 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
571 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
572 * Use <b>pds_flags</b> as arguments to router_pick_directory_server()
573 * or router_pick_trusteddirserver().
575 MOCK_IMPL(void,
576 directory_get_from_dirserver,(
577 uint8_t dir_purpose,
578 uint8_t router_purpose,
579 const char *resource,
580 int pds_flags,
581 download_want_authority_t want_authority))
583 const routerstatus_t *rs = NULL;
584 const or_options_t *options = get_options();
585 int prefer_authority = (directory_fetches_from_authorities(options)
586 || want_authority == DL_WANT_AUTHORITY);
587 int require_authority = 0;
588 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose,
589 resource);
590 dirinfo_type_t type = dir_fetch_type(dir_purpose, router_purpose, resource);
592 if (type == NO_DIRINFO)
593 return;
595 if (!options->FetchServerDescriptors)
596 return;
598 circuit_guard_state_t *guard_state = NULL;
599 if (!get_via_tor) {
600 if (options->UseBridges && !(type & BRIDGE_DIRINFO)) {
601 /* We want to ask a running bridge for which we have a descriptor.
603 * When we ask choose_random_entry() for a bridge, we specify what
604 * sort of dir fetch we'll be doing, so it won't return a bridge
605 * that can't answer our question.
607 const node_t *node = guards_choose_dirguard(&guard_state);
608 if (node && node->ri) {
609 /* every bridge has a routerinfo. */
610 routerinfo_t *ri = node->ri;
611 /* clients always make OR connections to bridges */
612 tor_addr_port_t or_ap;
613 directory_request_t *req = directory_request_new(dir_purpose);
614 /* we are willing to use a non-preferred address if we need to */
615 fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0,
616 &or_ap);
617 directory_request_set_or_addr_port(req, &or_ap);
618 directory_request_set_directory_id_digest(req,
619 ri->cache_info.identity_digest);
620 directory_request_set_router_purpose(req, router_purpose);
621 directory_request_set_resource(req, resource);
622 if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS)
623 dir_consensus_request_set_additional_headers(req, resource);
624 directory_request_set_guard_state(req, guard_state);
625 directory_initiate_request(req);
626 directory_request_free(req);
627 } else {
628 if (guard_state) {
629 entry_guard_cancel(&guard_state);
631 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
632 "nodes are available yet.");
635 return;
636 } else {
637 if (prefer_authority || (type & BRIDGE_DIRINFO)) {
638 /* only ask authdirservers, and don't ask myself */
639 rs = router_pick_trusteddirserver(type, pds_flags);
640 if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
641 PDS_NO_EXISTING_MICRODESC_FETCH))) {
642 /* We don't want to fetch from any authorities that we're currently
643 * fetching server descriptors from, and we got no match. Did we
644 * get no match because all the authorities have connections
645 * fetching server descriptors (in which case we should just
646 * return,) or because all the authorities are down or on fire or
647 * unreachable or something (in which case we should go on with
648 * our fallback code)? */
649 pds_flags &= ~(PDS_NO_EXISTING_SERVERDESC_FETCH|
650 PDS_NO_EXISTING_MICRODESC_FETCH);
651 rs = router_pick_trusteddirserver(type, pds_flags);
652 if (rs) {
653 log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
654 "are in use.");
655 return;
658 if (rs == NULL && require_authority) {
659 log_info(LD_DIR, "No authorities were available for %s: will try "
660 "later.", dir_conn_purpose_to_string(dir_purpose));
661 return;
664 if (!rs && !(type & BRIDGE_DIRINFO)) {
665 rs = directory_pick_generic_dirserver(type, pds_flags,
666 dir_purpose,
667 &guard_state);
668 if (!rs)
669 get_via_tor = 1; /* last resort: try routing it via Tor */
674 if (get_via_tor) {
675 /* Never use fascistfirewall; we're going via Tor. */
676 pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
677 rs = router_pick_directory_server(type, pds_flags);
680 /* If we have any hope of building an indirect conn, we know some router
681 * descriptors. If (rs==NULL), we can't build circuits anyway, so
682 * there's no point in falling back to the authorities in this case. */
683 if (rs) {
684 const dir_indirection_t indirection =
685 get_via_tor ? DIRIND_ANONYMOUS : DIRIND_ONEHOP;
686 directory_request_t *req = directory_request_new(dir_purpose);
687 directory_request_set_routerstatus(req, rs);
688 directory_request_set_router_purpose(req, router_purpose);
689 directory_request_set_indirection(req, indirection);
690 directory_request_set_resource(req, resource);
691 if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS)
692 dir_consensus_request_set_additional_headers(req, resource);
693 if (guard_state)
694 directory_request_set_guard_state(req, guard_state);
695 directory_initiate_request(req);
696 directory_request_free(req);
697 } else {
698 log_notice(LD_DIR,
699 "While fetching directory info, "
700 "no running dirservers known. Will try again later. "
701 "(purpose %d)", dir_purpose);
702 if (!purpose_needs_anonymity(dir_purpose, router_purpose, resource)) {
703 /* remember we tried them all and failed. */
704 directory_all_unreachable(time(NULL));
709 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
710 * directory authority other than ourself. Only for use by authorities when
711 * searching for missing information while voting. */
712 void
713 directory_get_from_all_authorities(uint8_t dir_purpose,
714 uint8_t router_purpose,
715 const char *resource)
717 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
718 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
720 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
721 dir_server_t *, ds) {
722 if (router_digest_is_me(ds->digest))
723 continue;
724 if (!(ds->type & V3_DIRINFO))
725 continue;
726 const routerstatus_t *rs = &ds->fake_status;
727 directory_request_t *req = directory_request_new(dir_purpose);
728 directory_request_set_routerstatus(req, rs);
729 directory_request_set_router_purpose(req, router_purpose);
730 directory_request_set_resource(req, resource);
731 directory_initiate_request(req);
732 directory_request_free(req);
733 } SMARTLIST_FOREACH_END(ds);
736 /** Return true iff <b>ind</b> requires a multihop circuit. */
737 static int
738 dirind_is_anon(dir_indirection_t ind)
740 return ind == DIRIND_ANON_DIRPORT || ind == DIRIND_ANONYMOUS;
743 /* Choose reachable OR and Dir addresses and ports from status, copying them
744 * into use_or_ap and use_dir_ap. If indirection is anonymous, then we're
745 * connecting via another relay, so choose the primary IPv4 address and ports.
747 * status should have at least one reachable address, if we can't choose a
748 * reachable address, warn and return -1. Otherwise, return 0.
750 static int
751 directory_choose_address_routerstatus(const routerstatus_t *status,
752 dir_indirection_t indirection,
753 tor_addr_port_t *use_or_ap,
754 tor_addr_port_t *use_dir_ap)
756 tor_assert(status != NULL);
757 tor_assert(use_or_ap != NULL);
758 tor_assert(use_dir_ap != NULL);
760 const or_options_t *options = get_options();
761 int have_or = 0, have_dir = 0;
763 /* We expect status to have at least one reachable address if we're
764 * connecting to it directly.
766 * Therefore, we can simply use the other address if the one we want isn't
767 * allowed by the firewall.
769 * (When Tor uploads and downloads a hidden service descriptor, it uses
770 * DIRIND_ANONYMOUS, except for Tor2Web, which uses DIRIND_ONEHOP.
771 * So this code will only modify the address for Tor2Web's HS descriptor
772 * fetches. Even Single Onion Servers (NYI) use DIRIND_ANONYMOUS, to avoid
773 * HSDirs denying service by rejecting descriptors.)
776 /* Initialise the OR / Dir addresses */
777 tor_addr_make_null(&use_or_ap->addr, AF_UNSPEC);
778 use_or_ap->port = 0;
779 tor_addr_make_null(&use_dir_ap->addr, AF_UNSPEC);
780 use_dir_ap->port = 0;
782 /* ORPort connections */
783 if (indirection == DIRIND_ANONYMOUS) {
784 if (status->addr) {
785 /* Since we're going to build a 3-hop circuit and ask the 2nd relay
786 * to extend to this address, always use the primary (IPv4) OR address */
787 tor_addr_from_ipv4h(&use_or_ap->addr, status->addr);
788 use_or_ap->port = status->or_port;
789 have_or = 1;
791 } else if (indirection == DIRIND_ONEHOP) {
792 /* We use an IPv6 address if we have one and we prefer it.
793 * Use the preferred address and port if they are reachable, otherwise,
794 * use the alternate address and port (if any).
796 have_or = fascist_firewall_choose_address_rs(status,
797 FIREWALL_OR_CONNECTION, 0,
798 use_or_ap);
801 /* DirPort connections
802 * DIRIND_ONEHOP uses ORPort, but may fall back to the DirPort on relays */
803 if (indirection == DIRIND_DIRECT_CONN ||
804 indirection == DIRIND_ANON_DIRPORT ||
805 (indirection == DIRIND_ONEHOP
806 && !directory_must_use_begindir(options))) {
807 have_dir = fascist_firewall_choose_address_rs(status,
808 FIREWALL_DIR_CONNECTION, 0,
809 use_dir_ap);
812 /* We rejected all addresses in the relay's status. This means we can't
813 * connect to it. */
814 if (!have_or && !have_dir) {
815 static int logged_backtrace = 0;
816 log_info(LD_BUG, "Rejected all OR and Dir addresses from %s when "
817 "launching an outgoing directory connection to: IPv4 %s OR %d "
818 "Dir %d IPv6 %s OR %d Dir %d", routerstatus_describe(status),
819 fmt_addr32(status->addr), status->or_port,
820 status->dir_port, fmt_addr(&status->ipv6_addr),
821 status->ipv6_orport, status->dir_port);
822 if (!logged_backtrace) {
823 log_backtrace(LOG_INFO, LD_BUG, "Addresses came from");
824 logged_backtrace = 1;
826 return -1;
829 return 0;
832 /** Return true iff <b>conn</b> is the client side of a directory connection
833 * we launched to ourself in order to determine the reachability of our
834 * dir_port. */
835 static int
836 directory_conn_is_self_reachability_test(dir_connection_t *conn)
838 if (conn->requested_resource &&
839 !strcmpstart(conn->requested_resource,"authority")) {
840 const routerinfo_t *me = router_get_my_routerinfo();
841 if (me &&
842 router_digest_is_me(conn->identity_digest) &&
843 tor_addr_eq_ipv4h(&conn->base_.addr, me->addr) && /*XXXX prop 118*/
844 me->dir_port == conn->base_.port)
845 return 1;
847 return 0;
850 /** Called when we are unable to complete the client's request to a directory
851 * server due to a network error: Mark the router as down and try again if
852 * possible.
854 static void
855 connection_dir_request_failed(dir_connection_t *conn)
857 if (conn->guard_state) {
858 /* We haven't seen a success on this guard state, so consider it to have
859 * failed. */
860 entry_guard_failed(&conn->guard_state);
862 if (directory_conn_is_self_reachability_test(conn)) {
863 return; /* this was a test fetch. don't retry. */
865 if (!entry_list_is_constrained(get_options()))
866 router_set_status(conn->identity_digest, 0); /* don't try this one again */
867 if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
868 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
869 log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
870 "directory server at '%s'; retrying",
871 conn->base_.address);
872 if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
873 connection_dir_bridge_routerdesc_failed(conn);
874 connection_dir_download_routerdesc_failed(conn);
875 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
876 if (conn->requested_resource)
877 networkstatus_consensus_download_failed(0, conn->requested_resource);
878 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
879 log_info(LD_DIR, "Giving up on certificate fetch from directory server "
880 "at '%s'; retrying",
881 conn->base_.address);
882 connection_dir_download_cert_failed(conn, 0);
883 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
884 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
885 conn->base_.address);
886 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
887 log_info(LD_DIR, "Giving up downloading votes from '%s'",
888 conn->base_.address);
889 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
890 log_info(LD_DIR, "Giving up on downloading microdescriptors from "
891 "directory server at '%s'; will retry", conn->base_.address);
892 connection_dir_download_routerdesc_failed(conn);
896 /** Helper: Attempt to fetch directly the descriptors of each bridge
897 * listed in <b>failed</b>.
899 static void
900 connection_dir_retry_bridges(smartlist_t *descs)
902 char digest[DIGEST_LEN];
903 SMARTLIST_FOREACH(descs, const char *, cp,
905 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) != DIGEST_LEN) {
906 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
907 escaped(cp));
908 continue;
910 retry_bridge_descriptor_fetch_directly(digest);
914 /** Called when an attempt to download one or more router descriptors
915 * or extra-info documents on connection <b>conn</b> failed.
917 static void
918 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
920 /* No need to increment the failure count for routerdescs, since
921 * it's not their fault. */
923 /* No need to relaunch descriptor downloads here: we already do it
924 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
925 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
926 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
927 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
929 (void) conn;
932 /** Called when an attempt to download a bridge's routerdesc from
933 * one of the authorities failed due to a network error. If
934 * possible attempt to download descriptors from the bridge directly.
936 static void
937 connection_dir_bridge_routerdesc_failed(dir_connection_t *conn)
939 smartlist_t *which = NULL;
941 /* Requests for bridge descriptors are in the form 'fp/', so ignore
942 anything else. */
943 if (!conn->requested_resource || strcmpstart(conn->requested_resource,"fp/"))
944 return;
946 which = smartlist_new();
947 dir_split_resource_into_fingerprints(conn->requested_resource
948 + strlen("fp/"),
949 which, NULL, 0);
951 tor_assert(conn->base_.purpose != DIR_PURPOSE_FETCH_EXTRAINFO);
952 if (smartlist_len(which)) {
953 connection_dir_retry_bridges(which);
954 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
956 smartlist_free(which);
959 /** Called when an attempt to fetch a certificate fails. */
960 static void
961 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
963 const char *fp_pfx = "fp/";
964 const char *fpsk_pfx = "fp-sk/";
965 smartlist_t *failed;
966 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
968 if (!conn->requested_resource)
969 return;
970 failed = smartlist_new();
972 * We have two cases download by fingerprint (resource starts
973 * with "fp/") or download by fingerprint/signing key pair
974 * (resource starts with "fp-sk/").
976 if (!strcmpstart(conn->requested_resource, fp_pfx)) {
977 /* Download by fingerprint case */
978 dir_split_resource_into_fingerprints(conn->requested_resource +
979 strlen(fp_pfx),
980 failed, NULL, DSR_HEX);
981 SMARTLIST_FOREACH_BEGIN(failed, char *, cp) {
982 /* Null signing key digest indicates download by fp only */
983 authority_cert_dl_failed(cp, NULL, status);
984 tor_free(cp);
985 } SMARTLIST_FOREACH_END(cp);
986 } else if (!strcmpstart(conn->requested_resource, fpsk_pfx)) {
987 /* Download by (fp,sk) pairs */
988 dir_split_resource_into_fingerprint_pairs(conn->requested_resource +
989 strlen(fpsk_pfx), failed);
990 SMARTLIST_FOREACH_BEGIN(failed, fp_pair_t *, cp) {
991 authority_cert_dl_failed(cp->first, cp->second, status);
992 tor_free(cp);
993 } SMARTLIST_FOREACH_END(cp);
994 } else {
995 log_warn(LD_DIR,
996 "Don't know what to do with failure for cert fetch %s",
997 conn->requested_resource);
1000 smartlist_free(failed);
1002 update_certificate_downloads(time(NULL));
1005 /* Should this tor instance only use begindir for all its directory requests?
1008 directory_must_use_begindir(const or_options_t *options)
1010 /* Clients, onion services, and bridges must use begindir,
1011 * relays and authorities do not have to */
1012 return !public_server_mode(options);
1015 struct directory_request_t {
1017 * These fields specify which directory we're contacting. Routerstatus,
1018 * if present, overrides the other fields.
1020 * @{ */
1021 tor_addr_port_t or_addr_port;
1022 tor_addr_port_t dir_addr_port;
1023 char digest[DIGEST_LEN];
1025 const routerstatus_t *routerstatus;
1026 /** @} */
1027 /** One of DIR_PURPOSE_* other than DIR_PURPOSE_SERVER. Describes what
1028 * kind of operation we'll be doing (upload/download), and of what kind
1029 * of document. */
1030 uint8_t dir_purpose;
1031 /** One of ROUTER_PURPOSE_*; used for uploads and downloads of routerinfo
1032 * and extrainfo docs. */
1033 uint8_t router_purpose;
1034 /** Enum: determines whether to anonymize, and whether to use dirport or
1035 * orport. */
1036 dir_indirection_t indirection;
1037 /** Alias to the variable part of the URL for this request */
1038 const char *resource;
1039 /** Alias to the payload to upload (if any) */
1040 const char *payload;
1041 /** Number of bytes to upload from payload</b> */
1042 size_t payload_len;
1043 /** Value to send in an if-modified-since header, or 0 for none. */
1044 time_t if_modified_since;
1045 /** Hidden-service-specific information v2. */
1046 const rend_data_t *rend_query;
1047 /** Extra headers to append to the request */
1048 config_line_t *additional_headers;
1049 /** Hidden-service-specific information for v3+. */
1050 const hs_ident_dir_conn_t *hs_ident;
1051 /** Used internally to directory.c: gets informed when the attempt to
1052 * connect to the directory succeeds or fails, if that attempt bears on the
1053 * directory's usability as a directory guard. */
1054 circuit_guard_state_t *guard_state;
1057 /** Evaluate the situation and decide if we should use an encrypted
1058 * "begindir-style" connection for this directory request.
1059 * 0) If there is no DirPort, yes.
1060 * 1) If or_port is 0, or it's a direct conn and or_port is firewalled
1061 * or we're a dir mirror, no.
1062 * 2) If we prefer to avoid begindir conns, and we're not fetching or
1063 * publishing a bridge relay descriptor, no.
1064 * 3) Else yes.
1065 * If returning 0, return in *reason why we can't use begindir.
1066 * reason must not be NULL.
1068 static int
1069 directory_command_should_use_begindir(const or_options_t *options,
1070 const directory_request_t *req,
1071 const char **reason)
1073 const tor_addr_t *or_addr = &req->or_addr_port.addr;
1074 //const tor_addr_t *dir_addr = &req->dir_addr_port.addr;
1075 const int or_port = req->or_addr_port.port;
1076 const int dir_port = req->dir_addr_port.port;
1078 const dir_indirection_t indirection = req->indirection;
1080 tor_assert(reason);
1081 *reason = NULL;
1083 /* Reasons why we must use begindir */
1084 if (!dir_port) {
1085 *reason = "(using begindir - directory with no DirPort)";
1086 return 1; /* We don't know a DirPort -- must begindir. */
1088 /* Reasons why we can't possibly use begindir */
1089 if (!or_port) {
1090 *reason = "directory with unknown ORPort";
1091 return 0; /* We don't know an ORPort -- no chance. */
1093 if (indirection == DIRIND_DIRECT_CONN ||
1094 indirection == DIRIND_ANON_DIRPORT) {
1095 *reason = "DirPort connection";
1096 return 0;
1098 if (indirection == DIRIND_ONEHOP) {
1099 /* We're firewalled and want a direct OR connection */
1100 if (!fascist_firewall_allows_address_addr(or_addr, or_port,
1101 FIREWALL_OR_CONNECTION, 0, 0)) {
1102 *reason = "ORPort not reachable";
1103 return 0;
1106 /* Reasons why we want to avoid using begindir */
1107 if (indirection == DIRIND_ONEHOP) {
1108 if (!directory_must_use_begindir(options)) {
1109 *reason = "in relay mode";
1110 return 0;
1113 /* DIRIND_ONEHOP on a client, or DIRIND_ANONYMOUS
1115 *reason = "(using begindir)";
1116 return 1;
1120 * Create and return a new directory_request_t with purpose
1121 * <b>dir_purpose</b>.
1123 directory_request_t *
1124 directory_request_new(uint8_t dir_purpose)
1126 tor_assert(dir_purpose >= DIR_PURPOSE_MIN_);
1127 tor_assert(dir_purpose <= DIR_PURPOSE_MAX_);
1128 tor_assert(dir_purpose != DIR_PURPOSE_SERVER);
1129 tor_assert(dir_purpose != DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2);
1130 tor_assert(dir_purpose != DIR_PURPOSE_HAS_FETCHED_HSDESC);
1132 directory_request_t *result = tor_malloc_zero(sizeof(*result));
1133 tor_addr_make_null(&result->or_addr_port.addr, AF_INET);
1134 result->or_addr_port.port = 0;
1135 tor_addr_make_null(&result->dir_addr_port.addr, AF_INET);
1136 result->dir_addr_port.port = 0;
1137 result->dir_purpose = dir_purpose;
1138 result->router_purpose = ROUTER_PURPOSE_GENERAL;
1139 result->indirection = DIRIND_ONEHOP;
1140 return result;
1143 * Release all resources held by <b>req</b>.
1145 void
1146 directory_request_free(directory_request_t *req)
1148 if (req == NULL)
1149 return;
1150 config_free_lines(req->additional_headers);
1151 tor_free(req);
1154 * Set the address and OR port to use for this directory request. If there is
1155 * no OR port, we'll have to connect over the dirport. (If there are both,
1156 * the indirection setting determins which to use.)
1158 void
1159 directory_request_set_or_addr_port(directory_request_t *req,
1160 const tor_addr_port_t *p)
1162 memcpy(&req->or_addr_port, p, sizeof(*p));
1165 * Set the address and dirport to use for this directory request. If there
1166 * is no dirport, we'll have to connect over the OR port. (If there are both,
1167 * the indirection setting determins which to use.)
1169 void
1170 directory_request_set_dir_addr_port(directory_request_t *req,
1171 const tor_addr_port_t *p)
1173 memcpy(&req->dir_addr_port, p, sizeof(*p));
1176 * Set the RSA identity digest of the directory to use for this directory
1177 * request.
1179 void
1180 directory_request_set_directory_id_digest(directory_request_t *req,
1181 const char *digest)
1183 memcpy(req->digest, digest, DIGEST_LEN);
1186 * Set the router purpose associated with uploaded and downloaded router
1187 * descriptors and extrainfo documents in this directory request. The purpose
1188 * must be one of ROUTER_PURPOSE_GENERAL (the default) or
1189 * ROUTER_PURPOSE_BRIDGE.
1191 void
1192 directory_request_set_router_purpose(directory_request_t *req,
1193 uint8_t router_purpose)
1195 tor_assert(router_purpose == ROUTER_PURPOSE_GENERAL ||
1196 router_purpose == ROUTER_PURPOSE_BRIDGE);
1197 // assert that it actually makes sense to set this purpose, given
1198 // the dir_purpose.
1199 req->router_purpose = router_purpose;
1202 * Set the indirection to be used for the directory request. The indirection
1203 * parameter configures whether to connect to a DirPort or ORPort, and whether
1204 * to anonymize the connection. DIRIND_ONEHOP (use ORPort, don't anonymize)
1205 * is the default. See dir_indirection_t for more information.
1207 void
1208 directory_request_set_indirection(directory_request_t *req,
1209 dir_indirection_t indirection)
1211 req->indirection = indirection;
1215 * Set a pointer to the resource to request from a directory. Different
1216 * request types use resources to indicate different components of their URL.
1217 * Note that only an alias to <b>resource</b> is stored, so the
1218 * <b>resource</b> must outlive the request.
1220 void
1221 directory_request_set_resource(directory_request_t *req,
1222 const char *resource)
1224 req->resource = resource;
1227 * Set a pointer to the payload to include with this directory request, along
1228 * with its length. Note that only an alias to <b>payload</b> is stored, so
1229 * the <b>payload</b> must outlive the request.
1231 void
1232 directory_request_set_payload(directory_request_t *req,
1233 const char *payload,
1234 size_t payload_len)
1236 tor_assert(DIR_PURPOSE_IS_UPLOAD(req->dir_purpose));
1238 req->payload = payload;
1239 req->payload_len = payload_len;
1242 * Set an if-modified-since date to send along with the request. The
1243 * default is 0 (meaning, send no if-modified-since header).
1245 void
1246 directory_request_set_if_modified_since(directory_request_t *req,
1247 time_t if_modified_since)
1249 req->if_modified_since = if_modified_since;
1252 /** Include a header of name <b>key</b> with content <b>val</b> in the
1253 * request. Neither may include newlines or other odd characters. Their
1254 * ordering is not currently guaranteed.
1256 * Note that, as elsewhere in this module, header keys include a trailing
1257 * colon and space.
1259 void
1260 directory_request_add_header(directory_request_t *req,
1261 const char *key,
1262 const char *val)
1264 config_line_prepend(&req->additional_headers, key, val);
1267 * Set an object containing HS data to be associated with this request. Note
1268 * that only an alias to <b>query</b> is stored, so the <b>query</b> object
1269 * must outlive the request.
1271 void
1272 directory_request_set_rend_query(directory_request_t *req,
1273 const rend_data_t *query)
1275 if (query) {
1276 tor_assert(req->dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 ||
1277 req->dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2);
1279 req->rend_query = query;
1282 * Set an object containing HS connection identifier to be associated with
1283 * this request. Note that only an alias to <b>ident</b> is stored, so the
1284 * <b>ident</b> object must outlive the request.
1286 void
1287 directory_request_upload_set_hs_ident(directory_request_t *req,
1288 const hs_ident_dir_conn_t *ident)
1290 if (ident) {
1291 tor_assert(req->dir_purpose == DIR_PURPOSE_UPLOAD_HSDESC);
1293 req->hs_ident = ident;
1296 * Set an object containing HS connection identifier to be associated with
1297 * this fetch request. Note that only an alias to <b>ident</b> is stored, so
1298 * the <b>ident</b> object must outlive the request.
1300 void
1301 directory_request_fetch_set_hs_ident(directory_request_t *req,
1302 const hs_ident_dir_conn_t *ident)
1304 if (ident) {
1305 tor_assert(req->dir_purpose == DIR_PURPOSE_FETCH_HSDESC);
1307 req->hs_ident = ident;
1309 /** Set a static circuit_guard_state_t object to affliate with the request in
1310 * <b>req</b>. This object will receive notification when the attempt to
1311 * connect to the guard either succeeds or fails. */
1312 void
1313 directory_request_set_guard_state(directory_request_t *req,
1314 circuit_guard_state_t *state)
1316 req->guard_state = state;
1320 * Internal: Return true if any information for contacting the directory in
1321 * <b>req</b> has been set, other than by the routerstatus. */
1322 static int
1323 directory_request_dir_contact_info_specified(const directory_request_t *req)
1325 /* We only check for ports here, since we don't use an addr unless the port
1326 * is set */
1327 return (req->or_addr_port.port ||
1328 req->dir_addr_port.port ||
1329 ! tor_digest_is_zero(req->digest));
1333 * Set the routerstatus to use for the directory associated with this
1334 * request. If this option is set, then no other function to set the
1335 * directory's address or identity should be called.
1337 void
1338 directory_request_set_routerstatus(directory_request_t *req,
1339 const routerstatus_t *status)
1341 req->routerstatus = status;
1344 * Helper: update the addresses, ports, and identities in <b>req</b>
1345 * from the routerstatus object in <b>req</b>. Return 0 on success.
1346 * On failure, warn and return -1.
1348 static int
1349 directory_request_set_dir_from_routerstatus(directory_request_t *req)
1352 const routerstatus_t *status = req->routerstatus;
1353 if (BUG(status == NULL))
1354 return -1;
1355 const or_options_t *options = get_options();
1356 const node_t *node;
1357 tor_addr_port_t use_or_ap, use_dir_ap;
1358 const int anonymized_connection = dirind_is_anon(req->indirection);
1360 tor_assert(status != NULL);
1362 node = node_get_by_id(status->identity_digest);
1364 /* XXX The below check is wrong: !node means it's not in the consensus,
1365 * but we haven't checked if we have a descriptor for it -- and also,
1366 * we only care about the descriptor if it's a begindir-style anonymized
1367 * connection. */
1368 if (!node && anonymized_connection) {
1369 log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
1370 "don't have its router descriptor.",
1371 routerstatus_describe(status));
1372 return -1;
1375 if (options->ExcludeNodes && options->StrictNodes &&
1376 routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
1377 log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
1378 "it's in our ExcludedNodes list and StrictNodes is set. "
1379 "Skipping. This choice might make your Tor not work.",
1380 routerstatus_describe(status),
1381 dir_conn_purpose_to_string(req->dir_purpose));
1382 return -1;
1385 /* At this point, if we are a client making a direct connection to a
1386 * directory server, we have selected a server that has at least one address
1387 * allowed by ClientUseIPv4/6 and Reachable{"",OR,Dir}Addresses. This
1388 * selection uses the preference in ClientPreferIPv6{OR,Dir}Port, if
1389 * possible. (If UseBridges is set, clients always use IPv6, and prefer it
1390 * by default.)
1392 * Now choose an address that we can use to connect to the directory server.
1394 if (directory_choose_address_routerstatus(status,
1395 req->indirection, &use_or_ap,
1396 &use_dir_ap) < 0) {
1397 return -1;
1400 directory_request_set_or_addr_port(req, &use_or_ap);
1401 directory_request_set_dir_addr_port(req, &use_dir_ap);
1402 directory_request_set_directory_id_digest(req, status->identity_digest);
1403 return 0;
1407 * Launch the provided directory request, configured in <b>request</b>.
1408 * After this function is called, you can free <b>request</b>.
1410 MOCK_IMPL(void,
1411 directory_initiate_request,(directory_request_t *request))
1413 tor_assert(request);
1414 if (request->routerstatus) {
1415 tor_assert_nonfatal(
1416 ! directory_request_dir_contact_info_specified(request));
1417 if (directory_request_set_dir_from_routerstatus(request) < 0) {
1418 return;
1422 const tor_addr_port_t *or_addr_port = &request->or_addr_port;
1423 const tor_addr_port_t *dir_addr_port = &request->dir_addr_port;
1424 const char *digest = request->digest;
1425 const uint8_t dir_purpose = request->dir_purpose;
1426 const uint8_t router_purpose = request->router_purpose;
1427 const dir_indirection_t indirection = request->indirection;
1428 const char *resource = request->resource;
1429 const rend_data_t *rend_query = request->rend_query;
1430 const hs_ident_dir_conn_t *hs_ident = request->hs_ident;
1431 circuit_guard_state_t *guard_state = request->guard_state;
1433 tor_assert(or_addr_port->port || dir_addr_port->port);
1434 tor_assert(digest);
1436 dir_connection_t *conn;
1437 const or_options_t *options = get_options();
1438 int socket_error = 0;
1439 const char *begindir_reason = NULL;
1440 /* Should the connection be to a relay's OR port (and inside that we will
1441 * send our directory request)? */
1442 const int use_begindir =
1443 directory_command_should_use_begindir(options, request, &begindir_reason);
1445 /* Will the connection go via a three-hop Tor circuit? Note that this
1446 * is separate from whether it will use_begindir. */
1447 const int anonymized_connection = dirind_is_anon(indirection);
1449 /* What is the address we want to make the directory request to? If
1450 * we're making a begindir request this is the ORPort of the relay
1451 * we're contacting; if not a begindir request, this is its DirPort.
1452 * Note that if anonymized_connection is true, we won't be initiating
1453 * a connection directly to this address. */
1454 tor_addr_t addr;
1455 tor_addr_copy(&addr, &(use_begindir ? or_addr_port : dir_addr_port)->addr);
1456 uint16_t port = (use_begindir ? or_addr_port : dir_addr_port)->port;
1458 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
1459 anonymized_connection, use_begindir);
1461 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
1463 if (purpose_needs_anonymity(dir_purpose, router_purpose, resource)) {
1464 tor_assert(anonymized_connection ||
1465 rend_non_anonymous_mode_enabled(options));
1468 /* use encrypted begindir connections for everything except relays
1469 * this provides better protection for directory fetches */
1470 if (!use_begindir && directory_must_use_begindir(options)) {
1471 log_warn(LD_BUG, "Client could not use begindir connection: %s",
1472 begindir_reason ? begindir_reason : "(NULL)");
1473 return;
1476 /* ensure that we don't make direct connections when a SOCKS server is
1477 * configured. */
1478 if (!anonymized_connection && !use_begindir && !options->HTTPProxy &&
1479 (options->Socks4Proxy || options->Socks5Proxy)) {
1480 log_warn(LD_DIR, "Cannot connect to a directory server through a "
1481 "SOCKS proxy!");
1482 return;
1485 /* Make sure that the destination addr and port we picked is viable. */
1486 if (!port || tor_addr_is_null(&addr)) {
1487 static int logged_backtrace = 0;
1488 log_warn(LD_DIR,
1489 "Cannot make an outgoing %sconnection without a remote %sPort.",
1490 use_begindir ? "begindir " : "",
1491 use_begindir ? "OR" : "Dir");
1492 if (!logged_backtrace) {
1493 log_backtrace(LOG_INFO, LD_BUG, "Address came from");
1494 logged_backtrace = 1;
1496 return;
1499 conn = dir_connection_new(tor_addr_family(&addr));
1501 /* set up conn so it's got all the data we need to remember */
1502 tor_addr_copy(&conn->base_.addr, &addr);
1503 conn->base_.port = port;
1504 conn->base_.address = tor_addr_to_str_dup(&addr);
1505 memcpy(conn->identity_digest, digest, DIGEST_LEN);
1507 conn->base_.purpose = dir_purpose;
1508 conn->router_purpose = router_purpose;
1510 /* give it an initial state */
1511 conn->base_.state = DIR_CONN_STATE_CONNECTING;
1513 /* decide whether we can learn our IP address from this conn */
1514 /* XXXX This is a bad name for this field now. */
1515 conn->dirconn_direct = !anonymized_connection;
1517 /* copy rendezvous data, if any */
1518 if (rend_query) {
1519 /* We can't have both v2 and v3+ identifier. */
1520 tor_assert_nonfatal(!hs_ident);
1521 conn->rend_data = rend_data_dup(rend_query);
1523 if (hs_ident) {
1524 /* We can't have both v2 and v3+ identifier. */
1525 tor_assert_nonfatal(!rend_query);
1526 conn->hs_ident = hs_ident_dir_conn_dup(hs_ident);
1529 if (!anonymized_connection && !use_begindir) {
1530 /* then we want to connect to dirport directly */
1532 if (options->HTTPProxy) {
1533 tor_addr_copy(&addr, &options->HTTPProxyAddr);
1534 port = options->HTTPProxyPort;
1537 // In this case we should not have picked a directory guard.
1538 if (BUG(guard_state)) {
1539 entry_guard_cancel(&guard_state);
1542 switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr,
1543 port, &socket_error)) {
1544 case -1:
1545 connection_mark_for_close(TO_CONN(conn));
1546 return;
1547 case 1:
1548 /* start flushing conn */
1549 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
1550 /* fall through */
1551 case 0:
1552 /* queue the command on the outbuf */
1553 directory_send_command(conn, 1, request);
1554 connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT);
1555 /* writable indicates finish, readable indicates broken link,
1556 error indicates broken link in windowsland. */
1558 } else {
1559 /* We will use a Tor circuit (maybe 1-hop, maybe 3-hop, maybe with
1560 * begindir, maybe not with begindir) */
1562 entry_connection_t *linked_conn;
1564 /* Anonymized tunneled connections can never share a circuit.
1565 * One-hop directory connections can share circuits with each other
1566 * but nothing else. */
1567 int iso_flags = anonymized_connection ? ISO_STREAM : ISO_SESSIONGRP;
1569 /* If it's an anonymized connection, remember the fact that we
1570 * wanted it for later: maybe we'll want it again soon. */
1571 if (anonymized_connection && use_begindir)
1572 rep_hist_note_used_internal(time(NULL), 0, 1);
1573 else if (anonymized_connection && !use_begindir)
1574 rep_hist_note_used_port(time(NULL), conn->base_.port);
1576 // In this case we should not have a directory guard; we'll
1577 // get a regular guard later when we build the circuit.
1578 if (BUG(anonymized_connection && guard_state)) {
1579 entry_guard_cancel(&guard_state);
1582 conn->guard_state = guard_state;
1584 /* make an AP connection
1585 * populate it and add it at the right state
1586 * hook up both sides
1588 linked_conn =
1589 connection_ap_make_link(TO_CONN(conn),
1590 conn->base_.address, conn->base_.port,
1591 digest,
1592 SESSION_GROUP_DIRCONN, iso_flags,
1593 use_begindir, !anonymized_connection);
1594 if (!linked_conn) {
1595 log_warn(LD_NET,"Making tunnel to dirserver failed.");
1596 connection_mark_for_close(TO_CONN(conn));
1597 return;
1600 if (connection_add(TO_CONN(conn)) < 0) {
1601 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
1602 connection_mark_for_close(TO_CONN(conn));
1603 return;
1605 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
1606 /* queue the command on the outbuf */
1607 directory_send_command(conn, 0, request);
1609 connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
1610 connection_start_reading(ENTRY_TO_CONN(linked_conn));
1614 /** Return true iff anything we say on <b>conn</b> is being encrypted before
1615 * we send it to the client/server. */
1617 connection_dir_is_encrypted(const dir_connection_t *conn)
1619 /* Right now it's sufficient to see if conn is or has been linked, since
1620 * the only thing it could be linked to is an edge connection on a
1621 * circuit, and the only way it could have been unlinked is at the edge
1622 * connection getting closed.
1624 return TO_CONN(conn)->linked;
1627 /** Helper for sorting
1629 * sort strings alphabetically
1631 static int
1632 compare_strs_(const void **a, const void **b)
1634 const char *s1 = *a, *s2 = *b;
1635 return strcmp(s1, s2);
1638 #define CONDITIONAL_CONSENSUS_FPR_LEN 3
1639 #if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
1640 #error "conditional consensus fingerprint length is larger than digest length"
1641 #endif
1643 /** Return the URL we should use for a consensus download.
1645 * Use the "conditional consensus downloading" feature described in
1646 * dir-spec.txt, i.e.
1647 * GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
1649 * If 'resource' is provided, it is the name of a consensus flavor to request.
1651 static char *
1652 directory_get_consensus_url(const char *resource)
1654 char *url = NULL;
1655 const char *hyphen, *flavor;
1656 if (resource==NULL || strcmp(resource, "ns")==0) {
1657 flavor = ""; /* Request ns consensuses as "", so older servers will work*/
1658 hyphen = "";
1659 } else {
1660 flavor = resource;
1661 hyphen = "-";
1665 char *authority_id_list;
1666 smartlist_t *authority_digests = smartlist_new();
1668 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
1669 dir_server_t *, ds) {
1670 char *hex;
1671 if (!(ds->type & V3_DIRINFO))
1672 continue;
1674 hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
1675 base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
1676 ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN);
1677 smartlist_add(authority_digests, hex);
1678 } SMARTLIST_FOREACH_END(ds);
1679 smartlist_sort(authority_digests, compare_strs_);
1680 authority_id_list = smartlist_join_strings(authority_digests,
1681 "+", 0, NULL);
1683 tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s/%s.z",
1684 hyphen, flavor, authority_id_list);
1686 SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
1687 smartlist_free(authority_digests);
1688 tor_free(authority_id_list);
1690 return url;
1694 * Copies the ipv6 from source to destination, subject to buffer size limit
1695 * size. If decorate is true, makes sure the copied address is decorated.
1697 static void
1698 copy_ipv6_address(char* destination, const char* source, size_t len,
1699 int decorate) {
1700 tor_assert(destination);
1701 tor_assert(source);
1703 if (decorate && source[0] != '[') {
1704 tor_snprintf(destination, len, "[%s]", source);
1705 } else {
1706 strlcpy(destination, source, len);
1710 /** Queue an appropriate HTTP command for <b>request</b> on
1711 * <b>conn</b>-\>outbuf. If <b>direct</b> is true, we're making a
1712 * non-anonymized connection to the dirport.
1714 static void
1715 directory_send_command(dir_connection_t *conn,
1716 const int direct,
1717 const directory_request_t *req)
1719 tor_assert(req);
1720 const int purpose = req->dir_purpose;
1721 const char *resource = req->resource;
1722 const char *payload = req->payload;
1723 const size_t payload_len = req->payload_len;
1724 const time_t if_modified_since = req->if_modified_since;
1725 const int anonymized_connection = dirind_is_anon(req->indirection);
1727 char proxystring[256];
1728 char hoststring[128];
1729 /* NEEDS to be the same size hoststring.
1730 Will be decorated with brackets around it if it is ipv6. */
1731 char decorated_address[128];
1732 smartlist_t *headers = smartlist_new();
1733 char *url;
1734 char *accept_encoding;
1735 size_t url_len;
1736 char request[8192];
1737 size_t request_len, total_request_len = 0;
1738 const char *httpcommand = NULL;
1740 tor_assert(conn);
1741 tor_assert(conn->base_.type == CONN_TYPE_DIR);
1743 tor_free(conn->requested_resource);
1744 if (resource)
1745 conn->requested_resource = tor_strdup(resource);
1747 /* decorate the ip address if it is ipv6 */
1748 if (strchr(conn->base_.address, ':')) {
1749 copy_ipv6_address(decorated_address, conn->base_.address,
1750 sizeof(decorated_address), 1);
1751 } else {
1752 strlcpy(decorated_address, conn->base_.address, sizeof(decorated_address));
1755 /* come up with a string for which Host: we want */
1756 if (conn->base_.port == 80) {
1757 strlcpy(hoststring, decorated_address, sizeof(hoststring));
1758 } else {
1759 tor_snprintf(hoststring, sizeof(hoststring), "%s:%d",
1760 decorated_address, conn->base_.port);
1763 /* Format if-modified-since */
1764 if (if_modified_since) {
1765 char b[RFC1123_TIME_LEN+1];
1766 format_rfc1123_time(b, if_modified_since);
1767 smartlist_add_asprintf(headers, "If-Modified-Since: %s\r\n", b);
1770 /* come up with some proxy lines, if we're using one. */
1771 if (direct && get_options()->HTTPProxy) {
1772 char *base64_authenticator=NULL;
1773 const char *authenticator = get_options()->HTTPProxyAuthenticator;
1775 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
1776 if (authenticator) {
1777 base64_authenticator = alloc_http_authenticator(authenticator);
1778 if (!base64_authenticator)
1779 log_warn(LD_BUG, "Encoding http authenticator failed");
1781 if (base64_authenticator) {
1782 smartlist_add_asprintf(headers,
1783 "Proxy-Authorization: Basic %s\r\n",
1784 base64_authenticator);
1785 tor_free(base64_authenticator);
1787 } else {
1788 proxystring[0] = 0;
1791 if (! anonymized_connection) {
1792 /* Add Accept-Encoding. */
1793 accept_encoding = accept_encoding_header();
1794 smartlist_add_asprintf(headers, "Accept-Encoding: %s\r\n",
1795 accept_encoding);
1796 tor_free(accept_encoding);
1799 /* Add additional headers, if any */
1801 config_line_t *h;
1802 for (h = req->additional_headers; h; h = h->next) {
1803 smartlist_add_asprintf(headers, "%s%s\r\n", h->key, h->value);
1807 switch (purpose) {
1808 case DIR_PURPOSE_FETCH_CONSENSUS:
1809 /* resource is optional. If present, it's a flavor name */
1810 tor_assert(!payload);
1811 httpcommand = "GET";
1812 url = directory_get_consensus_url(resource);
1813 log_info(LD_DIR, "Downloading consensus from %s using %s",
1814 hoststring, url);
1815 break;
1816 case DIR_PURPOSE_FETCH_CERTIFICATE:
1817 tor_assert(resource);
1818 tor_assert(!payload);
1819 httpcommand = "GET";
1820 tor_asprintf(&url, "/tor/keys/%s", resource);
1821 break;
1822 case DIR_PURPOSE_FETCH_STATUS_VOTE:
1823 tor_assert(resource);
1824 tor_assert(!payload);
1825 httpcommand = "GET";
1826 tor_asprintf(&url, "/tor/status-vote/next/%s.z", resource);
1827 break;
1828 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
1829 tor_assert(!resource);
1830 tor_assert(!payload);
1831 httpcommand = "GET";
1832 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
1833 break;
1834 case DIR_PURPOSE_FETCH_SERVERDESC:
1835 tor_assert(resource);
1836 httpcommand = "GET";
1837 tor_asprintf(&url, "/tor/server/%s", resource);
1838 break;
1839 case DIR_PURPOSE_FETCH_EXTRAINFO:
1840 tor_assert(resource);
1841 httpcommand = "GET";
1842 tor_asprintf(&url, "/tor/extra/%s", resource);
1843 break;
1844 case DIR_PURPOSE_FETCH_MICRODESC:
1845 tor_assert(resource);
1846 httpcommand = "GET";
1847 tor_asprintf(&url, "/tor/micro/%s", resource);
1848 break;
1849 case DIR_PURPOSE_UPLOAD_DIR: {
1850 const char *why = router_get_descriptor_gen_reason();
1851 tor_assert(!resource);
1852 tor_assert(payload);
1853 httpcommand = "POST";
1854 url = tor_strdup("/tor/");
1855 if (why) {
1856 smartlist_add_asprintf(headers, "X-Desc-Gen-Reason: %s\r\n", why);
1858 break;
1860 case DIR_PURPOSE_UPLOAD_VOTE:
1861 tor_assert(!resource);
1862 tor_assert(payload);
1863 httpcommand = "POST";
1864 url = tor_strdup("/tor/post/vote");
1865 break;
1866 case DIR_PURPOSE_UPLOAD_SIGNATURES:
1867 tor_assert(!resource);
1868 tor_assert(payload);
1869 httpcommand = "POST";
1870 url = tor_strdup("/tor/post/consensus-signature");
1871 break;
1872 case DIR_PURPOSE_FETCH_RENDDESC_V2:
1873 tor_assert(resource);
1874 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
1875 tor_assert(!payload);
1876 httpcommand = "GET";
1877 tor_asprintf(&url, "/tor/rendezvous2/%s", resource);
1878 break;
1879 case DIR_PURPOSE_FETCH_HSDESC:
1880 tor_assert(resource);
1881 tor_assert(strlen(resource) <= ED25519_BASE64_LEN);
1882 tor_assert(!payload);
1883 httpcommand = "GET";
1884 tor_asprintf(&url, "/tor/hs/3/%s", resource);
1885 break;
1886 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
1887 tor_assert(!resource);
1888 tor_assert(payload);
1889 httpcommand = "POST";
1890 url = tor_strdup("/tor/rendezvous2/publish");
1891 break;
1892 case DIR_PURPOSE_UPLOAD_HSDESC:
1893 tor_assert(resource);
1894 tor_assert(payload);
1895 httpcommand = "POST";
1896 tor_asprintf(&url, "/tor/hs/%s/publish", resource);
1897 break;
1898 default:
1899 tor_assert(0);
1900 return;
1903 /* warn in the non-tunneled case */
1904 if (direct && (strlen(proxystring) + strlen(url) >= 4096)) {
1905 log_warn(LD_BUG,
1906 "Squid does not like URLs longer than 4095 bytes, and this "
1907 "one is %d bytes long: %s%s",
1908 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
1911 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
1913 request_len = strlen(request);
1914 total_request_len += request_len;
1915 connection_write_to_buf(request, request_len, TO_CONN(conn));
1917 url_len = strlen(url);
1918 total_request_len += url_len;
1919 connection_write_to_buf(url, url_len, TO_CONN(conn));
1920 tor_free(url);
1922 if (!strcmp(httpcommand, "POST") || payload) {
1923 smartlist_add_asprintf(headers, "Content-Length: %lu\r\n",
1924 payload ? (unsigned long)payload_len : 0);
1928 char *header = smartlist_join_strings(headers, "", 0, NULL);
1929 tor_snprintf(request, sizeof(request), " HTTP/1.0\r\nHost: %s\r\n%s\r\n",
1930 hoststring, header);
1931 tor_free(header);
1934 request_len = strlen(request);
1935 total_request_len += request_len;
1936 connection_write_to_buf(request, request_len, TO_CONN(conn));
1938 if (payload) {
1939 /* then send the payload afterwards too */
1940 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
1941 total_request_len += payload_len;
1944 SMARTLIST_FOREACH(headers, char *, h, tor_free(h));
1945 smartlist_free(headers);
1947 log_debug(LD_DIR,
1948 "Sent request to directory server '%s:%d': "
1949 "(purpose: %d, request size: " U64_FORMAT ", "
1950 "payload size: " U64_FORMAT ")",
1951 conn->base_.address, conn->base_.port,
1952 conn->base_.purpose,
1953 U64_PRINTF_ARG(total_request_len),
1954 U64_PRINTF_ARG(payload ? payload_len : 0));
1957 /** Parse an HTTP request string <b>headers</b> of the form
1958 * \verbatim
1959 * "\%s [http[s]://]\%s HTTP/1..."
1960 * \endverbatim
1961 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
1962 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
1963 * so it does. Return 0.
1964 * Otherwise, return -1.
1966 STATIC int
1967 parse_http_url(const char *headers, char **url)
1969 char *s, *start, *tmp;
1971 s = (char *)eat_whitespace_no_nl(headers);
1972 if (!*s) return -1;
1973 s = (char *)find_whitespace(s); /* get past GET/POST */
1974 if (!*s) return -1;
1975 s = (char *)eat_whitespace_no_nl(s);
1976 if (!*s) return -1;
1977 start = s; /* this is it, assuming it's valid */
1978 s = (char *)find_whitespace(start);
1979 if (!*s) return -1;
1981 /* tolerate the http[s] proxy style of putting the hostname in the url */
1982 if (s-start >= 4 && !strcmpstart(start,"http")) {
1983 tmp = start + 4;
1984 if (*tmp == 's')
1985 tmp++;
1986 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
1987 tmp = strchr(tmp+3, '/');
1988 if (tmp && tmp < s) {
1989 log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
1990 start = tmp;
1995 /* Check if the header is well formed (next sequence
1996 * should be HTTP/1.X\r\n). Assumes we're supporting 1.0? */
1998 unsigned minor_ver;
1999 char ch;
2000 char *e = (char *)eat_whitespace_no_nl(s);
2001 if (2 != tor_sscanf(e, "HTTP/1.%u%c", &minor_ver, &ch)) {
2002 return -1;
2004 if (ch != '\r')
2005 return -1;
2008 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
2009 *url = tor_malloc(s - start + 5);
2010 strlcpy(*url,"/tor", s-start+5);
2011 strlcat((*url)+4, start, s-start+1);
2012 } else {
2013 *url = tor_strndup(start, s-start);
2015 return 0;
2018 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
2019 * <b>which</b>. The key should be given with a terminating colon and space;
2020 * this function copies everything after, up to but not including the
2021 * following \\r\\n. */
2022 static char *
2023 http_get_header(const char *headers, const char *which)
2025 const char *cp = headers;
2026 while (cp) {
2027 if (!strcasecmpstart(cp, which)) {
2028 char *eos;
2029 cp += strlen(which);
2030 if ((eos = strchr(cp,'\r')))
2031 return tor_strndup(cp, eos-cp);
2032 else
2033 return tor_strdup(cp);
2035 cp = strchr(cp, '\n');
2036 if (cp)
2037 ++cp;
2039 return NULL;
2042 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
2043 * <b>conn</b>-\>address to describe our best guess of the address that
2044 * originated this HTTP request. */
2045 static void
2046 http_set_address_origin(const char *headers, connection_t *conn)
2048 char *fwd;
2050 fwd = http_get_header(headers, "Forwarded-For: ");
2051 if (!fwd)
2052 fwd = http_get_header(headers, "X-Forwarded-For: ");
2053 if (fwd) {
2054 tor_addr_t toraddr;
2055 if (tor_addr_parse(&toraddr,fwd) == -1 ||
2056 tor_addr_is_internal(&toraddr,0)) {
2057 log_debug(LD_DIR, "Ignoring local/internal IP %s", escaped(fwd));
2058 tor_free(fwd);
2059 return;
2062 tor_free(conn->address);
2063 conn->address = tor_strdup(fwd);
2064 tor_free(fwd);
2068 /** Parse an HTTP response string <b>headers</b> of the form
2069 * \verbatim
2070 * "HTTP/1.\%d \%d\%s\r\n...".
2071 * \endverbatim
2073 * If it's well-formed, assign the status code to *<b>code</b> and
2074 * return 0. Otherwise, return -1.
2076 * On success: If <b>date</b> is provided, set *date to the Date
2077 * header in the http headers, or 0 if no such header is found. If
2078 * <b>compression</b> is provided, set *<b>compression</b> to the
2079 * compression method given in the Content-Encoding header, or 0 if no
2080 * such header is found, or -1 if the value of the header is not
2081 * recognized. If <b>reason</b> is provided, strdup the reason string
2082 * into it.
2085 parse_http_response(const char *headers, int *code, time_t *date,
2086 compress_method_t *compression, char **reason)
2088 unsigned n1, n2;
2089 char datestr[RFC1123_TIME_LEN+1];
2090 smartlist_t *parsed_headers;
2091 tor_assert(headers);
2092 tor_assert(code);
2094 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
2096 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
2097 (n1 != 0 && n1 != 1) ||
2098 (n2 < 100 || n2 >= 600)) {
2099 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
2100 return -1;
2102 *code = n2;
2104 parsed_headers = smartlist_new();
2105 smartlist_split_string(parsed_headers, headers, "\n",
2106 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
2107 if (reason) {
2108 smartlist_t *status_line_elements = smartlist_new();
2109 tor_assert(smartlist_len(parsed_headers));
2110 smartlist_split_string(status_line_elements,
2111 smartlist_get(parsed_headers, 0),
2112 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
2113 tor_assert(smartlist_len(status_line_elements) <= 3);
2114 if (smartlist_len(status_line_elements) == 3) {
2115 *reason = smartlist_get(status_line_elements, 2);
2116 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
2118 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
2119 smartlist_free(status_line_elements);
2121 if (date) {
2122 *date = 0;
2123 SMARTLIST_FOREACH(parsed_headers, const char *, s,
2124 if (!strcmpstart(s, "Date: ")) {
2125 strlcpy(datestr, s+6, sizeof(datestr));
2126 /* This will do nothing on failure, so we don't need to check
2127 the result. We shouldn't warn, since there are many other valid
2128 date formats besides the one we use. */
2129 parse_rfc1123_time(datestr, date);
2130 break;
2133 if (compression) {
2134 const char *enc = NULL;
2135 SMARTLIST_FOREACH(parsed_headers, const char *, s,
2136 if (!strcmpstart(s, "Content-Encoding: ")) {
2137 enc = s+18; break;
2140 if (enc == NULL)
2141 *compression = NO_METHOD;
2142 else {
2143 *compression = compression_method_get_by_name(enc);
2145 if (*compression == UNKNOWN_METHOD)
2146 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
2147 escaped(enc));
2150 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
2151 smartlist_free(parsed_headers);
2153 return 0;
2156 /** Return true iff <b>body</b> doesn't start with a plausible router or
2157 * network-status or microdescriptor opening. This is a sign of possible
2158 * compression. */
2159 static int
2160 body_is_plausible(const char *body, size_t len, int purpose)
2162 int i;
2163 if (len == 0)
2164 return 1; /* empty bodies don't need decompression */
2165 if (len < 32)
2166 return 0;
2167 if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
2168 return (!strcmpstart(body,"onion-key"));
2171 if (!strcmpstart(body,"router") ||
2172 !strcmpstart(body,"network-status"))
2173 return 1;
2174 for (i=0;i<32;++i) {
2175 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
2176 return 0;
2179 return 1;
2182 /** Called when we've just fetched a bunch of router descriptors in
2183 * <b>body</b>. The list <b>which</b>, if present, holds digests for
2184 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
2185 * is true, or identity digests otherwise. Parse the descriptors, validate
2186 * them, and annotate them as having purpose <b>purpose</b> and as having been
2187 * downloaded from <b>source</b>.
2189 * Return the number of routers actually added. */
2190 static int
2191 load_downloaded_routers(const char *body, smartlist_t *which,
2192 int descriptor_digests,
2193 int router_purpose,
2194 const char *source)
2196 char buf[256];
2197 char time_buf[ISO_TIME_LEN+1];
2198 int added = 0;
2199 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
2200 format_iso_time(time_buf, time(NULL));
2201 tor_assert(source);
2203 if (tor_snprintf(buf, sizeof(buf),
2204 "@downloaded-at %s\n"
2205 "@source %s\n"
2206 "%s%s%s", time_buf, escaped(source),
2207 !general ? "@purpose " : "",
2208 !general ? router_purpose_to_string(router_purpose) : "",
2209 !general ? "\n" : "")<0)
2210 return added;
2212 added = router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
2213 descriptor_digests, buf);
2214 if (added && general)
2215 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
2216 count_loading_descriptors_progress());
2217 return added;
2220 static int handle_response_fetch_consensus(dir_connection_t *,
2221 const response_handler_args_t *);
2222 static int handle_response_fetch_certificate(dir_connection_t *,
2223 const response_handler_args_t *);
2224 static int handle_response_fetch_status_vote(dir_connection_t *,
2225 const response_handler_args_t *);
2226 static int handle_response_fetch_detached_signatures(dir_connection_t *,
2227 const response_handler_args_t *);
2228 static int handle_response_fetch_desc(dir_connection_t *,
2229 const response_handler_args_t *);
2230 static int handle_response_fetch_microdesc(dir_connection_t *,
2231 const response_handler_args_t *);
2232 static int handle_response_upload_dir(dir_connection_t *,
2233 const response_handler_args_t *);
2234 static int handle_response_upload_vote(dir_connection_t *,
2235 const response_handler_args_t *);
2236 static int handle_response_upload_signatures(dir_connection_t *,
2237 const response_handler_args_t *);
2238 static int handle_response_fetch_renddesc_v2(dir_connection_t *,
2239 const response_handler_args_t *);
2240 static int handle_response_upload_renddesc_v2(dir_connection_t *,
2241 const response_handler_args_t *);
2242 static int handle_response_upload_hsdesc(dir_connection_t *,
2243 const response_handler_args_t *);
2245 static int
2246 dir_client_decompress_response_body(char **bodyp, size_t *bodylenp,
2247 dir_connection_t *conn,
2248 compress_method_t compression,
2249 int anonymized_connection)
2251 int rv = 0;
2252 const char *body = *bodyp;
2253 size_t body_len = *bodylenp;
2254 int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
2255 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
2256 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
2258 int plausible = body_is_plausible(body, body_len, conn->base_.purpose);
2260 if (plausible && compression == NO_METHOD) {
2261 return 0;
2264 int severity = LOG_DEBUG;
2265 char *new_body = NULL;
2266 size_t new_len = 0;
2267 const char *description1, *description2;
2268 int want_to_try_both = 0;
2269 int tried_both = 0;
2270 compress_method_t guessed = detect_compression_method(body, body_len);
2272 description1 = compression_method_get_human_name(compression);
2274 if (BUG(description1 == NULL))
2275 description1 = compression_method_get_human_name(UNKNOWN_METHOD);
2277 if (guessed == UNKNOWN_METHOD && !plausible)
2278 description2 = "confusing binary junk";
2279 else
2280 description2 = compression_method_get_human_name(guessed);
2282 /* Tell the user if we don't believe what we're told about compression.*/
2283 want_to_try_both = (compression == UNKNOWN_METHOD ||
2284 guessed != compression);
2285 if (want_to_try_both) {
2286 severity = LOG_PROTOCOL_WARN;
2289 tor_log(severity, LD_HTTP,
2290 "HTTP body from server '%s:%d' was labeled as %s, "
2291 "%s it seems to be %s.%s",
2292 conn->base_.address, conn->base_.port, description1,
2293 guessed != compression?"but":"and",
2294 description2,
2295 (compression>0 && guessed>0 && want_to_try_both)?
2296 " Trying both.":"");
2298 /* Try declared compression first if we can.
2299 * tor_compress_supports_method() also returns true for NO_METHOD.
2300 * Ensure that the server is not sending us data compressed using a
2301 * compression method that is not allowed for anonymous connections. */
2302 if (anonymized_connection &&
2303 ! allowed_anonymous_connection_compression_method(compression)) {
2304 warn_disallowed_anonymous_compression_method(compression);
2305 rv = -1;
2306 goto done;
2309 if (tor_compress_supports_method(compression)) {
2310 tor_uncompress(&new_body, &new_len, body, body_len, compression,
2311 !allow_partial, LOG_PROTOCOL_WARN);
2312 if (new_body) {
2313 /* We succeeded with the declared compression method. Great! */
2314 rv = 0;
2315 goto done;
2319 /* Okay, if that didn't work, and we think that it was compressed
2320 * differently, try that. */
2321 if (anonymized_connection &&
2322 ! allowed_anonymous_connection_compression_method(guessed)) {
2323 warn_disallowed_anonymous_compression_method(guessed);
2324 rv = -1;
2325 goto done;
2328 if (tor_compress_supports_method(guessed) &&
2329 compression != guessed) {
2330 tor_uncompress(&new_body, &new_len, body, body_len, guessed,
2331 !allow_partial, LOG_INFO);
2332 tried_both = 1;
2334 /* If we're pretty sure that we have a compressed directory, and
2335 * we didn't manage to uncompress it, then warn and bail. */
2336 if (!plausible && !new_body) {
2337 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
2338 "Unable to decompress HTTP body (tried %s%s%s, server '%s:%d').",
2339 description1,
2340 tried_both?" and ":"",
2341 tried_both?description2:"",
2342 conn->base_.address, conn->base_.port);
2343 rv = -1;
2344 goto done;
2347 done:
2348 if (new_body) {
2349 if (rv == 0) {
2350 /* success! */
2351 tor_free(*bodyp);
2352 *bodyp = new_body;
2353 *bodylenp = new_len;
2354 } else {
2355 tor_free(new_body);
2359 return rv;
2362 /** We are a client, and we've finished reading the server's
2363 * response. Parse it and act appropriately.
2365 * If we're still happy with using this directory server in the future, return
2366 * 0. Otherwise return -1; and the caller should consider trying the request
2367 * again.
2369 * The caller will take care of marking the connection for close.
2371 static int
2372 connection_dir_client_reached_eof(dir_connection_t *conn)
2374 char *body = NULL;
2375 char *headers = NULL;
2376 char *reason = NULL;
2377 size_t body_len = 0;
2378 int status_code;
2379 time_t date_header = 0;
2380 long apparent_skew;
2381 compress_method_t compression;
2382 int skewed = 0;
2383 int rv;
2384 int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
2385 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
2386 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
2387 size_t received_bytes;
2388 const int anonymized_connection =
2389 purpose_needs_anonymity(conn->base_.purpose,
2390 conn->router_purpose,
2391 conn->requested_resource);
2393 received_bytes = connection_get_inbuf_len(TO_CONN(conn));
2395 switch (connection_fetch_from_buf_http(TO_CONN(conn),
2396 &headers, MAX_HEADERS_SIZE,
2397 &body, &body_len, MAX_DIR_DL_SIZE,
2398 allow_partial)) {
2399 case -1: /* overflow */
2400 log_warn(LD_PROTOCOL,
2401 "'fetch' response too large (server '%s:%d'). Closing.",
2402 conn->base_.address, conn->base_.port);
2403 return -1;
2404 case 0:
2405 log_info(LD_HTTP,
2406 "'fetch' response not all here, but we're at eof. Closing.");
2407 return -1;
2408 /* case 1, fall through */
2411 if (parse_http_response(headers, &status_code, &date_header,
2412 &compression, &reason) < 0) {
2413 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
2414 conn->base_.address, conn->base_.port);
2416 rv = -1;
2417 goto done;
2419 if (!reason) reason = tor_strdup("[no reason given]");
2421 tor_log(LOG_DEBUG, LD_DIR,
2422 "Received response from directory server '%s:%d': %d %s "
2423 "(purpose: %d, response size: " U64_FORMAT
2424 #ifdef MEASUREMENTS_21206
2425 ", data cells received: %d, data cells sent: %d"
2426 #endif
2427 ", compression: %d)",
2428 conn->base_.address, conn->base_.port, status_code,
2429 escaped(reason), conn->base_.purpose,
2430 U64_PRINTF_ARG(received_bytes),
2431 #ifdef MEASUREMENTS_21206
2432 conn->data_cells_received, conn->data_cells_sent,
2433 #endif
2434 compression);
2436 if (conn->guard_state) {
2437 /* we count the connection as successful once we can read from it. We do
2438 * not, however, delay use of the circuit here, since it's just for a
2439 * one-hop directory request. */
2440 /* XXXXprop271 note that this will not do the right thing for other
2441 * waiting circuits that would be triggered by this circuit becoming
2442 * complete/usable. But that's ok, I think.
2444 entry_guard_succeeded(&conn->guard_state);
2445 circuit_guard_state_free(conn->guard_state);
2446 conn->guard_state = NULL;
2449 /* now check if it's got any hints for us about our IP address. */
2450 if (conn->dirconn_direct) {
2451 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
2452 if (guess) {
2453 router_new_address_suggestion(guess, conn);
2454 tor_free(guess);
2458 if (date_header > 0) {
2459 /* The date header was written very soon after we sent our request,
2460 * so compute the skew as the difference between sending the request
2461 * and the date header. (We used to check now-date_header, but that's
2462 * inaccurate if we spend a lot of time downloading.)
2464 apparent_skew = conn->base_.timestamp_lastwritten - date_header;
2465 if (labs(apparent_skew)>ALLOW_DIRECTORY_TIME_SKEW) {
2466 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
2467 clock_skew_warning(TO_CONN(conn), apparent_skew, trusted, LD_HTTP,
2468 "directory", "DIRSERV");
2469 skewed = 1; /* don't check the recommended-versions line */
2470 } else {
2471 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
2472 "we are %ld seconds skewed. (That's okay.)", apparent_skew);
2475 (void) skewed; /* skewed isn't used yet. */
2477 if (status_code == 503) {
2478 routerstatus_t *rs;
2479 dir_server_t *ds;
2480 const char *id_digest = conn->identity_digest;
2481 log_info(LD_DIR,"Received http status code %d (%s) from server "
2482 "'%s:%d'. I'll try again soon.",
2483 status_code, escaped(reason), conn->base_.address,
2484 conn->base_.port);
2485 time_t now = approx_time();
2486 if ((rs = router_get_mutable_consensus_status_by_id(id_digest)))
2487 rs->last_dir_503_at = now;
2488 if ((ds = router_get_fallback_dirserver_by_digest(id_digest)))
2489 ds->fake_status.last_dir_503_at = now;
2491 rv = -1;
2492 goto done;
2495 if (dir_client_decompress_response_body(&body, &body_len,
2496 conn, compression, anonymized_connection) < 0) {
2497 rv = -1;
2498 goto done;
2501 response_handler_args_t args;
2502 memset(&args, 0, sizeof(args));
2503 args.status_code = status_code;
2504 args.reason = reason;
2505 args.body = body;
2506 args.body_len = body_len;
2507 args.headers = headers;
2509 switch (conn->base_.purpose) {
2510 case DIR_PURPOSE_FETCH_CONSENSUS:
2511 rv = handle_response_fetch_consensus(conn, &args);
2512 break;
2513 case DIR_PURPOSE_FETCH_CERTIFICATE:
2514 rv = handle_response_fetch_certificate(conn, &args);
2515 break;
2516 case DIR_PURPOSE_FETCH_STATUS_VOTE:
2517 rv = handle_response_fetch_status_vote(conn, &args);
2518 break;
2519 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
2520 rv = handle_response_fetch_detached_signatures(conn, &args);
2521 break;
2522 case DIR_PURPOSE_FETCH_SERVERDESC:
2523 case DIR_PURPOSE_FETCH_EXTRAINFO:
2524 rv = handle_response_fetch_desc(conn, &args);
2525 break;
2526 case DIR_PURPOSE_FETCH_MICRODESC:
2527 rv = handle_response_fetch_microdesc(conn, &args);
2528 break;
2529 case DIR_PURPOSE_FETCH_RENDDESC_V2:
2530 rv = handle_response_fetch_renddesc_v2(conn, &args);
2531 break;
2532 case DIR_PURPOSE_UPLOAD_DIR:
2533 rv = handle_response_upload_dir(conn, &args);
2534 break;
2535 case DIR_PURPOSE_UPLOAD_SIGNATURES:
2536 rv = handle_response_upload_signatures(conn, &args);
2537 break;
2538 case DIR_PURPOSE_UPLOAD_VOTE:
2539 rv = handle_response_upload_vote(conn, &args);
2540 break;
2541 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
2542 rv = handle_response_upload_renddesc_v2(conn, &args);
2543 break;
2544 case DIR_PURPOSE_UPLOAD_HSDESC:
2545 rv = handle_response_upload_hsdesc(conn, &args);
2546 break;
2547 case DIR_PURPOSE_FETCH_HSDESC:
2548 rv = handle_response_fetch_hsdesc_v3(conn, &args);
2549 break;
2550 default:
2551 tor_assert_nonfatal_unreached();
2552 rv = -1;
2553 break;
2556 done:
2557 tor_free(body);
2558 tor_free(headers);
2559 tor_free(reason);
2560 return rv;
2564 * Handler function: processes a response to a request for a networkstatus
2565 * consensus document by checking the consensus, storing it, and marking
2566 * router requests as reachable.
2568 static int
2569 handle_response_fetch_consensus(dir_connection_t *conn,
2570 const response_handler_args_t *args)
2572 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS);
2573 const int status_code = args->status_code;
2574 const char *body = args->body;
2575 const size_t body_len = args->body_len;
2576 const char *reason = args->reason;
2577 const time_t now = approx_time();
2579 const char *consensus;
2580 char *new_consensus = NULL;
2581 const char *sourcename;
2583 int r;
2584 const char *flavname = conn->requested_resource;
2585 if (status_code != 200) {
2586 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
2587 tor_log(severity, LD_DIR,
2588 "Received http status code %d (%s) from server "
2589 "'%s:%d' while fetching consensus directory.",
2590 status_code, escaped(reason), conn->base_.address,
2591 conn->base_.port);
2592 networkstatus_consensus_download_failed(status_code, flavname);
2593 return -1;
2596 if (looks_like_a_consensus_diff(body, body_len)) {
2597 /* First find our previous consensus. Maybe it's in ram, maybe not. */
2598 cached_dir_t *cd = dirserv_get_consensus(flavname);
2599 const char *consensus_body;
2600 char *owned_consensus = NULL;
2601 if (cd) {
2602 consensus_body = cd->dir;
2603 } else {
2604 owned_consensus = networkstatus_read_cached_consensus(flavname);
2605 consensus_body = owned_consensus;
2607 if (!consensus_body) {
2608 log_warn(LD_DIR, "Received a consensus diff, but we can't find "
2609 "any %s-flavored consensus in our current cache.",flavname);
2610 networkstatus_consensus_download_failed(0, flavname);
2611 // XXXX if this happens too much, see below
2612 return -1;
2615 new_consensus = consensus_diff_apply(consensus_body, body);
2616 tor_free(owned_consensus);
2617 if (new_consensus == NULL) {
2618 log_warn(LD_DIR, "Could not apply consensus diff received from server "
2619 "'%s:%d'", conn->base_.address, conn->base_.port);
2620 // XXXX If this happens too many times, we should maybe not use
2621 // XXXX this directory for diffs any more?
2622 networkstatus_consensus_download_failed(0, flavname);
2623 return -1;
2625 log_info(LD_DIR, "Applied consensus diff (size %d) from server "
2626 "'%s:%d', resulting in a new consensus document (size %d).",
2627 (int)body_len, conn->base_.address, conn->base_.port,
2628 (int)strlen(new_consensus));
2629 consensus = new_consensus;
2630 sourcename = "generated based on a diff";
2631 } else {
2632 log_info(LD_DIR,"Received consensus directory (body size %d) from server "
2633 "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
2634 consensus = body;
2635 sourcename = "downloaded";
2638 if ((r=networkstatus_set_current_consensus(consensus, flavname, 0,
2639 conn->identity_digest))<0) {
2640 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
2641 "Unable to load %s consensus directory %s from "
2642 "server '%s:%d'. I'll try again soon.",
2643 flavname, sourcename, conn->base_.address, conn->base_.port);
2644 networkstatus_consensus_download_failed(0, flavname);
2645 tor_free(new_consensus);
2646 return -1;
2649 /* If we launched other fetches for this consensus, cancel them. */
2650 connection_dir_close_consensus_fetches(conn, flavname);
2652 /* launches router downloads as needed */
2653 routers_update_all_from_networkstatus(now, 3);
2654 update_microdescs_from_networkstatus(now);
2655 update_microdesc_downloads(now);
2656 directory_info_has_arrived(now, 0, 0);
2657 if (authdir_mode_v3(get_options())) {
2658 sr_act_post_consensus(
2659 networkstatus_get_latest_consensus_by_flavor(FLAV_NS));
2661 log_info(LD_DIR, "Successfully loaded consensus.");
2663 tor_free(new_consensus);
2664 return 0;
2668 * Handler function: processes a response to a request for one or more
2669 * authority certificates
2671 static int
2672 handle_response_fetch_certificate(dir_connection_t *conn,
2673 const response_handler_args_t *args)
2675 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
2676 const int status_code = args->status_code;
2677 const char *reason = args->reason;
2678 const char *body = args->body;
2679 const size_t body_len = args->body_len;
2681 if (status_code != 200) {
2682 log_warn(LD_DIR,
2683 "Received http status code %d (%s) from server "
2684 "'%s:%d' while fetching \"/tor/keys/%s\".",
2685 status_code, escaped(reason), conn->base_.address,
2686 conn->base_.port, conn->requested_resource);
2687 connection_dir_download_cert_failed(conn, status_code);
2688 return -1;
2690 log_info(LD_DIR,"Received authority certificates (body size %d) from "
2691 "server '%s:%d'",
2692 (int)body_len, conn->base_.address, conn->base_.port);
2695 * Tell trusted_dirs_load_certs_from_string() whether it was by fp
2696 * or fp-sk pair.
2698 int src_code = -1;
2699 if (!strcmpstart(conn->requested_resource, "fp/")) {
2700 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST;
2701 } else if (!strcmpstart(conn->requested_resource, "fp-sk/")) {
2702 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST;
2705 if (src_code != -1) {
2706 if (trusted_dirs_load_certs_from_string(body, src_code, 1,
2707 conn->identity_digest)<0) {
2708 log_warn(LD_DIR, "Unable to parse fetched certificates");
2709 /* if we fetched more than one and only some failed, the successful
2710 * ones got flushed to disk so it's safe to call this on them */
2711 connection_dir_download_cert_failed(conn, status_code);
2712 } else {
2713 time_t now = approx_time();
2714 directory_info_has_arrived(now, 0, 0);
2715 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
2717 } else {
2718 log_warn(LD_DIR,
2719 "Couldn't figure out what to do with fetched certificates for "
2720 "unknown resource %s",
2721 conn->requested_resource);
2722 connection_dir_download_cert_failed(conn, status_code);
2724 return 0;
2728 * Handler function: processes a response to a request for an authority's
2729 * current networkstatus vote.
2731 static int
2732 handle_response_fetch_status_vote(dir_connection_t *conn,
2733 const response_handler_args_t *args)
2735 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE);
2736 const int status_code = args->status_code;
2737 const char *reason = args->reason;
2738 const char *body = args->body;
2739 const size_t body_len = args->body_len;
2741 const char *msg;
2742 int st;
2743 log_info(LD_DIR,"Got votes (body size %d) from server %s:%d",
2744 (int)body_len, conn->base_.address, conn->base_.port);
2745 if (status_code != 200) {
2746 log_warn(LD_DIR,
2747 "Received http status code %d (%s) from server "
2748 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
2749 status_code, escaped(reason), conn->base_.address,
2750 conn->base_.port, conn->requested_resource);
2751 return -1;
2753 dirvote_add_vote(body, &msg, &st);
2754 if (st > 299) {
2755 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
2756 } else {
2757 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
2760 return 0;
2764 * Handler function: processes a response to a request for the signatures
2765 * that an authority knows about on a given consensus.
2767 static int
2768 handle_response_fetch_detached_signatures(dir_connection_t *conn,
2769 const response_handler_args_t *args)
2771 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
2772 const int status_code = args->status_code;
2773 const char *reason = args->reason;
2774 const char *body = args->body;
2775 const size_t body_len = args->body_len;
2777 const char *msg = NULL;
2778 log_info(LD_DIR,"Got detached signatures (body size %d) from server %s:%d",
2779 (int)body_len, conn->base_.address, conn->base_.port);
2780 if (status_code != 200) {
2781 log_warn(LD_DIR,
2782 "Received http status code %d (%s) from server '%s:%d' while fetching "
2783 "\"/tor/status-vote/next/consensus-signatures.z\".",
2784 status_code, escaped(reason), conn->base_.address,
2785 conn->base_.port);
2786 return -1;
2788 if (dirvote_add_signatures(body, conn->base_.address, &msg)<0) {
2789 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
2790 conn->base_.address, conn->base_.port, msg?msg:"???");
2793 return 0;
2797 * Handler function: processes a response to a request for a group of server
2798 * descriptors or an extrainfo documents.
2800 static int
2801 handle_response_fetch_desc(dir_connection_t *conn,
2802 const response_handler_args_t *args)
2804 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
2805 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
2806 const int status_code = args->status_code;
2807 const char *reason = args->reason;
2808 const char *body = args->body;
2809 const size_t body_len = args->body_len;
2811 int was_ei = conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
2812 smartlist_t *which = NULL;
2813 int n_asked_for = 0;
2814 int descriptor_digests = conn->requested_resource &&
2815 !strcmpstart(conn->requested_resource,"d/");
2816 log_info(LD_DIR,"Received %s (body size %d) from server '%s:%d'",
2817 was_ei ? "extra server info" : "server info",
2818 (int)body_len, conn->base_.address, conn->base_.port);
2819 if (conn->requested_resource &&
2820 (!strcmpstart(conn->requested_resource,"d/") ||
2821 !strcmpstart(conn->requested_resource,"fp/"))) {
2822 which = smartlist_new();
2823 dir_split_resource_into_fingerprints(conn->requested_resource +
2824 (descriptor_digests ? 2 : 3),
2825 which, NULL, 0);
2826 n_asked_for = smartlist_len(which);
2828 if (status_code != 200) {
2829 int dir_okay = status_code == 404 ||
2830 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
2831 /* 404 means that it didn't have them; no big deal.
2832 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
2833 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
2834 "Received http status code %d (%s) from server '%s:%d' "
2835 "while fetching \"/tor/server/%s\". I'll try again soon.",
2836 status_code, escaped(reason), conn->base_.address,
2837 conn->base_.port, conn->requested_resource);
2838 if (!which) {
2839 connection_dir_download_routerdesc_failed(conn);
2840 } else {
2841 dir_routerdesc_download_failed(which, status_code,
2842 conn->router_purpose,
2843 was_ei, descriptor_digests);
2844 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2845 smartlist_free(which);
2847 return dir_okay ? 0 : -1;
2849 /* Learn the routers, assuming we requested by fingerprint or "all"
2850 * or "authority".
2852 * We use "authority" to fetch our own descriptor for
2853 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
2854 * the output of "authority" requests unless we are using bridges,
2855 * since otherwise they'll be the response from reachability tests,
2856 * and we don't really want to add that to our routerlist. */
2857 if (which || (conn->requested_resource &&
2858 (!strcmpstart(conn->requested_resource, "all") ||
2859 (!strcmpstart(conn->requested_resource, "authority") &&
2860 get_options()->UseBridges)))) {
2861 /* as we learn from them, we remove them from 'which' */
2862 if (was_ei) {
2863 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
2864 descriptor_digests);
2865 } else {
2866 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
2867 // descriptor_digests, conn->router_purpose);
2868 if (load_downloaded_routers(body, which, descriptor_digests,
2869 conn->router_purpose,
2870 conn->base_.address)) {
2871 time_t now = approx_time();
2872 directory_info_has_arrived(now, 0, 0);
2876 if (which) { /* mark remaining ones as failed */
2877 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
2878 n_asked_for-smartlist_len(which), n_asked_for,
2879 was_ei ? "extra-info documents" : "router descriptors",
2880 conn->base_.address, (int)conn->base_.port);
2881 if (smartlist_len(which)) {
2882 dir_routerdesc_download_failed(which, status_code,
2883 conn->router_purpose,
2884 was_ei, descriptor_digests);
2886 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2887 smartlist_free(which);
2889 if (directory_conn_is_self_reachability_test(conn))
2890 router_dirport_found_reachable();
2892 return 0;
2896 * Handler function: processes a response to a request for a group of
2897 * microdescriptors
2899 static int
2900 handle_response_fetch_microdesc(dir_connection_t *conn,
2901 const response_handler_args_t *args)
2903 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
2904 const int status_code = args->status_code;
2905 const char *reason = args->reason;
2906 const char *body = args->body;
2907 const size_t body_len = args->body_len;
2909 smartlist_t *which = NULL;
2910 log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
2911 "body size %d) from server '%s:%d'",
2912 status_code, (int)body_len, conn->base_.address,
2913 conn->base_.port);
2914 tor_assert(conn->requested_resource &&
2915 !strcmpstart(conn->requested_resource, "d/"));
2916 which = smartlist_new();
2917 dir_split_resource_into_fingerprints(conn->requested_resource+2,
2918 which, NULL,
2919 DSR_DIGEST256|DSR_BASE64);
2920 if (status_code != 200) {
2921 log_info(LD_DIR, "Received status code %d (%s) from server "
2922 "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again "
2923 "soon.",
2924 status_code, escaped(reason), conn->base_.address,
2925 (int)conn->base_.port, conn->requested_resource);
2926 dir_microdesc_download_failed(which, status_code);
2927 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2928 smartlist_free(which);
2929 return 0;
2930 } else {
2931 smartlist_t *mds;
2932 time_t now = approx_time();
2933 mds = microdescs_add_to_cache(get_microdesc_cache(),
2934 body, body+body_len, SAVED_NOWHERE, 0,
2935 now, which);
2936 if (smartlist_len(which)) {
2937 /* Mark remaining ones as failed. */
2938 dir_microdesc_download_failed(which, status_code);
2940 if (mds && smartlist_len(mds)) {
2941 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
2942 count_loading_descriptors_progress());
2943 directory_info_has_arrived(now, 0, 1);
2945 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
2946 smartlist_free(which);
2947 smartlist_free(mds);
2950 return 0;
2954 * Handler function: processes a response to a POST request to upload our
2955 * router descriptor.
2957 static int
2958 handle_response_upload_dir(dir_connection_t *conn,
2959 const response_handler_args_t *args)
2961 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_DIR);
2962 const int status_code = args->status_code;
2963 const char *reason = args->reason;
2964 const char *headers = args->headers;
2966 switch (status_code) {
2967 case 200: {
2968 dir_server_t *ds =
2969 router_get_trusteddirserver_by_digest(conn->identity_digest);
2970 char *rejected_hdr = http_get_header(headers,
2971 "X-Descriptor-Not-New: ");
2972 if (rejected_hdr) {
2973 if (!strcmp(rejected_hdr, "Yes")) {
2974 log_info(LD_GENERAL,
2975 "Authority '%s' declined our descriptor (not new)",
2976 ds->nickname);
2977 /* XXXX use this information; be sure to upload next one
2978 * sooner. -NM */
2979 /* XXXX++ On further thought, the task above implies that we're
2980 * basing our regenerate-descriptor time on when we uploaded the
2981 * last descriptor, not on the published time of the last
2982 * descriptor. If those are different, that's a bad thing to
2983 * do. -NM */
2985 tor_free(rejected_hdr);
2987 log_info(LD_GENERAL,"eof (status 200) after uploading server "
2988 "descriptor: finished.");
2989 control_event_server_status(
2990 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
2991 conn->base_.address, conn->base_.port);
2993 ds->has_accepted_serverdesc = 1;
2994 if (directories_have_accepted_server_descriptor())
2995 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
2997 break;
2998 case 400:
2999 log_warn(LD_GENERAL,"http status 400 (%s) response from "
3000 "dirserver '%s:%d'. Please correct.",
3001 escaped(reason), conn->base_.address, conn->base_.port);
3002 control_event_server_status(LOG_WARN,
3003 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
3004 conn->base_.address, conn->base_.port, escaped(reason));
3005 break;
3006 default:
3007 log_warn(LD_GENERAL,
3008 "HTTP status %d (%s) was unexpected while uploading "
3009 "descriptor to server '%s:%d'. Possibly the server is "
3010 "misconfigured?",
3011 status_code, escaped(reason), conn->base_.address,
3012 conn->base_.port);
3013 break;
3015 /* return 0 in all cases, since we don't want to mark any
3016 * dirservers down just because they don't like us. */
3018 return 0;
3022 * Handler function: processes a response to POST request to upload our
3023 * own networkstatus vote.
3025 static int
3026 handle_response_upload_vote(dir_connection_t *conn,
3027 const response_handler_args_t *args)
3029 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_VOTE);
3030 const int status_code = args->status_code;
3031 const char *reason = args->reason;
3033 switch (status_code) {
3034 case 200: {
3035 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
3036 conn->base_.address, conn->base_.port);
3038 break;
3039 case 400:
3040 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
3041 "vote to dirserver '%s:%d'. Please correct.",
3042 escaped(reason), conn->base_.address, conn->base_.port);
3043 break;
3044 default:
3045 log_warn(LD_GENERAL,
3046 "HTTP status %d (%s) was unexpected while uploading "
3047 "vote to server '%s:%d'.",
3048 status_code, escaped(reason), conn->base_.address,
3049 conn->base_.port);
3050 break;
3052 /* return 0 in all cases, since we don't want to mark any
3053 * dirservers down just because they don't like us. */
3054 return 0;
3058 * Handler function: processes a response to POST request to upload our
3059 * view of the signatures on the current consensus.
3061 static int
3062 handle_response_upload_signatures(dir_connection_t *conn,
3063 const response_handler_args_t *args)
3065 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES);
3066 const int status_code = args->status_code;
3067 const char *reason = args->reason;
3069 switch (status_code) {
3070 case 200: {
3071 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
3072 conn->base_.address, conn->base_.port);
3074 break;
3075 case 400:
3076 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
3077 "signatures to dirserver '%s:%d'. Please correct.",
3078 escaped(reason), conn->base_.address, conn->base_.port);
3079 break;
3080 default:
3081 log_warn(LD_GENERAL,
3082 "HTTP status %d (%s) was unexpected while uploading "
3083 "signatures to server '%s:%d'.",
3084 status_code, escaped(reason), conn->base_.address,
3085 conn->base_.port);
3086 break;
3088 /* return 0 in all cases, since we don't want to mark any
3089 * dirservers down just because they don't like us. */
3091 return 0;
3095 * Handler function: processes a response to a request for a v3 hidden service
3096 * descriptor.
3098 STATIC int
3099 handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
3100 const response_handler_args_t *args)
3102 const int status_code = args->status_code;
3103 const char *reason = args->reason;
3104 const char *body = args->body;
3105 const size_t body_len = args->body_len;
3107 tor_assert(conn->hs_ident);
3109 log_info(LD_REND,"Received v3 hsdesc (body size %d, status %d (%s))",
3110 (int)body_len, status_code, escaped(reason));
3112 switch (status_code) {
3113 case 200:
3114 /* We got something: Try storing it in the cache. */
3115 if (hs_cache_store_as_client(body, &conn->hs_ident->identity_pk) < 0) {
3116 log_warn(LD_REND, "Failed to store hidden service descriptor");
3117 } else {
3118 log_info(LD_REND, "Stored hidden service descriptor successfully.");
3119 TO_CONN(conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
3120 hs_client_desc_has_arrived(conn->hs_ident);
3122 break;
3123 case 404:
3124 /* Not there. We'll retry when connection_about_to_close_connection()
3125 * tries to clean this conn up. */
3126 log_info(LD_REND, "Fetching hidden service v3 descriptor not found: "
3127 "Retrying at another directory.");
3128 /* TODO: Inform the control port */
3129 break;
3130 case 400:
3131 log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
3132 "http status 400 (%s). Dirserver didn't like our "
3133 "query? Retrying at another directory.",
3134 escaped(reason));
3135 break;
3136 default:
3137 log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
3138 "http status %d (%s) response unexpected from HSDir server "
3139 "'%s:%d'. Retrying at another directory.",
3140 status_code, escaped(reason), TO_CONN(conn)->address,
3141 TO_CONN(conn)->port);
3142 break;
3145 return 0;
3149 * Handler function: processes a response to a request for a v2 hidden service
3150 * descriptor.
3152 static int
3153 handle_response_fetch_renddesc_v2(dir_connection_t *conn,
3154 const response_handler_args_t *args)
3156 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2);
3157 const int status_code = args->status_code;
3158 const char *reason = args->reason;
3159 const char *body = args->body;
3160 const size_t body_len = args->body_len;
3162 #define SEND_HS_DESC_FAILED_EVENT(reason) \
3163 (control_event_hs_descriptor_failed(conn->rend_data, \
3164 conn->identity_digest, \
3165 reason))
3166 #define SEND_HS_DESC_FAILED_CONTENT() \
3167 (control_event_hs_descriptor_content( \
3168 rend_data_get_address(conn->rend_data), \
3169 conn->requested_resource, \
3170 conn->identity_digest, \
3171 NULL))
3173 tor_assert(conn->rend_data);
3174 log_info(LD_REND,"Received rendezvous descriptor (body size %d, status %d "
3175 "(%s))",
3176 (int)body_len, status_code, escaped(reason));
3177 switch (status_code) {
3178 case 200:
3180 rend_cache_entry_t *entry = NULL;
3182 if (rend_cache_store_v2_desc_as_client(body,
3183 conn->requested_resource,
3184 conn->rend_data, &entry) < 0) {
3185 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
3186 "Retrying at another directory.");
3187 /* We'll retry when connection_about_to_close_connection()
3188 * cleans this dir conn up. */
3189 SEND_HS_DESC_FAILED_EVENT("BAD_DESC");
3190 SEND_HS_DESC_FAILED_CONTENT();
3191 } else {
3192 char service_id[REND_SERVICE_ID_LEN_BASE32 + 1];
3193 /* Should never be NULL here if we found the descriptor. */
3194 tor_assert(entry);
3195 rend_get_service_id(entry->parsed->pk, service_id);
3197 /* success. notify pending connections about this. */
3198 log_info(LD_REND, "Successfully fetched v2 rendezvous "
3199 "descriptor.");
3200 control_event_hs_descriptor_received(service_id,
3201 conn->rend_data,
3202 conn->identity_digest);
3203 control_event_hs_descriptor_content(service_id,
3204 conn->requested_resource,
3205 conn->identity_digest,
3206 body);
3207 conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
3208 rend_client_desc_trynow(service_id);
3209 memwipe(service_id, 0, sizeof(service_id));
3211 break;
3213 case 404:
3214 /* Not there. We'll retry when
3215 * connection_about_to_close_connection() cleans this conn up. */
3216 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
3217 "Retrying at another directory.");
3218 SEND_HS_DESC_FAILED_EVENT("NOT_FOUND");
3219 SEND_HS_DESC_FAILED_CONTENT();
3220 break;
3221 case 400:
3222 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
3223 "http status 400 (%s). Dirserver didn't like our "
3224 "v2 rendezvous query? Retrying at another directory.",
3225 escaped(reason));
3226 SEND_HS_DESC_FAILED_EVENT("QUERY_REJECTED");
3227 SEND_HS_DESC_FAILED_CONTENT();
3228 break;
3229 default:
3230 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
3231 "http status %d (%s) response unexpected while "
3232 "fetching v2 hidden service descriptor (server '%s:%d'). "
3233 "Retrying at another directory.",
3234 status_code, escaped(reason), conn->base_.address,
3235 conn->base_.port);
3236 SEND_HS_DESC_FAILED_EVENT("UNEXPECTED");
3237 SEND_HS_DESC_FAILED_CONTENT();
3238 break;
3241 return 0;
3245 * Handler function: processes a response to a POST request to upload a v2
3246 * hidden service descriptor.
3248 static int
3249 handle_response_upload_renddesc_v2(dir_connection_t *conn,
3250 const response_handler_args_t *args)
3252 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2);
3253 const int status_code = args->status_code;
3254 const char *reason = args->reason;
3256 #define SEND_HS_DESC_UPLOAD_FAILED_EVENT(reason) \
3257 (control_event_hs_descriptor_upload_failed( \
3258 conn->identity_digest, \
3259 rend_data_get_address(conn->rend_data), \
3260 reason))
3262 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
3263 "(%s))",
3264 status_code, escaped(reason));
3265 /* Without the rend data, we'll have a problem identifying what has been
3266 * uploaded for which service. */
3267 tor_assert(conn->rend_data);
3268 switch (status_code) {
3269 case 200:
3270 log_info(LD_REND,
3271 "Uploading rendezvous descriptor: finished with status "
3272 "200 (%s)", escaped(reason));
3273 control_event_hs_descriptor_uploaded(conn->identity_digest,
3274 rend_data_get_address(conn->rend_data));
3275 rend_service_desc_has_uploaded(conn->rend_data);
3276 break;
3277 case 400:
3278 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
3279 "'%s:%d'. Malformed rendezvous descriptor?",
3280 escaped(reason), conn->base_.address, conn->base_.port);
3281 SEND_HS_DESC_UPLOAD_FAILED_EVENT("UPLOAD_REJECTED");
3282 break;
3283 default:
3284 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
3285 "'%s:%d').",
3286 status_code, escaped(reason), conn->base_.address,
3287 conn->base_.port);
3288 SEND_HS_DESC_UPLOAD_FAILED_EVENT("UNEXPECTED");
3289 break;
3292 return 0;
3296 * Handler function: processes a response to a POST request to upload an
3297 * hidden service descriptor.
3299 static int
3300 handle_response_upload_hsdesc(dir_connection_t *conn,
3301 const response_handler_args_t *args)
3303 const int status_code = args->status_code;
3304 const char *reason = args->reason;
3306 tor_assert(conn);
3307 tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_HSDESC);
3309 log_info(LD_REND, "Uploaded hidden service descriptor (status %d "
3310 "(%s))",
3311 status_code, escaped(reason));
3312 /* For this directory response, it MUST have an hidden service identifier on
3313 * this connection. */
3314 tor_assert(conn->hs_ident);
3315 switch (status_code) {
3316 case 200:
3317 log_info(LD_REND, "Uploading hidden service descriptor: "
3318 "finished with status 200 (%s)", escaped(reason));
3319 /* XXX: Trigger control event. */
3320 break;
3321 case 400:
3322 log_warn(LD_REND, "Uploading hidden service descriptor: http "
3323 "status 400 (%s) response from dirserver "
3324 "'%s:%d'. Malformed hidden service descriptor?",
3325 escaped(reason), conn->base_.address, conn->base_.port);
3326 /* XXX: Trigger control event. */
3327 break;
3328 default:
3329 log_warn(LD_REND, "Uploading hidden service descriptor: http "
3330 "status %d (%s) response unexpected (server "
3331 "'%s:%d').",
3332 status_code, escaped(reason), conn->base_.address,
3333 conn->base_.port);
3334 /* XXX: Trigger control event. */
3335 break;
3338 return 0;
3341 /** Called when a directory connection reaches EOF. */
3343 connection_dir_reached_eof(dir_connection_t *conn)
3345 int retval;
3346 if (conn->base_.state != DIR_CONN_STATE_CLIENT_READING) {
3347 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
3348 conn->base_.state);
3349 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
3350 connection_mark_for_close(TO_CONN(conn));
3351 return -1;
3354 retval = connection_dir_client_reached_eof(conn);
3355 if (retval == 0) /* success */
3356 conn->base_.state = DIR_CONN_STATE_CLIENT_FINISHED;
3357 connection_mark_for_close(TO_CONN(conn));
3358 return retval;
3361 /** If any directory object is arriving, and it's over 10MB large, we're
3362 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
3363 * ask for more than 96 router descriptors at a time.)
3365 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
3367 #define MAX_VOTE_DL_SIZE (MAX_DIRECTORY_OBJECT_SIZE * 5)
3369 /** Read handler for directory connections. (That's connections <em>to</em>
3370 * directory servers and connections <em>at</em> directory servers.)
3373 connection_dir_process_inbuf(dir_connection_t *conn)
3375 size_t max_size;
3376 tor_assert(conn);
3377 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3379 /* Directory clients write, then read data until they receive EOF;
3380 * directory servers read data until they get an HTTP command, then
3381 * write their response (when it's finished flushing, they mark for
3382 * close).
3385 /* If we're on the dirserver side, look for a command. */
3386 if (conn->base_.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
3387 if (directory_handle_command(conn) < 0) {
3388 connection_mark_for_close(TO_CONN(conn));
3389 return -1;
3391 return 0;
3394 max_size =
3395 (TO_CONN(conn)->purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) ?
3396 MAX_VOTE_DL_SIZE : MAX_DIRECTORY_OBJECT_SIZE;
3398 if (connection_get_inbuf_len(TO_CONN(conn)) > max_size) {
3399 log_warn(LD_HTTP,
3400 "Too much data received from directory connection (%s): "
3401 "denial of service attempt, or you need to upgrade?",
3402 conn->base_.address);
3403 connection_mark_for_close(TO_CONN(conn));
3404 return -1;
3407 if (!conn->base_.inbuf_reached_eof)
3408 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
3409 return 0;
3412 /** We are closing a dir connection: If <b>dir_conn</b> is a dir connection
3413 * that tried to fetch an HS descriptor, check if it successfuly fetched it,
3414 * or if we need to try again. */
3415 static void
3416 refetch_hsdesc_if_needed(dir_connection_t *dir_conn)
3418 connection_t *conn = TO_CONN(dir_conn);
3420 /* If we were trying to fetch a v2 rend desc and did not succeed, retry as
3421 * needed. (If a fetch is successful, the connection state is changed to
3422 * DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 or DIR_PURPOSE_HAS_FETCHED_HSDESC to
3423 * mark that refetching is unnecessary.) */
3424 if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
3425 dir_conn->rend_data &&
3426 rend_valid_v2_service_id(
3427 rend_data_get_address(dir_conn->rend_data))) {
3428 rend_client_refetch_v2_renddesc(dir_conn->rend_data);
3431 /* Check for v3 rend desc fetch */
3432 if (conn->purpose == DIR_PURPOSE_FETCH_HSDESC &&
3433 dir_conn->hs_ident &&
3434 !ed25519_public_key_is_zero(&dir_conn->hs_ident->identity_pk)) {
3435 hs_client_refetch_hsdesc(&dir_conn->hs_ident->identity_pk);
3439 /** Called when we're about to finally unlink and free a directory connection:
3440 * perform necessary accounting and cleanup */
3441 void
3442 connection_dir_about_to_close(dir_connection_t *dir_conn)
3444 connection_t *conn = TO_CONN(dir_conn);
3446 if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
3447 /* It's a directory connection and connecting or fetching
3448 * failed: forget about this router, and maybe try again. */
3449 connection_dir_request_failed(dir_conn);
3452 refetch_hsdesc_if_needed(dir_conn);
3455 /** Create an http response for the client <b>conn</b> out of
3456 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
3458 static void
3459 write_http_status_line(dir_connection_t *conn, int status,
3460 const char *reason_phrase)
3462 char buf[256];
3463 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
3464 status, reason_phrase ? reason_phrase : "OK") < 0) {
3465 log_warn(LD_BUG,"status line too long.");
3466 return;
3468 log_debug(LD_DIRSERV,"Wrote status 'HTTP/1.0 %d %s'", status, reason_phrase);
3469 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
3472 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
3473 * with <b>type</b> as the Content-Type.
3475 * If <b>length</b> is nonnegative, it is the Content-Length.
3476 * If <b>encoding</b> is provided, it is the Content-Encoding.
3477 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
3478 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
3479 static void
3480 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
3481 const char *type, const char *encoding,
3482 const char *extra_headers,
3483 long cache_lifetime)
3485 char date[RFC1123_TIME_LEN+1];
3486 char tmp[1024];
3487 char *cp;
3488 time_t now = time(NULL);
3490 tor_assert(conn);
3492 format_rfc1123_time(date, now);
3493 cp = tmp;
3494 tor_snprintf(cp, sizeof(tmp),
3495 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
3496 date);
3497 cp += strlen(tmp);
3498 if (type) {
3499 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
3500 cp += strlen(cp);
3502 if (!is_local_addr(&conn->base_.addr)) {
3503 /* Don't report the source address for a nearby/private connection.
3504 * Otherwise we tend to mis-report in cases where incoming ports are
3505 * being forwarded to a Tor server running behind the firewall. */
3506 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
3507 X_ADDRESS_HEADER "%s\r\n", conn->base_.address);
3508 cp += strlen(cp);
3510 if (encoding) {
3511 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
3512 "Content-Encoding: %s\r\n", encoding);
3513 cp += strlen(cp);
3515 if (length >= 0) {
3516 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
3517 "Content-Length: %ld\r\n", (long)length);
3518 cp += strlen(cp);
3520 if (cache_lifetime > 0) {
3521 char expbuf[RFC1123_TIME_LEN+1];
3522 format_rfc1123_time(expbuf, (time_t)(now + cache_lifetime));
3523 /* We could say 'Cache-control: max-age=%d' here if we start doing
3524 * http/1.1 */
3525 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
3526 "Expires: %s\r\n", expbuf);
3527 cp += strlen(cp);
3528 } else if (cache_lifetime == 0) {
3529 /* We could say 'Cache-control: no-cache' here if we start doing
3530 * http/1.1 */
3531 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
3532 cp += strlen(cp);
3534 if (extra_headers) {
3535 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
3536 cp += strlen(cp);
3538 if (sizeof(tmp)-(cp-tmp) > 3)
3539 memcpy(cp, "\r\n", 3);
3540 else
3541 tor_assert(0);
3542 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
3545 /** As write_http_response_header_impl, but sets encoding and content-typed
3546 * based on whether the response will be <b>compressed</b> or not. */
3547 static void
3548 write_http_response_headers(dir_connection_t *conn, ssize_t length,
3549 compress_method_t method,
3550 const char *extra_headers, long cache_lifetime)
3552 const char *methodname = compression_method_get_name(method);
3553 const char *doctype;
3554 if (method == NO_METHOD)
3555 doctype = "text/plain";
3556 else
3557 doctype = "application/octet-stream";
3558 write_http_response_header_impl(conn, length,
3559 doctype,
3560 methodname,
3561 extra_headers,
3562 cache_lifetime);
3565 /** As write_http_response_headers, but assumes extra_headers is NULL */
3566 static void
3567 write_http_response_header(dir_connection_t *conn, ssize_t length,
3568 compress_method_t method,
3569 long cache_lifetime)
3571 write_http_response_headers(conn, length, method, NULL, cache_lifetime);
3574 /** Array of compression methods to use (if supported) for serving
3575 * precompressed data, ordered from best to worst. */
3576 static compress_method_t srv_meth_pref_precompressed[] = {
3577 LZMA_METHOD,
3578 ZSTD_METHOD,
3579 ZLIB_METHOD,
3580 GZIP_METHOD,
3581 NO_METHOD
3584 /** Array of compression methods to use (if supported) for serving
3585 * streamed data, ordered from best to worst. */
3586 static compress_method_t srv_meth_pref_streaming_compression[] = {
3587 ZSTD_METHOD,
3588 ZLIB_METHOD,
3589 GZIP_METHOD,
3590 NO_METHOD
3593 /** Array of allowed compression methods to use (if supported) when receiving a
3594 * response from a request that was required to be anonymous. */
3595 static compress_method_t client_meth_allowed_anonymous_compression[] = {
3596 ZLIB_METHOD,
3597 GZIP_METHOD,
3598 NO_METHOD
3601 /** Parse the compression methods listed in an Accept-Encoding header <b>h</b>,
3602 * and convert them to a bitfield where compression method x is supported if
3603 * and only if 1 &lt;&lt; x is set in the bitfield. */
3604 STATIC unsigned
3605 parse_accept_encoding_header(const char *h)
3607 unsigned result = (1u << NO_METHOD);
3608 smartlist_t *methods = smartlist_new();
3609 smartlist_split_string(methods, h, ",",
3610 SPLIT_SKIP_SPACE|SPLIT_STRIP_SPACE|SPLIT_IGNORE_BLANK, 0);
3612 SMARTLIST_FOREACH_BEGIN(methods, const char *, m) {
3613 compress_method_t method = compression_method_get_by_name(m);
3614 if (method != UNKNOWN_METHOD) {
3615 tor_assert(((unsigned)method) < 8*sizeof(unsigned));
3616 result |= (1u << method);
3618 } SMARTLIST_FOREACH_END(m);
3619 SMARTLIST_FOREACH_BEGIN(methods, char *, m) {
3620 tor_free(m);
3621 } SMARTLIST_FOREACH_END(m);
3622 smartlist_free(methods);
3623 return result;
3626 /** Array of compression methods to use (if supported) for requesting
3627 * compressed data, ordered from best to worst. */
3628 static compress_method_t client_meth_pref[] = {
3629 LZMA_METHOD,
3630 ZSTD_METHOD,
3631 ZLIB_METHOD,
3632 GZIP_METHOD,
3633 NO_METHOD
3636 /** Return a newly allocated string containing a comma separated list of
3637 * supported encodings. */
3638 STATIC char *
3639 accept_encoding_header(void)
3641 smartlist_t *methods = smartlist_new();
3642 char *header = NULL;
3643 compress_method_t method;
3644 unsigned i;
3646 for (i = 0; i < ARRAY_LENGTH(client_meth_pref); ++i) {
3647 method = client_meth_pref[i];
3648 if (tor_compress_supports_method(method))
3649 smartlist_add(methods, (char *)compression_method_get_name(method));
3652 header = smartlist_join_strings(methods, ", ", 0, NULL);
3653 smartlist_free(methods);
3655 return header;
3658 /** Decide whether a client would accept the consensus we have.
3660 * Clients can say they only want a consensus if it's signed by more
3661 * than half the authorities in a list. They pass this list in
3662 * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
3664 * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
3665 * of the full authority identity digest. (Only strings of even length,
3666 * i.e. encodings of full bytes, are handled correctly. In the case
3667 * of an odd number of hex digits the last one is silently ignored.)
3669 * Returns 1 if more than half of the requested authorities signed the
3670 * consensus, 0 otherwise.
3673 client_likes_consensus(const struct consensus_cache_entry_t *ent,
3674 const char *want_url)
3676 smartlist_t *voters = smartlist_new();
3677 int need_at_least;
3678 int have = 0;
3680 if (consensus_cache_entry_get_voter_id_digests(ent, voters) != 0) {
3681 return 1; // We don't know the voters; assume the client won't mind. */
3684 smartlist_t *want_authorities = smartlist_new();
3685 dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0);
3686 need_at_least = smartlist_len(want_authorities)/2+1;
3688 SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, want_digest) {
3690 SMARTLIST_FOREACH_BEGIN(voters, const char *, digest) {
3691 if (!strcasecmpstart(digest, want_digest)) {
3692 have++;
3693 break;
3695 } SMARTLIST_FOREACH_END(digest);
3697 /* early exit, if we already have enough */
3698 if (have >= need_at_least)
3699 break;
3700 } SMARTLIST_FOREACH_END(want_digest);
3702 SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
3703 smartlist_free(want_authorities);
3704 SMARTLIST_FOREACH(voters, char *, cp, tor_free(cp));
3705 smartlist_free(voters);
3706 return (have >= need_at_least);
3709 /** Return the compression level we should use for sending a compressed
3710 * response of size <b>n_bytes</b>. */
3711 STATIC compression_level_t
3712 choose_compression_level(ssize_t n_bytes)
3714 if (! have_been_under_memory_pressure()) {
3715 return HIGH_COMPRESSION; /* we have plenty of RAM. */
3716 } else if (n_bytes < 0) {
3717 return HIGH_COMPRESSION; /* unknown; might be big. */
3718 } else if (n_bytes < 1024) {
3719 return LOW_COMPRESSION;
3720 } else if (n_bytes < 2048) {
3721 return MEDIUM_COMPRESSION;
3722 } else {
3723 return HIGH_COMPRESSION;
3727 /** Information passed to handle a GET request. */
3728 typedef struct get_handler_args_t {
3729 /** Bitmask of compression methods that the client said (or implied) it
3730 * supported. */
3731 unsigned compression_supported;
3732 /** If nonzero, the time included an if-modified-since header with this
3733 * value. */
3734 time_t if_modified_since;
3735 /** String containing the requested URL or resource. */
3736 const char *url;
3737 /** String containing the HTTP headers */
3738 const char *headers;
3739 } get_handler_args_t;
3741 /** Entry for handling an HTTP GET request.
3743 * This entry matches a request if "string" is equal to the requested
3744 * resource, or if "is_prefix" is true and "string" is a prefix of the
3745 * requested resource.
3747 * The 'handler' function is called to handle the request. It receives
3748 * an arguments structure, and must return 0 on success or -1 if we should
3749 * close the connection.
3751 typedef struct url_table_ent_s {
3752 const char *string;
3753 int is_prefix;
3754 int (*handler)(dir_connection_t *conn, const get_handler_args_t *args);
3755 } url_table_ent_t;
3757 static int handle_get_frontpage(dir_connection_t *conn,
3758 const get_handler_args_t *args);
3759 static int handle_get_current_consensus(dir_connection_t *conn,
3760 const get_handler_args_t *args);
3761 static int handle_get_status_vote(dir_connection_t *conn,
3762 const get_handler_args_t *args);
3763 static int handle_get_microdesc(dir_connection_t *conn,
3764 const get_handler_args_t *args);
3765 static int handle_get_descriptor(dir_connection_t *conn,
3766 const get_handler_args_t *args);
3767 static int handle_get_keys(dir_connection_t *conn,
3768 const get_handler_args_t *args);
3769 static int handle_get_hs_descriptor_v2(dir_connection_t *conn,
3770 const get_handler_args_t *args);
3771 static int handle_get_robots(dir_connection_t *conn,
3772 const get_handler_args_t *args);
3773 static int handle_get_networkstatus_bridges(dir_connection_t *conn,
3774 const get_handler_args_t *args);
3776 /** Table for handling GET requests. */
3777 static const url_table_ent_t url_table[] = {
3778 { "/tor/", 0, handle_get_frontpage },
3779 { "/tor/status-vote/current/consensus", 1, handle_get_current_consensus },
3780 { "/tor/status-vote/current/", 1, handle_get_status_vote },
3781 { "/tor/status-vote/next/", 1, handle_get_status_vote },
3782 { "/tor/micro/d/", 1, handle_get_microdesc },
3783 { "/tor/server/", 1, handle_get_descriptor },
3784 { "/tor/extra/", 1, handle_get_descriptor },
3785 { "/tor/keys/", 1, handle_get_keys },
3786 { "/tor/rendezvous2/", 1, handle_get_hs_descriptor_v2 },
3787 { "/tor/hs/3/", 1, handle_get_hs_descriptor_v3 },
3788 { "/tor/robots.txt", 0, handle_get_robots },
3789 { "/tor/networkstatus-bridges", 0, handle_get_networkstatus_bridges },
3790 { NULL, 0, NULL },
3793 /** Helper function: called when a dirserver gets a complete HTTP GET
3794 * request. Look for a request for a directory or for a rendezvous
3795 * service descriptor. On finding one, write a response into
3796 * conn-\>outbuf. If the request is unrecognized, send a 404.
3797 * Return 0 if we handled this successfully, or -1 if we need to close
3798 * the connection. */
3799 MOCK_IMPL(STATIC int,
3800 directory_handle_command_get,(dir_connection_t *conn, const char *headers,
3801 const char *req_body, size_t req_body_len))
3803 char *url, *url_mem, *header;
3804 time_t if_modified_since = 0;
3805 int zlib_compressed_in_url;
3806 size_t url_len;
3807 unsigned compression_methods_supported;
3809 /* We ignore the body of a GET request. */
3810 (void)req_body;
3811 (void)req_body_len;
3813 log_debug(LD_DIRSERV,"Received GET command.");
3815 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
3817 if (parse_http_url(headers, &url) < 0) {
3818 write_http_status_line(conn, 400, "Bad request");
3819 return 0;
3821 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
3822 struct tm tm;
3823 if (parse_http_time(header, &tm) == 0) {
3824 if (tor_timegm(&tm, &if_modified_since)<0) {
3825 if_modified_since = 0;
3826 } else {
3827 log_debug(LD_DIRSERV, "If-Modified-Since is '%s'.", escaped(header));
3830 /* The correct behavior on a malformed If-Modified-Since header is to
3831 * act as if no If-Modified-Since header had been given. */
3832 tor_free(header);
3834 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
3836 url_mem = url;
3837 url_len = strlen(url);
3839 zlib_compressed_in_url = url_len > 2 && !strcmp(url+url_len-2, ".z");
3840 if (zlib_compressed_in_url) {
3841 url[url_len-2] = '\0';
3842 url_len -= 2;
3845 if ((header = http_get_header(headers, "Accept-Encoding: "))) {
3846 compression_methods_supported = parse_accept_encoding_header(header);
3847 tor_free(header);
3848 } else {
3849 compression_methods_supported = (1u << NO_METHOD);
3851 if (zlib_compressed_in_url) {
3852 compression_methods_supported |= (1u << ZLIB_METHOD);
3855 /* Remove all methods that we don't both support. */
3856 compression_methods_supported &= tor_compress_get_supported_method_bitmask();
3858 get_handler_args_t args;
3859 args.url = url;
3860 args.headers = headers;
3861 args.if_modified_since = if_modified_since;
3862 args.compression_supported = compression_methods_supported;
3864 int i, result = -1;
3865 for (i = 0; url_table[i].string; ++i) {
3866 int match;
3867 if (url_table[i].is_prefix) {
3868 match = !strcmpstart(url, url_table[i].string);
3869 } else {
3870 match = !strcmp(url, url_table[i].string);
3872 if (match) {
3873 result = url_table[i].handler(conn, &args);
3874 goto done;
3878 /* we didn't recognize the url */
3879 write_http_status_line(conn, 404, "Not found");
3880 result = 0;
3882 done:
3883 tor_free(url_mem);
3884 return result;
3887 /** Helper function for GET / or GET /tor/
3889 static int
3890 handle_get_frontpage(dir_connection_t *conn, const get_handler_args_t *args)
3892 (void) args; /* unused */
3893 const char *frontpage = get_dirportfrontpage();
3895 if (frontpage) {
3896 size_t dlen;
3897 dlen = strlen(frontpage);
3898 /* Let's return a disclaimer page (users shouldn't use V1 anymore,
3899 and caches don't fetch '/', so this is safe). */
3901 /* [We don't check for write_bucket_low here, since we want to serve
3902 * this page no matter what.] */
3903 write_http_response_header_impl(conn, dlen, "text/html", "identity",
3904 NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
3905 connection_write_to_buf(frontpage, dlen, TO_CONN(conn));
3906 } else {
3907 write_http_status_line(conn, 404, "Not found");
3909 return 0;
3912 /** Warn that the cached consensus <b>consensus</b> of type
3913 * <b>flavor</b> is too old and will not be served to clients. Rate-limit the
3914 * warning to avoid logging an entry on every request.
3916 static void
3917 warn_consensus_is_too_old(const struct consensus_cache_entry_t *consensus,
3918 const char *flavor, time_t now)
3920 #define TOO_OLD_WARNING_INTERVAL (60*60)
3921 static ratelim_t warned = RATELIM_INIT(TOO_OLD_WARNING_INTERVAL);
3922 char timestamp[ISO_TIME_LEN+1];
3923 time_t valid_until;
3924 char *dupes;
3926 if (consensus_cache_entry_get_valid_until(consensus, &valid_until))
3927 return;
3929 if ((dupes = rate_limit_log(&warned, now))) {
3930 format_local_iso_time(timestamp, valid_until);
3931 log_warn(LD_DIRSERV, "Our %s%sconsensus is too old, so we will not "
3932 "serve it to clients. It was valid until %s local time and we "
3933 "continued to serve it for up to 24 hours after it expired.%s",
3934 flavor ? flavor : "", flavor ? " " : "", timestamp, dupes);
3935 tor_free(dupes);
3940 * Parse a single hex-encoded sha3-256 digest from <b>hex</b> into
3941 * <b>digest</b>. Return 0 on success. On failure, report that the hash came
3942 * from <b>location</b>, report that we are taking <b>action</b> with it, and
3943 * return -1.
3945 static int
3946 parse_one_diff_hash(uint8_t *digest, const char *hex, const char *location,
3947 const char *action)
3949 if (base16_decode((char*)digest, DIGEST256_LEN, hex, strlen(hex)) ==
3950 DIGEST256_LEN) {
3951 return 0;
3952 } else {
3953 log_fn(LOG_PROTOCOL_WARN, LD_DIR,
3954 "%s contained bogus digest %s; %s.",
3955 location, escaped(hex), action);
3956 return -1;
3960 /** If there is an X-Or-Diff-From-Consensus header included in <b>headers</b>,
3961 * set <b>digest_out<b> to a new smartlist containing every 256-bit
3962 * hex-encoded digest listed in that header and return 0. Otherwise return
3963 * -1. */
3964 static int
3965 parse_or_diff_from_header(smartlist_t **digests_out, const char *headers)
3967 char *hdr = http_get_header(headers, X_OR_DIFF_FROM_CONSENSUS_HEADER);
3968 if (hdr == NULL) {
3969 return -1;
3971 smartlist_t *hex_digests = smartlist_new();
3972 *digests_out = smartlist_new();
3973 smartlist_split_string(hex_digests, hdr, " ",
3974 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
3975 SMARTLIST_FOREACH_BEGIN(hex_digests, const char *, hex) {
3976 uint8_t digest[DIGEST256_LEN];
3977 if (!parse_one_diff_hash(digest, hex, "X-Or-Diff-From-Consensus header",
3978 "ignoring")) {
3979 smartlist_add(*digests_out, tor_memdup(digest, sizeof(digest)));
3981 } SMARTLIST_FOREACH_END(hex);
3982 SMARTLIST_FOREACH(hex_digests, char *, cp, tor_free(cp));
3983 smartlist_free(hex_digests);
3984 tor_free(hdr);
3985 return 0;
3988 /** Fallback compression method. The fallback compression method is used in
3989 * case a client requests a non-compressed document. We only store compressed
3990 * documents, so we use this compression method to fetch the document and let
3991 * the spooling system do the streaming decompression.
3993 #define FALLBACK_COMPRESS_METHOD ZLIB_METHOD
3996 * Try to find the best consensus diff possible in order to serve a client
3997 * request for a diff from one of the consensuses in <b>digests</b> to the
3998 * current consensus of flavor <b>flav</b>. The client supports the
3999 * compression methods listed in the <b>compression_methods</b> bitfield:
4000 * place the method chosen (if any) into <b>compression_used_out</b>.
4002 static struct consensus_cache_entry_t *
4003 find_best_diff(const smartlist_t *digests, int flav,
4004 unsigned compression_methods,
4005 compress_method_t *compression_used_out)
4007 struct consensus_cache_entry_t *result = NULL;
4009 SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, diff_from) {
4010 unsigned u;
4011 for (u = 0; u < ARRAY_LENGTH(srv_meth_pref_precompressed); ++u) {
4012 compress_method_t method = srv_meth_pref_precompressed[u];
4013 if (0 == (compression_methods & (1u<<method)))
4014 continue; // client doesn't like this one, or we don't have it.
4015 if (consdiffmgr_find_diff_from(&result, flav, DIGEST_SHA3_256,
4016 diff_from, DIGEST256_LEN,
4017 method) == CONSDIFF_AVAILABLE) {
4018 tor_assert_nonfatal(result);
4019 *compression_used_out = method;
4020 return result;
4023 } SMARTLIST_FOREACH_END(diff_from);
4025 SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, diff_from) {
4026 if (consdiffmgr_find_diff_from(&result, flav, DIGEST_SHA3_256, diff_from,
4027 DIGEST256_LEN, FALLBACK_COMPRESS_METHOD) == CONSDIFF_AVAILABLE) {
4028 tor_assert_nonfatal(result);
4029 *compression_used_out = FALLBACK_COMPRESS_METHOD;
4030 return result;
4032 } SMARTLIST_FOREACH_END(diff_from);
4034 return NULL;
4037 /** Lookup the cached consensus document by the flavor found in <b>flav</b>.
4038 * The prefered set of compression methods should be listed in the
4039 * <b>compression_methods</b> bitfield. The compression method chosen (if any)
4040 * is stored in <b>compression_used_out</b>. */
4041 static struct consensus_cache_entry_t *
4042 find_best_consensus(int flav,
4043 unsigned compression_methods,
4044 compress_method_t *compression_used_out)
4046 struct consensus_cache_entry_t *result = NULL;
4047 unsigned u;
4049 for (u = 0; u < ARRAY_LENGTH(srv_meth_pref_precompressed); ++u) {
4050 compress_method_t method = srv_meth_pref_precompressed[u];
4052 if (0 == (compression_methods & (1u<<method)))
4053 continue;
4055 if (consdiffmgr_find_consensus(&result, flav,
4056 method) == CONSDIFF_AVAILABLE) {
4057 tor_assert_nonfatal(result);
4058 *compression_used_out = method;
4059 return result;
4063 if (consdiffmgr_find_consensus(&result, flav,
4064 FALLBACK_COMPRESS_METHOD) == CONSDIFF_AVAILABLE) {
4065 tor_assert_nonfatal(result);
4066 *compression_used_out = FALLBACK_COMPRESS_METHOD;
4067 return result;
4070 return NULL;
4073 /** Try to find the best supported compression method possible from a given
4074 * <b>compression_methods</b>. Return NO_METHOD if no mutually supported
4075 * compression method could be found. */
4076 static compress_method_t
4077 find_best_compression_method(unsigned compression_methods, int stream)
4079 unsigned u;
4080 compress_method_t *methods;
4081 size_t length;
4083 if (stream) {
4084 methods = srv_meth_pref_streaming_compression;
4085 length = ARRAY_LENGTH(srv_meth_pref_streaming_compression);
4086 } else {
4087 methods = srv_meth_pref_precompressed;
4088 length = ARRAY_LENGTH(srv_meth_pref_precompressed);
4091 for (u = 0; u < length; ++u) {
4092 compress_method_t method = methods[u];
4093 if (compression_methods & (1u<<method))
4094 return method;
4097 return NO_METHOD;
4100 /** Check if any of the digests in <b>digests</b> matches the latest consensus
4101 * flavor (given in <b>flavor</b>) that we have available. */
4102 static int
4103 digest_list_contains_best_consensus(consensus_flavor_t flavor,
4104 const smartlist_t *digests)
4106 const networkstatus_t *ns = NULL;
4108 if (digests == NULL)
4109 return 0;
4111 ns = networkstatus_get_latest_consensus_by_flavor(flavor);
4113 if (ns == NULL)
4114 return 0;
4116 SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, digest) {
4117 if (tor_memeq(ns->digest_sha3_as_signed, digest, DIGEST256_LEN))
4118 return 1;
4119 } SMARTLIST_FOREACH_END(digest);
4121 return 0;
4124 /** Check if the given compression method is allowed for a connection that is
4125 * supposed to be anonymous. Returns 1 if the compression method is allowed,
4126 * otherwise 0. */
4127 STATIC int
4128 allowed_anonymous_connection_compression_method(compress_method_t method)
4130 unsigned u;
4132 for (u = 0; u < ARRAY_LENGTH(client_meth_allowed_anonymous_compression);
4133 ++u) {
4134 compress_method_t allowed_method =
4135 client_meth_allowed_anonymous_compression[u];
4137 if (! tor_compress_supports_method(allowed_method))
4138 continue;
4140 if (method == allowed_method)
4141 return 1;
4144 return 0;
4147 /** Log a warning when a remote server has sent us a document using a
4148 * compression method that is not allowed for anonymous directory requests. */
4149 STATIC void
4150 warn_disallowed_anonymous_compression_method(compress_method_t method)
4152 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
4153 "Received a %s HTTP response, which is not "
4154 "allowed for anonymous directory requests.",
4155 compression_method_get_human_name(method));
4158 /** Encodes the results of parsing a consensus request to figure out what
4159 * consensus, and possibly what diffs, the user asked for. */
4160 typedef struct {
4161 /** name of the flavor to retrieve. */
4162 char *flavor;
4163 /** flavor to retrive, as enum. */
4164 consensus_flavor_t flav;
4165 /** plus-separated list of authority fingerprints; see
4166 * client_likes_consensus(). Aliases the URL in the request passed to
4167 * parse_consensus_request(). */
4168 const char *want_fps;
4169 /** Optionally, a smartlist of sha3 digests-as-signed of the consensuses
4170 * to return a diff from. */
4171 smartlist_t *diff_from_digests;
4172 /** If true, never send a full consensus. If there is no diff, send
4173 * a 404 instead. */
4174 int diff_only;
4175 } parsed_consensus_request_t;
4177 /** Remove all data held in <b>req</b>. Do not free <b>req</b> itself, since
4178 * it is stack-allocated. */
4179 static void
4180 parsed_consensus_request_clear(parsed_consensus_request_t *req)
4182 if (!req)
4183 return;
4184 tor_free(req->flavor);
4185 if (req->diff_from_digests) {
4186 SMARTLIST_FOREACH(req->diff_from_digests, uint8_t *, d, tor_free(d));
4187 smartlist_free(req->diff_from_digests);
4189 memset(req, 0, sizeof(parsed_consensus_request_t));
4193 * Parse the URL and relevant headers of <b>args</b> for a current-consensus
4194 * request to learn what flavor of consensus we want, what keys it must be
4195 * signed with, and what diffs we would accept (or demand) instead. Return 0
4196 * on success and -1 on failure.
4198 static int
4199 parse_consensus_request(parsed_consensus_request_t *out,
4200 const get_handler_args_t *args)
4202 const char *url = args->url;
4203 memset(out, 0, sizeof(parsed_consensus_request_t));
4204 out->flav = FLAV_NS;
4206 const char CONSENSUS_URL_PREFIX[] = "/tor/status-vote/current/consensus/";
4207 const char CONSENSUS_FLAVORED_PREFIX[] =
4208 "/tor/status-vote/current/consensus-";
4210 /* figure out the flavor if any, and who we wanted to sign the thing */
4211 const char *after_flavor = NULL;
4213 if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) {
4214 const char *f, *cp;
4215 f = url + strlen(CONSENSUS_FLAVORED_PREFIX);
4216 cp = strchr(f, '/');
4217 if (cp) {
4218 after_flavor = cp+1;
4219 out->flavor = tor_strndup(f, cp-f);
4220 } else {
4221 out->flavor = tor_strdup(f);
4223 int flav = networkstatus_parse_flavor_name(out->flavor);
4224 if (flav < 0)
4225 flav = FLAV_NS;
4226 out->flav = flav;
4227 } else {
4228 if (!strcmpstart(url, CONSENSUS_URL_PREFIX))
4229 after_flavor = url+strlen(CONSENSUS_URL_PREFIX);
4232 /* see whether we've been asked explicitly for a diff from an older
4233 * consensus. (The user might also have said that a diff would be okay,
4234 * via X-Or-Diff-From-Consensus */
4235 const char DIFF_COMPONENT[] = "diff/";
4236 char *diff_hash_in_url = NULL;
4237 if (after_flavor && !strcmpstart(after_flavor, DIFF_COMPONENT)) {
4238 after_flavor += strlen(DIFF_COMPONENT);
4239 const char *cp = strchr(after_flavor, '/');
4240 if (cp) {
4241 diff_hash_in_url = tor_strndup(after_flavor, cp-after_flavor);
4242 out->want_fps = cp+1;
4243 } else {
4244 diff_hash_in_url = tor_strdup(after_flavor);
4245 out->want_fps = NULL;
4247 } else {
4248 out->want_fps = after_flavor;
4251 if (diff_hash_in_url) {
4252 uint8_t diff_from[DIGEST256_LEN];
4253 out->diff_from_digests = smartlist_new();
4254 out->diff_only = 1;
4255 int ok = !parse_one_diff_hash(diff_from, diff_hash_in_url, "URL",
4256 "rejecting");
4257 tor_free(diff_hash_in_url);
4258 if (ok) {
4259 smartlist_add(out->diff_from_digests,
4260 tor_memdup(diff_from, DIGEST256_LEN));
4261 } else {
4262 return -1;
4264 } else {
4265 parse_or_diff_from_header(&out->diff_from_digests, args->headers);
4268 return 0;
4271 /** Helper function for GET /tor/status-vote/current/consensus
4273 static int
4274 handle_get_current_consensus(dir_connection_t *conn,
4275 const get_handler_args_t *args)
4277 const compress_method_t compress_method =
4278 find_best_compression_method(args->compression_supported, 0);
4279 const time_t if_modified_since = args->if_modified_since;
4280 int clear_spool = 0;
4282 /* v3 network status fetch. */
4283 long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
4285 time_t now = time(NULL);
4286 parsed_consensus_request_t req;
4288 if (parse_consensus_request(&req, args) < 0) {
4289 write_http_status_line(conn, 404, "Couldn't parse request");
4290 goto done;
4293 if (digest_list_contains_best_consensus(req.flav,
4294 req.diff_from_digests)) {
4295 write_http_status_line(conn, 304, "Not modified");
4296 geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
4297 goto done;
4300 struct consensus_cache_entry_t *cached_consensus = NULL;
4302 compress_method_t compression_used = NO_METHOD;
4303 if (req.diff_from_digests) {
4304 cached_consensus = find_best_diff(req.diff_from_digests, req.flav,
4305 args->compression_supported,
4306 &compression_used);
4309 if (req.diff_only && !cached_consensus) {
4310 write_http_status_line(conn, 404, "No such diff available");
4311 // XXXX warn_consensus_is_too_old(v, req.flavor, now);
4312 geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
4313 goto done;
4316 if (! cached_consensus) {
4317 cached_consensus = find_best_consensus(req.flav,
4318 args->compression_supported,
4319 &compression_used);
4322 time_t fresh_until, valid_until;
4323 int have_fresh_until = 0, have_valid_until = 0;
4324 if (cached_consensus) {
4325 have_fresh_until =
4326 !consensus_cache_entry_get_fresh_until(cached_consensus, &fresh_until);
4327 have_valid_until =
4328 !consensus_cache_entry_get_valid_until(cached_consensus, &valid_until);
4331 if (cached_consensus && have_valid_until &&
4332 !networkstatus_valid_until_is_reasonably_live(valid_until, now)) {
4333 write_http_status_line(conn, 404, "Consensus is too old");
4334 warn_consensus_is_too_old(cached_consensus, req.flavor, now);
4335 geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
4336 goto done;
4339 if (cached_consensus && req.want_fps &&
4340 !client_likes_consensus(cached_consensus, req.want_fps)) {
4341 write_http_status_line(conn, 404, "Consensus not signed by sufficient "
4342 "number of requested authorities");
4343 geoip_note_ns_response(GEOIP_REJECT_NOT_ENOUGH_SIGS);
4344 goto done;
4347 conn->spool = smartlist_new();
4348 clear_spool = 1;
4350 spooled_resource_t *spooled;
4351 if (cached_consensus) {
4352 spooled = spooled_resource_new_from_cache_entry(cached_consensus);
4353 smartlist_add(conn->spool, spooled);
4357 lifetime = (have_fresh_until && fresh_until > now) ? fresh_until - now : 0;
4359 size_t size_guess = 0;
4360 int n_expired = 0;
4361 dirserv_spool_remove_missing_and_guess_size(conn, if_modified_since,
4362 compress_method != NO_METHOD,
4363 &size_guess,
4364 &n_expired);
4366 if (!smartlist_len(conn->spool) && !n_expired) {
4367 write_http_status_line(conn, 404, "Not found");
4368 geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
4369 goto done;
4370 } else if (!smartlist_len(conn->spool)) {
4371 write_http_status_line(conn, 304, "Not modified");
4372 geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
4373 goto done;
4376 if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
4377 log_debug(LD_DIRSERV,
4378 "Client asked for network status lists, but we've been "
4379 "writing too many bytes lately. Sending 503 Dir busy.");
4380 write_http_status_line(conn, 503, "Directory busy, try again later");
4381 geoip_note_ns_response(GEOIP_REJECT_BUSY);
4382 goto done;
4385 tor_addr_t addr;
4386 if (tor_addr_parse(&addr, (TO_CONN(conn))->address) >= 0) {
4387 geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS,
4388 &addr, NULL,
4389 time(NULL));
4390 geoip_note_ns_response(GEOIP_SUCCESS);
4391 /* Note that a request for a network status has started, so that we
4392 * can measure the download time later on. */
4393 if (conn->dirreq_id)
4394 geoip_start_dirreq(conn->dirreq_id, size_guess, DIRREQ_TUNNELED);
4395 else
4396 geoip_start_dirreq(TO_CONN(conn)->global_identifier, size_guess,
4397 DIRREQ_DIRECT);
4400 /* Use this header to tell caches that the response depends on the
4401 * X-Or-Diff-From-Consensus header (or lack thereof). */
4402 const char vary_header[] = "Vary: X-Or-Diff-From-Consensus\r\n";
4404 clear_spool = 0;
4406 // The compress_method might have been NO_METHOD, but we store the data
4407 // compressed. Decompress them using `compression_used`. See fallback code in
4408 // find_best_consensus() and find_best_diff().
4409 write_http_response_headers(conn, -1,
4410 compress_method == NO_METHOD ?
4411 NO_METHOD : compression_used,
4412 vary_header,
4413 smartlist_len(conn->spool) == 1 ? lifetime : 0);
4415 if (compress_method == NO_METHOD && smartlist_len(conn->spool))
4416 conn->compress_state = tor_compress_new(0, compression_used,
4417 HIGH_COMPRESSION);
4419 /* Prime the connection with some data. */
4420 const int initial_flush_result = connection_dirserv_flushed_some(conn);
4421 tor_assert_nonfatal(initial_flush_result == 0);
4422 goto done;
4424 done:
4425 parsed_consensus_request_clear(&req);
4426 if (clear_spool) {
4427 dir_conn_clear_spool(conn);
4429 return 0;
4432 /** Helper function for GET /tor/status-vote/{current,next}/...
4434 static int
4435 handle_get_status_vote(dir_connection_t *conn, const get_handler_args_t *args)
4437 const char *url = args->url;
4439 int current;
4440 ssize_t body_len = 0;
4441 ssize_t estimated_len = 0;
4442 /* This smartlist holds strings that we can compress on the fly. */
4443 smartlist_t *items = smartlist_new();
4444 /* This smartlist holds cached_dir_t objects that have a precompressed
4445 * deflated version. */
4446 smartlist_t *dir_items = smartlist_new();
4447 int lifetime = 60; /* XXXX?? should actually use vote intervals. */
4448 url += strlen("/tor/status-vote/");
4449 current = !strcmpstart(url, "current/");
4450 url = strchr(url, '/');
4451 tor_assert(url);
4452 ++url;
4453 if (!strcmp(url, "consensus")) {
4454 const char *item;
4455 tor_assert(!current); /* we handle current consensus specially above,
4456 * since it wants to be spooled. */
4457 if ((item = dirvote_get_pending_consensus(FLAV_NS)))
4458 smartlist_add(items, (char*)item);
4459 } else if (!current && !strcmp(url, "consensus-signatures")) {
4460 /* XXXX the spec says that we should implement
4461 * current/consensus-signatures too. It doesn't seem to be needed,
4462 * though. */
4463 const char *item;
4464 if ((item=dirvote_get_pending_detached_signatures()))
4465 smartlist_add(items, (char*)item);
4466 } else if (!strcmp(url, "authority")) {
4467 const cached_dir_t *d;
4468 int flags = DGV_BY_ID |
4469 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
4470 if ((d=dirvote_get_vote(NULL, flags)))
4471 smartlist_add(dir_items, (cached_dir_t*)d);
4472 } else {
4473 const cached_dir_t *d;
4474 smartlist_t *fps = smartlist_new();
4475 int flags;
4476 if (!strcmpstart(url, "d/")) {
4477 url += 2;
4478 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
4479 } else {
4480 flags = DGV_BY_ID |
4481 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
4483 dir_split_resource_into_fingerprints(url, fps, NULL,
4484 DSR_HEX|DSR_SORT_UNIQ);
4485 SMARTLIST_FOREACH(fps, char *, fp, {
4486 if ((d = dirvote_get_vote(fp, flags)))
4487 smartlist_add(dir_items, (cached_dir_t*)d);
4488 tor_free(fp);
4490 smartlist_free(fps);
4492 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
4493 write_http_status_line(conn, 404, "Not found");
4494 goto vote_done;
4497 /* We're sending items from at most one kind of source */
4498 tor_assert_nonfatal(smartlist_len(items) == 0 ||
4499 smartlist_len(dir_items) == 0);
4501 int streaming;
4502 unsigned mask;
4503 if (smartlist_len(items)) {
4504 /* We're taking strings and compressing them on the fly. */
4505 streaming = 1;
4506 mask = ~0u;
4507 } else {
4508 /* We're taking cached_dir_t objects. We only have them uncompressed
4509 * or deflated. */
4510 streaming = 0;
4511 mask = (1u<<NO_METHOD) | (1u<<ZLIB_METHOD);
4513 const compress_method_t compress_method = find_best_compression_method(
4514 args->compression_supported&mask, streaming);
4516 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
4517 body_len += compress_method != NO_METHOD ?
4518 d->dir_compressed_len : d->dir_len);
4519 estimated_len += body_len;
4520 SMARTLIST_FOREACH(items, const char *, item, {
4521 size_t ln = strlen(item);
4522 if (compress_method != NO_METHOD) {
4523 estimated_len += ln/2;
4524 } else {
4525 body_len += ln; estimated_len += ln;
4529 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
4530 write_http_status_line(conn, 503, "Directory busy, try again later");
4531 goto vote_done;
4533 write_http_response_header(conn, body_len ? body_len : -1,
4534 compress_method,
4535 lifetime);
4537 if (smartlist_len(items)) {
4538 if (compress_method != NO_METHOD) {
4539 conn->compress_state = tor_compress_new(1, compress_method,
4540 choose_compression_level(estimated_len));
4541 SMARTLIST_FOREACH(items, const char *, c,
4542 connection_write_to_buf_compress(c, strlen(c), conn, 0));
4543 connection_write_to_buf_compress("", 0, conn, 1);
4544 } else {
4545 SMARTLIST_FOREACH(items, const char *, c,
4546 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
4548 } else {
4549 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
4550 connection_write_to_buf(compress_method != NO_METHOD ?
4551 d->dir_compressed : d->dir,
4552 compress_method != NO_METHOD ?
4553 d->dir_compressed_len : d->dir_len,
4554 TO_CONN(conn)));
4556 vote_done:
4557 smartlist_free(items);
4558 smartlist_free(dir_items);
4559 goto done;
4561 done:
4562 return 0;
4565 /** Helper function for GET /tor/micro/d/...
4567 static int
4568 handle_get_microdesc(dir_connection_t *conn, const get_handler_args_t *args)
4570 const char *url = args->url;
4571 const compress_method_t compress_method =
4572 find_best_compression_method(args->compression_supported, 1);
4573 int clear_spool = 1;
4575 conn->spool = smartlist_new();
4577 dir_split_resource_into_spoolable(url+strlen("/tor/micro/d/"),
4578 DIR_SPOOL_MICRODESC,
4579 conn->spool, NULL,
4580 DSR_DIGEST256|DSR_BASE64|DSR_SORT_UNIQ);
4582 size_t size_guess = 0;
4583 dirserv_spool_remove_missing_and_guess_size(conn, 0,
4584 compress_method != NO_METHOD,
4585 &size_guess, NULL);
4586 if (smartlist_len(conn->spool) == 0) {
4587 write_http_status_line(conn, 404, "Not found");
4588 goto done;
4590 if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
4591 log_info(LD_DIRSERV,
4592 "Client asked for server descriptors, but we've been "
4593 "writing too many bytes lately. Sending 503 Dir busy.");
4594 write_http_status_line(conn, 503, "Directory busy, try again later");
4595 goto done;
4598 clear_spool = 0;
4599 write_http_response_header(conn, -1,
4600 compress_method,
4601 MICRODESC_CACHE_LIFETIME);
4603 if (compress_method != NO_METHOD)
4604 conn->compress_state = tor_compress_new(1, compress_method,
4605 choose_compression_level(size_guess));
4607 const int initial_flush_result = connection_dirserv_flushed_some(conn);
4608 tor_assert_nonfatal(initial_flush_result == 0);
4609 goto done;
4612 done:
4613 if (clear_spool) {
4614 dir_conn_clear_spool(conn);
4616 return 0;
4619 /** Helper function for GET /tor/{server,extra}/...
4621 static int
4622 handle_get_descriptor(dir_connection_t *conn, const get_handler_args_t *args)
4624 const char *url = args->url;
4625 const compress_method_t compress_method =
4626 find_best_compression_method(args->compression_supported, 1);
4627 const or_options_t *options = get_options();
4628 int clear_spool = 1;
4629 if (!strcmpstart(url,"/tor/server/") ||
4630 (!options->BridgeAuthoritativeDir &&
4631 !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
4632 int res;
4633 const char *msg = NULL;
4634 int cache_lifetime = 0;
4635 int is_extra = !strcmpstart(url,"/tor/extra/");
4636 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
4637 dir_spool_source_t source;
4638 time_t publish_cutoff = 0;
4639 if (!strcmpstart(url, "d/")) {
4640 source =
4641 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
4642 } else {
4643 source =
4644 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
4645 /* We only want to apply a publish cutoff when we're requesting
4646 * resources by fingerprint. */
4647 publish_cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
4650 conn->spool = smartlist_new();
4651 res = dirserv_get_routerdesc_spool(conn->spool, url,
4652 source,
4653 connection_dir_is_encrypted(conn),
4654 &msg);
4656 if (!strcmpstart(url, "all")) {
4657 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
4658 } else if (smartlist_len(conn->spool) == 1) {
4659 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
4662 size_t size_guess = 0;
4663 int n_expired = 0;
4664 dirserv_spool_remove_missing_and_guess_size(conn, publish_cutoff,
4665 compress_method != NO_METHOD,
4666 &size_guess, &n_expired);
4668 /* If we are the bridge authority and the descriptor is a bridge
4669 * descriptor, remember that we served this descriptor for desc stats. */
4670 /* XXXX it's a bit of a kludge to have this here. */
4671 if (get_options()->BridgeAuthoritativeDir &&
4672 source == DIR_SPOOL_SERVER_BY_FP) {
4673 SMARTLIST_FOREACH_BEGIN(conn->spool, spooled_resource_t *, spooled) {
4674 const routerinfo_t *router =
4675 router_get_by_id_digest((const char *)spooled->digest);
4676 /* router can be NULL here when the bridge auth is asked for its own
4677 * descriptor. */
4678 if (router && router->purpose == ROUTER_PURPOSE_BRIDGE)
4679 rep_hist_note_desc_served(router->cache_info.identity_digest);
4680 } SMARTLIST_FOREACH_END(spooled);
4683 if (res < 0 || size_guess == 0 || smartlist_len(conn->spool) == 0) {
4684 if (msg == NULL)
4685 msg = "Not found";
4686 write_http_status_line(conn, 404, msg);
4687 } else {
4688 if (global_write_bucket_low(TO_CONN(conn), size_guess, 2)) {
4689 log_info(LD_DIRSERV,
4690 "Client asked for server descriptors, but we've been "
4691 "writing too many bytes lately. Sending 503 Dir busy.");
4692 write_http_status_line(conn, 503, "Directory busy, try again later");
4693 dir_conn_clear_spool(conn);
4694 goto done;
4696 write_http_response_header(conn, -1, compress_method, cache_lifetime);
4697 if (compress_method != NO_METHOD)
4698 conn->compress_state = tor_compress_new(1, compress_method,
4699 choose_compression_level(size_guess));
4700 clear_spool = 0;
4701 /* Prime the connection with some data. */
4702 int initial_flush_result = connection_dirserv_flushed_some(conn);
4703 tor_assert_nonfatal(initial_flush_result == 0);
4705 goto done;
4707 done:
4708 if (clear_spool)
4709 dir_conn_clear_spool(conn);
4710 return 0;
4713 /** Helper function for GET /tor/keys/...
4715 static int
4716 handle_get_keys(dir_connection_t *conn, const get_handler_args_t *args)
4718 const char *url = args->url;
4719 const compress_method_t compress_method =
4720 find_best_compression_method(args->compression_supported, 1);
4721 const time_t if_modified_since = args->if_modified_since;
4723 smartlist_t *certs = smartlist_new();
4724 ssize_t len = -1;
4725 if (!strcmp(url, "/tor/keys/all")) {
4726 authority_cert_get_all(certs);
4727 } else if (!strcmp(url, "/tor/keys/authority")) {
4728 authority_cert_t *cert = get_my_v3_authority_cert();
4729 if (cert)
4730 smartlist_add(certs, cert);
4731 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
4732 smartlist_t *fps = smartlist_new();
4733 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
4734 fps, NULL,
4735 DSR_HEX|DSR_SORT_UNIQ);
4736 SMARTLIST_FOREACH(fps, char *, d, {
4737 authority_cert_t *c = authority_cert_get_newest_by_id(d);
4738 if (c) smartlist_add(certs, c);
4739 tor_free(d);
4741 smartlist_free(fps);
4742 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
4743 smartlist_t *fps = smartlist_new();
4744 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
4745 fps, NULL,
4746 DSR_HEX|DSR_SORT_UNIQ);
4747 SMARTLIST_FOREACH(fps, char *, d, {
4748 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
4749 if (c) smartlist_add(certs, c);
4750 tor_free(d);
4752 smartlist_free(fps);
4753 } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
4754 smartlist_t *fp_sks = smartlist_new();
4755 dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
4756 fp_sks);
4757 SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
4758 authority_cert_t *c = authority_cert_get_by_digests(pair->first,
4759 pair->second);
4760 if (c) smartlist_add(certs, c);
4761 tor_free(pair);
4763 smartlist_free(fp_sks);
4764 } else {
4765 write_http_status_line(conn, 400, "Bad request");
4766 goto keys_done;
4768 if (!smartlist_len(certs)) {
4769 write_http_status_line(conn, 404, "Not found");
4770 goto keys_done;
4772 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
4773 if (c->cache_info.published_on < if_modified_since)
4774 SMARTLIST_DEL_CURRENT(certs, c));
4775 if (!smartlist_len(certs)) {
4776 write_http_status_line(conn, 304, "Not modified");
4777 goto keys_done;
4779 len = 0;
4780 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
4781 len += c->cache_info.signed_descriptor_len);
4783 if (global_write_bucket_low(TO_CONN(conn),
4784 compress_method != NO_METHOD ? len/2 : len,
4785 2)) {
4786 write_http_status_line(conn, 503, "Directory busy, try again later");
4787 goto keys_done;
4790 write_http_response_header(conn,
4791 compress_method != NO_METHOD ? -1 : len,
4792 compress_method,
4793 60*60);
4794 if (compress_method != NO_METHOD) {
4795 conn->compress_state = tor_compress_new(1, compress_method,
4796 choose_compression_level(len));
4797 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
4798 connection_write_to_buf_compress(
4799 c->cache_info.signed_descriptor_body,
4800 c->cache_info.signed_descriptor_len,
4801 conn, 0));
4802 connection_write_to_buf_compress("", 0, conn, 1);
4803 } else {
4804 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
4805 connection_write_to_buf(c->cache_info.signed_descriptor_body,
4806 c->cache_info.signed_descriptor_len,
4807 TO_CONN(conn)));
4809 keys_done:
4810 smartlist_free(certs);
4811 goto done;
4813 done:
4814 return 0;
4817 /** Helper function for GET /tor/rendezvous2/
4819 static int
4820 handle_get_hs_descriptor_v2(dir_connection_t *conn,
4821 const get_handler_args_t *args)
4823 const char *url = args->url;
4824 if (connection_dir_is_encrypted(conn)) {
4825 /* Handle v2 rendezvous descriptor fetch request. */
4826 const char *descp;
4827 const char *query = url + strlen("/tor/rendezvous2/");
4828 if (rend_valid_descriptor_id(query)) {
4829 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
4830 safe_str(escaped(query)));
4831 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
4832 case 1: /* valid */
4833 write_http_response_header(conn, strlen(descp), NO_METHOD, 0);
4834 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
4835 break;
4836 case 0: /* well-formed but not present */
4837 write_http_status_line(conn, 404, "Not found");
4838 break;
4839 case -1: /* not well-formed */
4840 write_http_status_line(conn, 400, "Bad request");
4841 break;
4843 } else { /* not well-formed */
4844 write_http_status_line(conn, 400, "Bad request");
4846 goto done;
4847 } else {
4848 /* Not encrypted! */
4849 write_http_status_line(conn, 404, "Not found");
4851 done:
4852 return 0;
4855 /** Helper function for GET /tor/hs/3/<z>. Only for version 3.
4857 STATIC int
4858 handle_get_hs_descriptor_v3(dir_connection_t *conn,
4859 const get_handler_args_t *args)
4861 int retval;
4862 const char *desc_str = NULL;
4863 const char *pubkey_str = NULL;
4864 const char *url = args->url;
4866 /* Reject unencrypted dir connections */
4867 if (!connection_dir_is_encrypted(conn)) {
4868 write_http_status_line(conn, 404, "Not found");
4869 goto done;
4872 /* After the path prefix follows the base64 encoded blinded pubkey which we
4873 * use to get the descriptor from the cache. Skip the prefix and get the
4874 * pubkey. */
4875 tor_assert(!strcmpstart(url, "/tor/hs/3/"));
4876 pubkey_str = url + strlen("/tor/hs/3/");
4877 retval = hs_cache_lookup_as_dir(HS_VERSION_THREE,
4878 pubkey_str, &desc_str);
4879 if (retval <= 0 || desc_str == NULL) {
4880 write_http_status_line(conn, 404, "Not found");
4881 goto done;
4884 /* Found requested descriptor! Pass it to this nice client. */
4885 write_http_response_header(conn, strlen(desc_str), NO_METHOD, 0);
4886 connection_write_to_buf(desc_str, strlen(desc_str), TO_CONN(conn));
4888 done:
4889 return 0;
4892 /** Helper function for GET /tor/networkstatus-bridges
4894 static int
4895 handle_get_networkstatus_bridges(dir_connection_t *conn,
4896 const get_handler_args_t *args)
4898 const char *headers = args->headers;
4900 const or_options_t *options = get_options();
4901 if (options->BridgeAuthoritativeDir &&
4902 options->BridgePassword_AuthDigest_ &&
4903 connection_dir_is_encrypted(conn)) {
4904 char *status;
4905 char digest[DIGEST256_LEN];
4907 char *header = http_get_header(headers, "Authorization: Basic ");
4908 if (header)
4909 crypto_digest256(digest, header, strlen(header), DIGEST_SHA256);
4911 /* now make sure the password is there and right */
4912 if (!header ||
4913 tor_memneq(digest,
4914 options->BridgePassword_AuthDigest_, DIGEST256_LEN)) {
4915 write_http_status_line(conn, 404, "Not found");
4916 tor_free(header);
4917 goto done;
4919 tor_free(header);
4921 /* all happy now. send an answer. */
4922 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
4923 size_t dlen = strlen(status);
4924 write_http_response_header(conn, dlen, NO_METHOD, 0);
4925 connection_write_to_buf(status, dlen, TO_CONN(conn));
4926 tor_free(status);
4927 goto done;
4929 done:
4930 return 0;
4933 /** Helper function for GET robots.txt or /tor/robots.txt */
4934 static int
4935 handle_get_robots(dir_connection_t *conn, const get_handler_args_t *args)
4937 (void)args;
4939 const char robots[] = "User-agent: *\r\nDisallow: /\r\n";
4940 size_t len = strlen(robots);
4941 write_http_response_header(conn, len, NO_METHOD, ROBOTS_CACHE_LIFETIME);
4942 connection_write_to_buf(robots, len, TO_CONN(conn));
4944 return 0;
4947 /* Given the <b>url</b> from a POST request, try to extract the version number
4948 * using the provided <b>prefix</b>. The version should be after the prefix and
4949 * ending with the seperator "/". For instance:
4950 * /tor/hs/3/publish
4952 * On success, <b>end_pos</b> points to the position right after the version
4953 * was found. On error, it is set to NULL.
4955 * Return version on success else negative value. */
4956 STATIC int
4957 parse_hs_version_from_post(const char *url, const char *prefix,
4958 const char **end_pos)
4960 int ok;
4961 unsigned long version;
4962 const char *start;
4963 char *end = NULL;
4965 tor_assert(url);
4966 tor_assert(prefix);
4967 tor_assert(end_pos);
4969 /* Check if the prefix does start the url. */
4970 if (strcmpstart(url, prefix)) {
4971 goto err;
4973 /* Move pointer to the end of the prefix string. */
4974 start = url + strlen(prefix);
4975 /* Try this to be the HS version and if we are still at the separator, next
4976 * will be move to the right value. */
4977 version = tor_parse_long(start, 10, 0, INT_MAX, &ok, &end);
4978 if (!ok) {
4979 goto err;
4982 *end_pos = end;
4983 return (int) version;
4984 err:
4985 *end_pos = NULL;
4986 return -1;
4989 /* Handle the POST request for a hidden service descripror. The request is in
4990 * <b>url</b>, the body of the request is in <b>body</b>. Return 200 on success
4991 * else return 400 indicating a bad request. */
4992 STATIC int
4993 handle_post_hs_descriptor(const char *url, const char *body)
4995 int version;
4996 const char *end_pos;
4998 tor_assert(url);
4999 tor_assert(body);
5001 version = parse_hs_version_from_post(url, "/tor/hs/", &end_pos);
5002 if (version < 0) {
5003 goto err;
5006 /* We have a valid version number, now make sure it's a publish request. Use
5007 * the end position just after the version and check for the command. */
5008 if (strcmpstart(end_pos, "/publish")) {
5009 goto err;
5012 switch (version) {
5013 case HS_VERSION_THREE:
5014 if (hs_cache_store_as_dir(body) < 0) {
5015 goto err;
5017 log_info(LD_REND, "Publish request for HS descriptor handled "
5018 "successfully.");
5019 break;
5020 default:
5021 /* Unsupported version, return a bad request. */
5022 goto err;
5025 return 200;
5026 err:
5027 /* Bad request. */
5028 return 400;
5031 /** Helper function: called when a dirserver gets a complete HTTP POST
5032 * request. Look for an uploaded server descriptor or rendezvous
5033 * service descriptor. On finding one, process it and write a
5034 * response into conn-\>outbuf. If the request is unrecognized, send a
5035 * 400. Always return 0. */
5036 MOCK_IMPL(STATIC int,
5037 directory_handle_command_post,(dir_connection_t *conn, const char *headers,
5038 const char *body, size_t body_len))
5040 char *url = NULL;
5041 const or_options_t *options = get_options();
5043 log_debug(LD_DIRSERV,"Received POST command.");
5045 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
5047 if (!public_server_mode(options)) {
5048 log_info(LD_DIR, "Rejected dir post request from %s "
5049 "since we're not a public relay.", conn->base_.address);
5050 write_http_status_line(conn, 503, "Not acting as a public relay");
5051 goto done;
5054 if (parse_http_url(headers, &url) < 0) {
5055 write_http_status_line(conn, 400, "Bad request");
5056 return 0;
5058 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
5060 /* Handle v2 rendezvous service publish request. */
5061 if (connection_dir_is_encrypted(conn) &&
5062 !strcmpstart(url,"/tor/rendezvous2/publish")) {
5063 if (rend_cache_store_v2_desc_as_dir(body) < 0) {
5064 log_warn(LD_REND, "Rejected v2 rend descriptor (body size %d) from %s.",
5065 (int)body_len, conn->base_.address);
5066 write_http_status_line(conn, 400,
5067 "Invalid v2 service descriptor rejected");
5068 } else {
5069 write_http_status_line(conn, 200, "Service descriptor (v2) stored");
5070 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
5072 goto done;
5075 /* Handle HS descriptor publish request. */
5076 /* XXX: This should be disabled with a consensus param until we want to
5077 * the prop224 be deployed and thus use. */
5078 if (connection_dir_is_encrypted(conn) && !strcmpstart(url, "/tor/hs/")) {
5079 const char *msg = "HS descriptor stored successfully.";
5081 /* We most probably have a publish request for an HS descriptor. */
5082 int code = handle_post_hs_descriptor(url, body);
5083 if (code != 200) {
5084 msg = "Invalid HS descriptor. Rejected.";
5086 write_http_status_line(conn, code, msg);
5087 goto done;
5090 if (!authdir_mode(options)) {
5091 /* we just provide cached directories; we don't want to
5092 * receive anything. */
5093 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
5094 "accept posted server descriptors");
5095 goto done;
5098 if (authdir_mode(options) &&
5099 !strcmp(url,"/tor/")) { /* server descriptor post */
5100 const char *msg = "[None]";
5101 uint8_t purpose = authdir_mode_bridge(options) ?
5102 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
5103 was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
5104 conn->base_.address, &msg);
5105 tor_assert(msg);
5107 if (r == ROUTER_ADDED_SUCCESSFULLY) {
5108 write_http_status_line(conn, 200, msg);
5109 } else if (WRA_WAS_OUTDATED(r)) {
5110 write_http_response_header_impl(conn, -1, NULL, NULL,
5111 "X-Descriptor-Not-New: Yes\r\n", -1);
5112 } else {
5113 log_info(LD_DIRSERV,
5114 "Rejected router descriptor or extra-info from %s "
5115 "(\"%s\").",
5116 conn->base_.address, msg);
5117 write_http_status_line(conn, 400, msg);
5119 goto done;
5122 if (authdir_mode_v3(options) &&
5123 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
5124 const char *msg = "OK";
5125 int status;
5126 if (dirvote_add_vote(body, &msg, &status)) {
5127 write_http_status_line(conn, status, "Vote stored");
5128 } else {
5129 tor_assert(msg);
5130 log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").",
5131 conn->base_.address, msg);
5132 write_http_status_line(conn, status, msg);
5134 goto done;
5137 if (authdir_mode_v3(options) &&
5138 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
5139 const char *msg = NULL;
5140 if (dirvote_add_signatures(body, conn->base_.address, &msg)>=0) {
5141 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
5142 } else {
5143 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
5144 conn->base_.address, msg?msg:"???");
5145 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
5147 goto done;
5150 /* we didn't recognize the url */
5151 write_http_status_line(conn, 404, "Not found");
5153 done:
5154 tor_free(url);
5155 return 0;
5158 /** Called when a dirserver receives data on a directory connection;
5159 * looks for an HTTP request. If the request is complete, remove it
5160 * from the inbuf, try to process it; otherwise, leave it on the
5161 * buffer. Return a 0 on success, or -1 on error.
5163 STATIC int
5164 directory_handle_command(dir_connection_t *conn)
5166 char *headers=NULL, *body=NULL;
5167 size_t body_len=0;
5168 int r;
5170 tor_assert(conn);
5171 tor_assert(conn->base_.type == CONN_TYPE_DIR);
5173 switch (connection_fetch_from_buf_http(TO_CONN(conn),
5174 &headers, MAX_HEADERS_SIZE,
5175 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
5176 case -1: /* overflow */
5177 log_warn(LD_DIRSERV,
5178 "Request too large from address '%s' to DirPort. Closing.",
5179 safe_str(conn->base_.address));
5180 return -1;
5181 case 0:
5182 log_debug(LD_DIRSERV,"command not all here yet.");
5183 return 0;
5184 /* case 1, fall through */
5187 http_set_address_origin(headers, TO_CONN(conn));
5188 // we should escape headers here as well,
5189 // but we can't call escaped() twice, as it uses the same buffer
5190 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, escaped(body));
5192 if (!strncasecmp(headers,"GET",3))
5193 r = directory_handle_command_get(conn, headers, body, body_len);
5194 else if (!strncasecmp(headers,"POST",4))
5195 r = directory_handle_command_post(conn, headers, body, body_len);
5196 else {
5197 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
5198 "Got headers %s with unknown command. Closing.",
5199 escaped(headers));
5200 r = -1;
5203 tor_free(headers); tor_free(body);
5204 return r;
5207 /** Write handler for directory connections; called when all data has
5208 * been flushed. Close the connection or wait for a response as
5209 * appropriate.
5212 connection_dir_finished_flushing(dir_connection_t *conn)
5214 tor_assert(conn);
5215 tor_assert(conn->base_.type == CONN_TYPE_DIR);
5217 /* Note that we have finished writing the directory response. For direct
5218 * connections this means we're done; for tunneled connections it's only
5219 * an intermediate step. */
5220 if (conn->dirreq_id)
5221 geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
5222 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
5223 else
5224 geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
5225 DIRREQ_DIRECT,
5226 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
5227 switch (conn->base_.state) {
5228 case DIR_CONN_STATE_CONNECTING:
5229 case DIR_CONN_STATE_CLIENT_SENDING:
5230 log_debug(LD_DIR,"client finished sending command.");
5231 conn->base_.state = DIR_CONN_STATE_CLIENT_READING;
5232 return 0;
5233 case DIR_CONN_STATE_SERVER_WRITING:
5234 if (conn->spool) {
5235 log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
5236 connection_mark_for_close(TO_CONN(conn));
5237 } else {
5238 log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
5239 connection_mark_for_close(TO_CONN(conn));
5241 return 0;
5242 default:
5243 log_warn(LD_BUG,"called in unexpected state %d.",
5244 conn->base_.state);
5245 tor_fragile_assert();
5246 return -1;
5248 return 0;
5251 /* We just got a new consensus! If there are other in-progress requests
5252 * for this consensus flavor (for example because we launched several in
5253 * parallel), cancel them.
5255 * We do this check here (not just in
5256 * connection_ap_handshake_attach_circuit()) to handle the edge case where
5257 * a consensus fetch begins and ends before some other one tries to attach to
5258 * a circuit, in which case the other one won't know that we're all happy now.
5260 * Don't mark the conn that just gave us the consensus -- otherwise we
5261 * would end up double-marking it when it cleans itself up.
5263 static void
5264 connection_dir_close_consensus_fetches(dir_connection_t *except_this_one,
5265 const char *resource)
5267 smartlist_t *conns_to_close =
5268 connection_dir_list_by_purpose_and_resource(DIR_PURPOSE_FETCH_CONSENSUS,
5269 resource);
5270 SMARTLIST_FOREACH_BEGIN(conns_to_close, dir_connection_t *, d) {
5271 if (d == except_this_one)
5272 continue;
5273 log_info(LD_DIR, "Closing consensus fetch (to %s) since one "
5274 "has just arrived.", TO_CONN(d)->address);
5275 connection_mark_for_close(TO_CONN(d));
5276 } SMARTLIST_FOREACH_END(d);
5277 smartlist_free(conns_to_close);
5280 /** Connected handler for directory connections: begin sending data to the
5281 * server, and return 0.
5282 * Only used when connections don't immediately connect. */
5284 connection_dir_finished_connecting(dir_connection_t *conn)
5286 tor_assert(conn);
5287 tor_assert(conn->base_.type == CONN_TYPE_DIR);
5288 tor_assert(conn->base_.state == DIR_CONN_STATE_CONNECTING);
5290 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
5291 conn->base_.address,conn->base_.port);
5293 /* start flushing conn */
5294 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
5295 return 0;
5298 /** Decide which download schedule we want to use based on descriptor type
5299 * in <b>dls</b> and <b>options</b>.
5300 * Then return a list of int pointers defining download delays in seconds.
5301 * Helper function for download_status_increment_failure(),
5302 * download_status_reset(), and download_status_increment_attempt(). */
5303 STATIC const smartlist_t *
5304 find_dl_schedule(const download_status_t *dls, const or_options_t *options)
5306 const int dir_server = dir_server_mode(options);
5307 const int multi_d = networkstatus_consensus_can_use_multiple_directories(
5308 options);
5309 const int we_are_bootstrapping = networkstatus_consensus_is_bootstrapping(
5310 time(NULL));
5311 const int use_fallbacks = networkstatus_consensus_can_use_extra_fallbacks(
5312 options);
5313 switch (dls->schedule) {
5314 case DL_SCHED_GENERIC:
5315 if (dir_server) {
5316 return options->TestingServerDownloadSchedule;
5317 } else {
5318 return options->TestingClientDownloadSchedule;
5320 case DL_SCHED_CONSENSUS:
5321 if (!multi_d) {
5322 return options->TestingServerConsensusDownloadSchedule;
5323 } else {
5324 if (we_are_bootstrapping) {
5325 if (!use_fallbacks) {
5326 /* A bootstrapping client without extra fallback directories */
5327 return
5328 options->ClientBootstrapConsensusAuthorityOnlyDownloadSchedule;
5329 } else if (dls->want_authority) {
5330 /* A bootstrapping client with extra fallback directories, but
5331 * connecting to an authority */
5332 return
5333 options->ClientBootstrapConsensusAuthorityDownloadSchedule;
5334 } else {
5335 /* A bootstrapping client connecting to extra fallback directories
5337 return
5338 options->ClientBootstrapConsensusFallbackDownloadSchedule;
5340 } else {
5341 return options->TestingClientConsensusDownloadSchedule;
5344 case DL_SCHED_BRIDGE:
5345 return options->TestingBridgeDownloadSchedule;
5346 default:
5347 tor_assert(0);
5350 /* Impossible, but gcc will fail with -Werror without a `return`. */
5351 return NULL;
5354 /** Decide which minimum and maximum delay step we want to use based on
5355 * descriptor type in <b>dls</b> and <b>options</b>.
5356 * Helper function for download_status_schedule_get_delay(). */
5357 STATIC void
5358 find_dl_min_and_max_delay(download_status_t *dls, const or_options_t *options,
5359 int *min, int *max)
5361 tor_assert(dls);
5362 tor_assert(options);
5363 tor_assert(min);
5364 tor_assert(max);
5367 * For now, just use the existing schedule config stuff and pick the
5368 * first/last entries off to get min/max delay for backoff purposes
5370 const smartlist_t *schedule = find_dl_schedule(dls, options);
5371 tor_assert(schedule != NULL && smartlist_len(schedule) >= 2);
5372 *min = *((int *)(smartlist_get(schedule, 0)));
5373 /* Increment on failure schedules always use exponential backoff, but they
5374 * have a smaller limit when they're deterministic */
5375 if (dls->backoff == DL_SCHED_DETERMINISTIC)
5376 *max = *((int *)((smartlist_get(schedule, smartlist_len(schedule) - 1))));
5377 else
5378 *max = INT_MAX;
5381 /** Advance one delay step. The algorithm is to use the previous delay to
5382 * compute an increment, we construct a value uniformly at random between
5383 * delay+1 and (delay*(DIR_DEFAULT_RANDOM_MULTIPLIER+1))+1 (or
5384 * DIR_TEST_NET_RANDOM_MULTIPLIER in test networks).
5385 * We then clamp that value to be no larger than max_delay, and return it.
5387 * Requires that delay is less than INT_MAX, and delay is in [0,max_delay].
5389 STATIC int
5390 next_random_exponential_delay(int delay, int max_delay)
5392 /* Check preconditions */
5393 if (BUG(max_delay < 0))
5394 max_delay = 0;
5395 if (BUG(delay > max_delay))
5396 delay = max_delay;
5397 if (delay == INT_MAX)
5398 return INT_MAX; /* prevent overflow */
5399 if (BUG(delay < 0))
5400 delay = 0;
5402 /* How much are we willing to add to the delay? */
5403 int max_increment;
5404 int multiplier = DIR_DEFAULT_RANDOM_MULTIPLIER;
5405 if (get_options()->TestingTorNetwork) {
5406 /* Decrease the multiplier in testing networks. This reduces the variance,
5407 * so that bootstrap is more reliable. */
5408 multiplier = DIR_TEST_NET_RANDOM_MULTIPLIER;
5411 if (delay && delay < (INT_MAX-1) / multiplier) {
5412 max_increment = delay * multiplier;
5413 } else if (delay) {
5414 max_increment = INT_MAX-1;
5415 } else {
5416 max_increment = 1;
5419 if (BUG(max_increment < 1))
5420 max_increment = 1;
5422 /* the + 1 here is so that we always wait longer than last time. */
5423 int increment = crypto_rand_int(max_increment)+1;
5425 if (increment < max_delay - delay)
5426 return delay + increment;
5427 else
5428 return max_delay;
5431 /** Find the current delay for dls based on schedule or min_delay/
5432 * max_delay if we're using exponential backoff. If dls->backoff is
5433 * DL_SCHED_RANDOM_EXPONENTIAL, we must have 0 <= min_delay <= max_delay <=
5434 * INT_MAX, but schedule may be set to NULL; otherwise schedule is required.
5435 * This function sets dls->next_attempt_at based on now, and returns the delay.
5436 * Helper for download_status_increment_failure and
5437 * download_status_increment_attempt. */
5438 STATIC int
5439 download_status_schedule_get_delay(download_status_t *dls,
5440 const smartlist_t *schedule,
5441 int min_delay, int max_delay,
5442 time_t now)
5444 tor_assert(dls);
5445 /* We don't need a schedule if we're using random exponential backoff */
5446 tor_assert(dls->backoff == DL_SCHED_RANDOM_EXPONENTIAL ||
5447 schedule != NULL);
5448 /* If we're using random exponential backoff, we do need min/max delay */
5449 tor_assert(dls->backoff != DL_SCHED_RANDOM_EXPONENTIAL ||
5450 (min_delay >= 0 && max_delay >= min_delay));
5452 int delay = INT_MAX;
5453 uint8_t dls_schedule_position = (dls->increment_on
5454 == DL_SCHED_INCREMENT_ATTEMPT
5455 ? dls->n_download_attempts
5456 : dls->n_download_failures);
5458 if (dls->backoff == DL_SCHED_DETERMINISTIC) {
5459 if (dls_schedule_position < smartlist_len(schedule))
5460 delay = *(int *)smartlist_get(schedule, dls_schedule_position);
5461 else if (dls_schedule_position == IMPOSSIBLE_TO_DOWNLOAD)
5462 delay = INT_MAX;
5463 else
5464 delay = *(int *)smartlist_get(schedule, smartlist_len(schedule) - 1);
5465 } else if (dls->backoff == DL_SCHED_RANDOM_EXPONENTIAL) {
5466 /* Check if we missed a reset somehow */
5467 IF_BUG_ONCE(dls->last_backoff_position > dls_schedule_position) {
5468 dls->last_backoff_position = 0;
5469 dls->last_delay_used = 0;
5472 if (dls_schedule_position > 0) {
5473 delay = dls->last_delay_used;
5475 while (dls->last_backoff_position < dls_schedule_position) {
5476 /* Do one increment step */
5477 delay = next_random_exponential_delay(delay, max_delay);
5478 /* Update our position */
5479 ++(dls->last_backoff_position);
5481 } else {
5482 /* If we're just starting out, use the minimum delay */
5483 delay = min_delay;
5486 /* Clamp it within min/max if we have them */
5487 if (min_delay >= 0 && delay < min_delay) delay = min_delay;
5488 if (max_delay != INT_MAX && delay > max_delay) delay = max_delay;
5490 /* Store it for next time */
5491 dls->last_backoff_position = dls_schedule_position;
5492 dls->last_delay_used = delay;
5495 /* A negative delay makes no sense. Knowing that delay is
5496 * non-negative allows us to safely do the wrapping check below. */
5497 tor_assert(delay >= 0);
5499 /* Avoid now+delay overflowing TIME_MAX, by comparing with a subtraction
5500 * that won't overflow (since delay is non-negative). */
5501 if (delay < INT_MAX && now <= TIME_MAX - delay) {
5502 dls->next_attempt_at = now+delay;
5503 } else {
5504 dls->next_attempt_at = TIME_MAX;
5507 return delay;
5510 /* Log a debug message about item, which increments on increment_action, has
5511 * incremented dls_n_download_increments times. The message varies based on
5512 * was_schedule_incremented (if not, not_incremented_response is logged), and
5513 * the values of increment, dls_next_attempt_at, and now.
5514 * Helper for download_status_increment_failure and
5515 * download_status_increment_attempt. */
5516 static void
5517 download_status_log_helper(const char *item, int was_schedule_incremented,
5518 const char *increment_action,
5519 const char *not_incremented_response,
5520 uint8_t dls_n_download_increments, int increment,
5521 time_t dls_next_attempt_at, time_t now)
5523 if (item) {
5524 if (!was_schedule_incremented)
5525 log_debug(LD_DIR, "%s %s %d time(s); I'll try again %s.",
5526 item, increment_action, (int)dls_n_download_increments,
5527 not_incremented_response);
5528 else if (increment == 0)
5529 log_debug(LD_DIR, "%s %s %d time(s); I'll try again immediately.",
5530 item, increment_action, (int)dls_n_download_increments);
5531 else if (dls_next_attempt_at < TIME_MAX)
5532 log_debug(LD_DIR, "%s %s %d time(s); I'll try again in %d seconds.",
5533 item, increment_action, (int)dls_n_download_increments,
5534 (int)(dls_next_attempt_at-now));
5535 else
5536 log_debug(LD_DIR, "%s %s %d time(s); Giving up for a while.",
5537 item, increment_action, (int)dls_n_download_increments);
5541 /** Determine when a failed download attempt should be retried.
5542 * Called when an attempt to download <b>dls</b> has failed with HTTP status
5543 * <b>status_code</b>. Increment the failure count (if the code indicates a
5544 * real failure, or if we're a server) and set <b>dls</b>-\>next_attempt_at to
5545 * an appropriate time in the future and return it.
5546 * If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_ATTEMPT, increment the
5547 * failure count, and return a time in the far future for the next attempt (to
5548 * avoid an immediate retry). */
5549 time_t
5550 download_status_increment_failure(download_status_t *dls, int status_code,
5551 const char *item, int server, time_t now)
5553 (void) status_code; // XXXX no longer used.
5554 (void) server; // XXXX no longer used.
5555 int increment = -1;
5556 int min_delay = 0, max_delay = INT_MAX;
5558 tor_assert(dls);
5560 /* dls wasn't reset before it was used */
5561 if (dls->next_attempt_at == 0) {
5562 download_status_reset(dls);
5565 /* count the failure */
5566 if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1) {
5567 ++dls->n_download_failures;
5570 if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
5571 /* We don't find out that a failure-based schedule has attempted a
5572 * connection until that connection fails.
5573 * We'll never find out about successful connections, but this doesn't
5574 * matter, because schedules are reset after a successful download.
5576 if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
5577 ++dls->n_download_attempts;
5579 /* only return a failure retry time if this schedule increments on failures
5581 const smartlist_t *schedule = find_dl_schedule(dls, get_options());
5582 find_dl_min_and_max_delay(dls, get_options(), &min_delay, &max_delay);
5583 increment = download_status_schedule_get_delay(dls, schedule,
5584 min_delay, max_delay, now);
5587 download_status_log_helper(item, !dls->increment_on, "failed",
5588 "concurrently", dls->n_download_failures,
5589 increment,
5590 download_status_get_next_attempt_at(dls),
5591 now);
5593 if (dls->increment_on == DL_SCHED_INCREMENT_ATTEMPT) {
5594 /* stop this schedule retrying on failure, it will launch concurrent
5595 * connections instead */
5596 return TIME_MAX;
5597 } else {
5598 return download_status_get_next_attempt_at(dls);
5602 /** Determine when the next download attempt should be made when using an
5603 * attempt-based (potentially concurrent) download schedule.
5604 * Called when an attempt to download <b>dls</b> is being initiated.
5605 * Increment the attempt count and set <b>dls</b>-\>next_attempt_at to an
5606 * appropriate time in the future and return it.
5607 * If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_FAILURE, don't increment
5608 * the attempts, and return a time in the far future (to avoid launching a
5609 * concurrent attempt). */
5610 time_t
5611 download_status_increment_attempt(download_status_t *dls, const char *item,
5612 time_t now)
5614 int delay = -1;
5615 int min_delay = 0, max_delay = INT_MAX;
5617 tor_assert(dls);
5619 /* dls wasn't reset before it was used */
5620 if (dls->next_attempt_at == 0) {
5621 download_status_reset(dls);
5624 if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
5625 /* this schedule should retry on failure, and not launch any concurrent
5626 attempts */
5627 log_warn(LD_BUG, "Tried to launch an attempt-based connection on a "
5628 "failure-based schedule.");
5629 return TIME_MAX;
5632 if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
5633 ++dls->n_download_attempts;
5635 const smartlist_t *schedule = find_dl_schedule(dls, get_options());
5636 find_dl_min_and_max_delay(dls, get_options(), &min_delay, &max_delay);
5637 delay = download_status_schedule_get_delay(dls, schedule,
5638 min_delay, max_delay, now);
5640 download_status_log_helper(item, dls->increment_on, "attempted",
5641 "on failure", dls->n_download_attempts,
5642 delay, download_status_get_next_attempt_at(dls),
5643 now);
5645 return download_status_get_next_attempt_at(dls);
5648 static time_t
5649 download_status_get_initial_delay_from_now(const download_status_t *dls)
5651 const smartlist_t *schedule = find_dl_schedule(dls, get_options());
5652 /* We use constant initial delays, even in exponential backoff
5653 * schedules. */
5654 return time(NULL) + *(int *)smartlist_get(schedule, 0);
5657 /** Reset <b>dls</b> so that it will be considered downloadable
5658 * immediately, and/or to show that we don't need it anymore.
5660 * Must be called to initialise a download schedule, otherwise the zeroth item
5661 * in the schedule will never be used.
5663 * (We find the zeroth element of the download schedule, and set
5664 * next_attempt_at to be the appropriate offset from 'now'. In most
5665 * cases this means setting it to 'now', so the item will be immediately
5666 * downloadable; in the case of bridge descriptors, the zeroth element
5667 * is an hour from now.) */
5668 void
5669 download_status_reset(download_status_t *dls)
5671 if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD
5672 || dls->n_download_attempts == IMPOSSIBLE_TO_DOWNLOAD)
5673 return; /* Don't reset this. */
5675 dls->n_download_failures = 0;
5676 dls->n_download_attempts = 0;
5677 dls->next_attempt_at = download_status_get_initial_delay_from_now(dls);
5678 dls->last_backoff_position = 0;
5679 dls->last_delay_used = 0;
5680 /* Don't reset dls->want_authority or dls->increment_on */
5683 /** Return the number of failures on <b>dls</b> since the last success (if
5684 * any). */
5686 download_status_get_n_failures(const download_status_t *dls)
5688 return dls->n_download_failures;
5691 /** Return the number of attempts to download <b>dls</b> since the last success
5692 * (if any). This can differ from download_status_get_n_failures() due to
5693 * outstanding concurrent attempts. */
5695 download_status_get_n_attempts(const download_status_t *dls)
5697 return dls->n_download_attempts;
5700 /** Return the next time to attempt to download <b>dls</b>. */
5701 time_t
5702 download_status_get_next_attempt_at(const download_status_t *dls)
5704 /* dls wasn't reset before it was used */
5705 if (dls->next_attempt_at == 0) {
5706 /* so give the answer we would have given if it had been */
5707 return download_status_get_initial_delay_from_now(dls);
5710 return dls->next_attempt_at;
5713 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
5714 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
5715 * either as descriptor digests or as identity digests based on
5716 * <b>was_descriptor_digests</b>).
5718 static void
5719 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
5720 int router_purpose,
5721 int was_extrainfo, int was_descriptor_digests)
5723 char digest[DIGEST_LEN];
5724 time_t now = time(NULL);
5725 int server = directory_fetches_from_authorities(get_options());
5726 if (!was_descriptor_digests) {
5727 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
5728 tor_assert(!was_extrainfo);
5729 connection_dir_retry_bridges(failed);
5731 return; /* FFFF should implement for other-than-router-purpose someday */
5733 SMARTLIST_FOREACH_BEGIN(failed, const char *, cp) {
5734 download_status_t *dls = NULL;
5735 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) != DIGEST_LEN) {
5736 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
5737 continue;
5739 if (was_extrainfo) {
5740 signed_descriptor_t *sd =
5741 router_get_by_extrainfo_digest(digest);
5742 if (sd)
5743 dls = &sd->ei_dl_status;
5744 } else {
5745 dls = router_get_dl_status_by_descriptor_digest(digest);
5747 if (!dls || dls->n_download_failures >=
5748 get_options()->TestingDescriptorMaxDownloadTries)
5749 continue;
5750 download_status_increment_failure(dls, status_code, cp, server, now);
5751 } SMARTLIST_FOREACH_END(cp);
5753 /* No need to relaunch descriptor downloads here: we already do it
5754 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
5757 /** Called when a connection to download microdescriptors has failed in whole
5758 * or in part. <b>failed</b> is a list of every microdesc digest we didn't
5759 * get. <b>status_code</b> is the http status code we received. Reschedule the
5760 * microdesc downloads as appropriate. */
5761 static void
5762 dir_microdesc_download_failed(smartlist_t *failed,
5763 int status_code)
5765 networkstatus_t *consensus
5766 = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
5767 routerstatus_t *rs;
5768 download_status_t *dls;
5769 time_t now = time(NULL);
5770 int server = directory_fetches_from_authorities(get_options());
5772 if (! consensus)
5773 return;
5774 SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
5775 rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
5776 if (!rs)
5777 continue;
5778 dls = &rs->dl_status;
5779 if (dls->n_download_failures >=
5780 get_options()->TestingMicrodescMaxDownloadTries)
5781 continue;
5783 char buf[BASE64_DIGEST256_LEN+1];
5784 digest256_to_base64(buf, d);
5785 download_status_increment_failure(dls, status_code, buf,
5786 server, now);
5788 } SMARTLIST_FOREACH_END(d);
5791 /** Helper. Compare two fp_pair_t objects, and return negative, 0, or
5792 * positive as appropriate. */
5793 static int
5794 compare_pairs_(const void **a, const void **b)
5796 const fp_pair_t *fp1 = *a, *fp2 = *b;
5797 int r;
5798 if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
5799 return r;
5800 else
5801 return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
5804 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
5805 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
5806 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
5807 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
5809 dir_split_resource_into_fingerprint_pairs(const char *res,
5810 smartlist_t *pairs_out)
5812 smartlist_t *pairs_tmp = smartlist_new();
5813 smartlist_t *pairs_result = smartlist_new();
5815 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
5816 if (smartlist_len(pairs_tmp)) {
5817 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
5818 size_t last_len = strlen(last);
5819 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
5820 last[last_len-2] = '\0';
5823 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
5824 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
5825 log_info(LD_DIR,
5826 "Skipping digest pair %s with non-standard length.", escaped(cp));
5827 } else if (cp[HEX_DIGEST_LEN] != '-') {
5828 log_info(LD_DIR,
5829 "Skipping digest pair %s with missing dash.", escaped(cp));
5830 } else {
5831 fp_pair_t pair;
5832 if (base16_decode(pair.first, DIGEST_LEN,
5833 cp, HEX_DIGEST_LEN) != DIGEST_LEN ||
5834 base16_decode(pair.second,DIGEST_LEN,
5835 cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN) != DIGEST_LEN) {
5836 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
5837 } else {
5838 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
5841 tor_free(cp);
5842 } SMARTLIST_FOREACH_END(cp);
5843 smartlist_free(pairs_tmp);
5845 /* Uniq-and-sort */
5846 smartlist_sort(pairs_result, compare_pairs_);
5847 smartlist_uniq(pairs_result, compare_pairs_, tor_free_);
5849 smartlist_add_all(pairs_out, pairs_result);
5850 smartlist_free(pairs_result);
5851 return 0;
5854 /** Given a directory <b>resource</b> request, containing zero
5855 * or more strings separated by plus signs, followed optionally by ".z", store
5856 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
5857 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
5859 * If (flags & DSR_HEX), then delete all elements that aren't hex digests, and
5860 * decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as
5861 * a separator, delete all the elements that aren't base64-encoded digests,
5862 * and decode the rest. If (flags & DSR_DIGEST256), these digests should be
5863 * 256 bits long; else they should be 160.
5865 * If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates.
5868 dir_split_resource_into_fingerprints(const char *resource,
5869 smartlist_t *fp_out, int *compressed_out,
5870 int flags)
5872 const int decode_hex = flags & DSR_HEX;
5873 const int decode_base64 = flags & DSR_BASE64;
5874 const int digests_are_256 = flags & DSR_DIGEST256;
5875 const int sort_uniq = flags & DSR_SORT_UNIQ;
5877 const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
5878 const int hex_digest_len = digests_are_256 ?
5879 HEX_DIGEST256_LEN : HEX_DIGEST_LEN;
5880 const int base64_digest_len = digests_are_256 ?
5881 BASE64_DIGEST256_LEN : BASE64_DIGEST_LEN;
5882 smartlist_t *fp_tmp = smartlist_new();
5884 tor_assert(!(decode_hex && decode_base64));
5885 tor_assert(fp_out);
5887 smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
5888 if (compressed_out)
5889 *compressed_out = 0;
5890 if (smartlist_len(fp_tmp)) {
5891 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
5892 size_t last_len = strlen(last);
5893 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
5894 last[last_len-2] = '\0';
5895 if (compressed_out)
5896 *compressed_out = 1;
5899 if (decode_hex || decode_base64) {
5900 const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
5901 int i;
5902 char *cp, *d = NULL;
5903 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
5904 cp = smartlist_get(fp_tmp, i);
5905 if (strlen(cp) != encoded_len) {
5906 log_info(LD_DIR,
5907 "Skipping digest %s with non-standard length.", escaped(cp));
5908 smartlist_del_keeporder(fp_tmp, i--);
5909 goto again;
5911 d = tor_malloc_zero(digest_len);
5912 if (decode_hex ?
5913 (base16_decode(d, digest_len, cp, hex_digest_len) != digest_len) :
5914 (base64_decode(d, digest_len, cp, base64_digest_len)
5915 != digest_len)) {
5916 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
5917 smartlist_del_keeporder(fp_tmp, i--);
5918 goto again;
5920 smartlist_set(fp_tmp, i, d);
5921 d = NULL;
5922 again:
5923 tor_free(cp);
5924 tor_free(d);
5927 if (sort_uniq) {
5928 if (decode_hex || decode_base64) {
5929 if (digests_are_256) {
5930 smartlist_sort_digests256(fp_tmp);
5931 smartlist_uniq_digests256(fp_tmp);
5932 } else {
5933 smartlist_sort_digests(fp_tmp);
5934 smartlist_uniq_digests(fp_tmp);
5936 } else {
5937 smartlist_sort_strings(fp_tmp);
5938 smartlist_uniq_strings(fp_tmp);
5941 smartlist_add_all(fp_out, fp_tmp);
5942 smartlist_free(fp_tmp);
5943 return 0;
5946 /** As dir_split_resource_into_fingerprints, but instead fills
5947 * <b>spool_out</b> with a list of spoolable_resource_t for the resource
5948 * identified through <b>source</b>. */
5950 dir_split_resource_into_spoolable(const char *resource,
5951 dir_spool_source_t source,
5952 smartlist_t *spool_out,
5953 int *compressed_out,
5954 int flags)
5956 smartlist_t *fingerprints = smartlist_new();
5958 tor_assert(flags & (DSR_HEX|DSR_BASE64));
5959 const size_t digest_len =
5960 (flags & DSR_DIGEST256) ? DIGEST256_LEN : DIGEST_LEN;
5962 int r = dir_split_resource_into_fingerprints(resource, fingerprints,
5963 compressed_out, flags);
5964 /* This is not a very efficient implementation XXXX */
5965 SMARTLIST_FOREACH_BEGIN(fingerprints, uint8_t *, digest) {
5966 spooled_resource_t *spooled =
5967 spooled_resource_new(source, digest, digest_len);
5968 if (spooled)
5969 smartlist_add(spool_out, spooled);
5970 tor_free(digest);
5971 } SMARTLIST_FOREACH_END(digest);
5973 smartlist_free(fingerprints);
5974 return r;