Prop210: Add want_authority to directory_get_from_dirserver
[tor.git] / src / or / directory.c
blob555462b325459d972c389187802b575575e54307
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2015, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "or.h"
7 #include "buffers.h"
8 #include "circuitbuild.h"
9 #include "config.h"
10 #include "connection.h"
11 #include "connection_edge.h"
12 #include "control.h"
13 #include "directory.h"
14 #include "dirserv.h"
15 #include "dirvote.h"
16 #include "entrynodes.h"
17 #include "geoip.h"
18 #include "main.h"
19 #include "microdesc.h"
20 #include "networkstatus.h"
21 #include "nodelist.h"
22 #include "policies.h"
23 #include "relay.h"
24 #include "rendclient.h"
25 #include "rendcommon.h"
26 #include "rendservice.h"
27 #include "rephist.h"
28 #include "router.h"
29 #include "routerlist.h"
30 #include "routerparse.h"
31 #include "routerset.h"
33 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
34 #ifndef OPENBSD
35 #include <malloc.h>
36 #endif
37 #endif
39 /**
40 * \file directory.c
41 * \brief Code to send and fetch directories and router
42 * descriptors via HTTP. Directories use dirserv.c to generate the
43 * results; clients use routers.c to parse them.
44 **/
46 /* In-points to directory.c:
48 * - directory_post_to_dirservers(), called from
49 * router_upload_dir_desc_to_dirservers() in router.c
50 * upload_service_descriptor() in rendservice.c
51 * - directory_get_from_dirserver(), called from
52 * rend_client_refetch_renddesc() in rendclient.c
53 * run_scheduled_events() in main.c
54 * do_hup() in main.c
55 * - connection_dir_process_inbuf(), called from
56 * connection_process_inbuf() in connection.c
57 * - connection_dir_finished_flushing(), called from
58 * connection_finished_flushing() in connection.c
59 * - connection_dir_finished_connecting(), called from
60 * connection_finished_connecting() in connection.c
62 static void directory_send_command(dir_connection_t *conn,
63 int purpose, int direct, const char *resource,
64 const char *payload, size_t payload_len,
65 time_t if_modified_since);
66 static int directory_handle_command(dir_connection_t *conn);
67 static int body_is_plausible(const char *body, size_t body_len, int purpose);
68 static char *http_get_header(const char *headers, const char *which);
69 static void http_set_address_origin(const char *headers, connection_t *conn);
70 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
71 static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn);
72 static void connection_dir_download_cert_failed(
73 dir_connection_t *conn, int status_code);
74 static void connection_dir_retry_bridges(smartlist_t *descs);
75 static void dir_routerdesc_download_failed(smartlist_t *failed,
76 int status_code,
77 int router_purpose,
78 int was_extrainfo,
79 int was_descriptor_digests);
80 static void dir_microdesc_download_failed(smartlist_t *failed,
81 int status_code);
82 static void note_client_request(int purpose, int compressed, size_t bytes);
83 static int client_likes_consensus(networkstatus_t *v, const char *want_url);
85 static void directory_initiate_command_rend(const tor_addr_t *addr,
86 uint16_t or_port,
87 uint16_t dir_port,
88 const char *digest,
89 uint8_t dir_purpose,
90 uint8_t router_purpose,
91 dir_indirection_t indirection,
92 const char *resource,
93 const char *payload,
94 size_t payload_len,
95 time_t if_modified_since,
96 const rend_data_t *rend_query);
98 /********* START VARIABLES **********/
100 /** How far in the future do we allow a directory server to tell us it is
101 * before deciding that one of us has the wrong time? */
102 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
104 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
106 /** HTTP cache control: how long do we tell proxies they can cache each
107 * kind of document we serve? */
108 #define FULL_DIR_CACHE_LIFETIME (60*60)
109 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
110 #define DIRPORTFRONTPAGE_CACHE_LIFETIME (20*60)
111 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
112 #define ROUTERDESC_CACHE_LIFETIME (30*60)
113 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
114 #define ROBOTS_CACHE_LIFETIME (24*60*60)
115 #define MICRODESC_CACHE_LIFETIME (48*60*60)
117 /********* END VARIABLES ************/
119 /** Return true iff the directory purpose <b>dir_purpose</b> (and if it's
120 * fetching descriptors, it's fetching them for <b>router_purpose</b>)
121 * must use an anonymous connection to a directory. */
122 STATIC int
123 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
125 if (get_options()->AllDirActionsPrivate)
126 return 1;
127 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
128 return 1; /* if no circuits yet, this might break bootstrapping, but it's
129 * needed to be safe. */
130 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
131 dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
132 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
133 dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
134 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
135 dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
136 dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
137 dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
138 dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
139 dir_purpose == DIR_PURPOSE_FETCH_MICRODESC)
140 return 0;
141 return 1;
144 /** Return a newly allocated string describing <b>auth</b>. Only describes
145 * authority features. */
146 static char *
147 authdir_type_to_string(dirinfo_type_t auth)
149 char *result;
150 smartlist_t *lst = smartlist_new();
151 if (auth & V3_DIRINFO)
152 smartlist_add(lst, (void*)"V3");
153 if (auth & BRIDGE_DIRINFO)
154 smartlist_add(lst, (void*)"Bridge");
155 if (smartlist_len(lst)) {
156 result = smartlist_join_strings(lst, ", ", 0, NULL);
157 } else {
158 result = tor_strdup("[Not an authority]");
160 smartlist_free(lst);
161 return result;
164 /** Return a string describing a given directory connection purpose. */
165 static const char *
166 dir_conn_purpose_to_string(int purpose)
168 switch (purpose)
170 case DIR_PURPOSE_UPLOAD_DIR:
171 return "server descriptor upload";
172 case DIR_PURPOSE_UPLOAD_VOTE:
173 return "server vote upload";
174 case DIR_PURPOSE_UPLOAD_SIGNATURES:
175 return "consensus signature upload";
176 case DIR_PURPOSE_FETCH_SERVERDESC:
177 return "server descriptor fetch";
178 case DIR_PURPOSE_FETCH_EXTRAINFO:
179 return "extra-info fetch";
180 case DIR_PURPOSE_FETCH_CONSENSUS:
181 return "consensus network-status fetch";
182 case DIR_PURPOSE_FETCH_CERTIFICATE:
183 return "authority cert fetch";
184 case DIR_PURPOSE_FETCH_STATUS_VOTE:
185 return "status vote fetch";
186 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
187 return "consensus signature fetch";
188 case DIR_PURPOSE_FETCH_RENDDESC_V2:
189 return "hidden-service v2 descriptor fetch";
190 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
191 return "hidden-service v2 descriptor upload";
192 case DIR_PURPOSE_FETCH_MICRODESC:
193 return "microdescriptor fetch";
196 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
197 return "(unknown)";
200 /** Return the requisite directory information types. */
201 STATIC dirinfo_type_t
202 dir_fetch_type(int dir_purpose, int router_purpose, const char *resource)
204 dirinfo_type_t type;
205 switch (dir_purpose) {
206 case DIR_PURPOSE_FETCH_EXTRAINFO:
207 type = EXTRAINFO_DIRINFO;
208 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
209 type |= BRIDGE_DIRINFO;
210 else
211 type |= V3_DIRINFO;
212 break;
213 case DIR_PURPOSE_FETCH_SERVERDESC:
214 if (router_purpose == ROUTER_PURPOSE_BRIDGE)
215 type = BRIDGE_DIRINFO;
216 else
217 type = V3_DIRINFO;
218 break;
219 case DIR_PURPOSE_FETCH_STATUS_VOTE:
220 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
221 case DIR_PURPOSE_FETCH_CERTIFICATE:
222 type = V3_DIRINFO;
223 break;
224 case DIR_PURPOSE_FETCH_CONSENSUS:
225 type = V3_DIRINFO;
226 if (resource && !strcmp(resource, "microdesc"))
227 type |= MICRODESC_DIRINFO;
228 break;
229 case DIR_PURPOSE_FETCH_MICRODESC:
230 type = MICRODESC_DIRINFO;
231 break;
232 default:
233 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
234 type = NO_DIRINFO;
235 break;
237 return type;
240 /** Return true iff <b>identity_digest</b> is the digest of a router which
241 * says that it caches extrainfos. (If <b>is_authority</b> we always
242 * believe that to be true.) */
244 router_supports_extrainfo(const char *identity_digest, int is_authority)
246 const node_t *node = node_get_by_id(identity_digest);
248 if (node && node->ri) {
249 if (node->ri->caches_extra_info)
250 return 1;
252 if (is_authority) {
253 return 1;
255 return 0;
258 /** Return true iff any trusted directory authority has accepted our
259 * server descriptor.
261 * We consider any authority sufficient because waiting for all of
262 * them means it never happens while any authority is down; we don't
263 * go for something more complex in the middle (like \>1/3 or \>1/2 or
264 * \>=1/2) because that doesn't seem necessary yet.
267 directories_have_accepted_server_descriptor(void)
269 const smartlist_t *servers = router_get_trusted_dir_servers();
270 const or_options_t *options = get_options();
271 SMARTLIST_FOREACH(servers, dir_server_t *, d, {
272 if ((d->type & options->PublishServerDescriptor_) &&
273 d->has_accepted_serverdesc) {
274 return 1;
277 return 0;
280 /** Start a connection to every suitable directory authority, using
281 * connection purpose <b>dir_purpose</b> and uploading <b>payload</b>
282 * (of length <b>payload_len</b>). The dir_purpose should be one of
283 * 'DIR_PURPOSE_UPLOAD_{DIR|VOTE|SIGNATURES}'.
285 * <b>router_purpose</b> describes the type of descriptor we're
286 * publishing, if we're publishing a descriptor -- e.g. general or bridge.
288 * <b>type</b> specifies what sort of dir authorities (V3,
289 * BRIDGE, etc) we should upload to.
291 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
292 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
293 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
294 * to all authorities, and the extra-info document to all authorities that
295 * support it.
297 void
298 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
299 dirinfo_type_t type,
300 const char *payload,
301 size_t payload_len, size_t extrainfo_len)
303 const or_options_t *options = get_options();
304 dir_indirection_t indirection;
305 const smartlist_t *dirservers = router_get_trusted_dir_servers();
306 int found = 0;
307 const int exclude_self = (dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
308 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES);
309 tor_assert(dirservers);
310 /* This tries dirservers which we believe to be down, but ultimately, that's
311 * harmless, and we may as well err on the side of getting things uploaded.
313 SMARTLIST_FOREACH_BEGIN(dirservers, dir_server_t *, ds) {
314 routerstatus_t *rs = &(ds->fake_status);
315 size_t upload_len = payload_len;
316 tor_addr_t ds_addr;
318 if ((type & ds->type) == 0)
319 continue;
321 if (exclude_self && router_digest_is_me(ds->digest)) {
322 /* we don't upload to ourselves, but at least there's now at least
323 * one authority of this type that has what we wanted to upload. */
324 found = 1;
325 continue;
328 if (options->StrictNodes &&
329 routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) {
330 log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
331 "it's in our ExcludedNodes list and StrictNodes is set. "
332 "Skipping.",
333 ds->nickname,
334 dir_conn_purpose_to_string(dir_purpose));
335 continue;
338 found = 1; /* at least one authority of this type was listed */
339 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
340 ds->has_accepted_serverdesc = 0;
342 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
343 upload_len += extrainfo_len;
344 log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
345 (int) extrainfo_len);
347 tor_addr_from_ipv4h(&ds_addr, ds->addr);
348 if (purpose_needs_anonymity(dir_purpose, router_purpose)) {
349 indirection = DIRIND_ANONYMOUS;
350 } else if (!fascist_firewall_allows_address_dir(&ds_addr,ds->dir_port)) {
351 if (fascist_firewall_allows_address_or(&ds_addr,ds->or_port))
352 indirection = DIRIND_ONEHOP;
353 else
354 indirection = DIRIND_ANONYMOUS;
355 } else {
356 indirection = DIRIND_DIRECT_CONN;
358 directory_initiate_command_routerstatus(rs, dir_purpose,
359 router_purpose,
360 indirection,
361 NULL, payload, upload_len, 0);
362 } SMARTLIST_FOREACH_END(ds);
363 if (!found) {
364 char *s = authdir_type_to_string(type);
365 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
366 "of type '%s', but no authorities of that type listed!", s);
367 tor_free(s);
371 /** Return true iff, according to the values in <b>options</b>, we should be
372 * using directory guards for direct downloads of directory information. */
373 static int
374 should_use_directory_guards(const or_options_t *options)
376 /* Public (non-bridge) servers never use directory guards. */
377 if (public_server_mode(options))
378 return 0;
379 /* If guards are disabled, or directory guards are disabled, we can't
380 * use directory guards.
382 if (!options->UseEntryGuards || !options->UseEntryGuardsAsDirGuards)
383 return 0;
384 /* If we're configured to fetch directory info aggressively or of a
385 * nonstandard type, don't use directory guards. */
386 if (options->DownloadExtraInfo || options->FetchDirInfoEarly ||
387 options->FetchDirInfoExtraEarly || options->FetchUselessDescriptors)
388 return 0;
389 return 1;
392 /** Pick an unconstrained directory server from among our guards, the latest
393 * networkstatus, or the fallback dirservers, for use in downloading
394 * information of type <b>type</b>, and return its routerstatus. */
395 static const routerstatus_t *
396 directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags,
397 uint8_t dir_purpose)
399 const routerstatus_t *rs = NULL;
400 const or_options_t *options = get_options();
402 if (options->UseBridges)
403 log_warn(LD_BUG, "Called when we have UseBridges set.");
405 if (should_use_directory_guards(options)) {
406 const node_t *node = choose_random_dirguard(type);
407 if (node)
408 rs = node->rs;
409 } else {
410 /* anybody with a non-zero dirport will do */
411 rs = router_pick_directory_server(type, pds_flags);
413 if (!rs) {
414 log_info(LD_DIR, "No router found for %s; falling back to "
415 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
416 rs = router_pick_fallback_dirserver(type, pds_flags);
419 return rs;
422 /** Start a connection to a random running directory server, using
423 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
424 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
425 * Use <b>pds_flags</b> as arguments to router_pick_directory_server()
426 * or router_pick_trusteddirserver().
428 MOCK_IMPL(void, directory_get_from_dirserver, (
429 uint8_t dir_purpose,
430 uint8_t router_purpose,
431 const char *resource,
432 int pds_flags,
433 download_want_authority_t want_authority))
435 const routerstatus_t *rs = NULL;
436 const or_options_t *options = get_options();
437 int prefer_authority = (directory_fetches_from_authorities(options)
438 || want_authority == DL_WANT_AUTHORITY);
439 int require_authority = 0;
440 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
441 dirinfo_type_t type = dir_fetch_type(dir_purpose, router_purpose, resource);
442 time_t if_modified_since = 0;
444 if (type == NO_DIRINFO)
445 return;
447 if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
448 int flav = FLAV_NS;
449 networkstatus_t *v;
450 if (resource)
451 flav = networkstatus_parse_flavor_name(resource);
453 /* DEFAULT_IF_MODIFIED_SINCE_DELAY is 1/20 of the default consensus
454 * period of 1 hour.
456 #define DEFAULT_IF_MODIFIED_SINCE_DELAY (180)
457 if (flav != -1) {
458 /* IF we have a parsed consensus of this type, we can do an
459 * if-modified-time based on it. */
460 v = networkstatus_get_latest_consensus_by_flavor(flav);
461 if (v) {
462 /* In networks with particularly short V3AuthVotingIntervals,
463 * ask for the consensus if it's been modified since half the
464 * V3AuthVotingInterval of the most recent consensus. */
465 time_t ims_delay = DEFAULT_IF_MODIFIED_SINCE_DELAY;
466 if (v->fresh_until > v->valid_after
467 && ims_delay > (v->fresh_until - v->valid_after)/2) {
468 ims_delay = (v->fresh_until - v->valid_after)/2;
470 if_modified_since = v->valid_after + ims_delay;
472 } else {
473 /* Otherwise it might be a consensus we don't parse, but which we
474 * do cache. Look at the cached copy, perhaps. */
475 cached_dir_t *cd = dirserv_get_consensus(resource);
476 /* We have no method of determining the voting interval from an
477 * unparsed consensus, so we use the default. */
478 if (cd)
479 if_modified_since = cd->published + DEFAULT_IF_MODIFIED_SINCE_DELAY;
483 if (!options->FetchServerDescriptors)
484 return;
486 if (!get_via_tor) {
487 if (options->UseBridges && !(type & BRIDGE_DIRINFO)) {
488 /* We want to ask a running bridge for which we have a descriptor.
490 * When we ask choose_random_entry() for a bridge, we specify what
491 * sort of dir fetch we'll be doing, so it won't return a bridge
492 * that can't answer our question.
494 /* XXX024 Not all bridges handle conditional consensus downloading,
495 * so, for now, never assume the server supports that. -PP */
496 const node_t *node = choose_random_dirguard(type);
497 if (node && node->ri) {
498 /* every bridge has a routerinfo. */
499 tor_addr_t addr;
500 routerinfo_t *ri = node->ri;
501 node_get_addr(node, &addr);
502 directory_initiate_command(&addr,
503 ri->or_port, 0/*no dirport*/,
504 ri->cache_info.identity_digest,
505 dir_purpose,
506 router_purpose,
507 DIRIND_ONEHOP,
508 resource, NULL, 0, if_modified_since);
509 } else
510 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
511 "nodes are available yet.");
512 return;
513 } else {
514 if (prefer_authority || (type & BRIDGE_DIRINFO)) {
515 /* only ask authdirservers, and don't ask myself */
516 rs = router_pick_trusteddirserver(type, pds_flags);
517 if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
518 PDS_NO_EXISTING_MICRODESC_FETCH))) {
519 /* We don't want to fetch from any authorities that we're currently
520 * fetching server descriptors from, and we got no match. Did we
521 * get no match because all the authorities have connections
522 * fetching server descriptors (in which case we should just
523 * return,) or because all the authorities are down or on fire or
524 * unreachable or something (in which case we should go on with
525 * our fallback code)? */
526 pds_flags &= ~(PDS_NO_EXISTING_SERVERDESC_FETCH|
527 PDS_NO_EXISTING_MICRODESC_FETCH);
528 rs = router_pick_trusteddirserver(type, pds_flags);
529 if (rs) {
530 log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
531 "are in use.");
532 return;
535 if (rs == NULL && require_authority) {
536 log_info(LD_DIR, "No authorities were available for %s: will try "
537 "later.", dir_conn_purpose_to_string(dir_purpose));
538 return;
541 if (!rs && !(type & BRIDGE_DIRINFO)) {
542 /* */
543 rs = directory_pick_generic_dirserver(type, pds_flags,
544 dir_purpose);
545 if (!rs)
546 get_via_tor = 1; /* last resort: try routing it via Tor */
551 if (get_via_tor) {
552 /* Never use fascistfirewall; we're going via Tor. */
553 pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
554 rs = router_pick_directory_server(type, pds_flags);
557 /* If we have any hope of building an indirect conn, we know some router
558 * descriptors. If (rs==NULL), we can't build circuits anyway, so
559 * there's no point in falling back to the authorities in this case. */
560 if (rs) {
561 const dir_indirection_t indirection =
562 get_via_tor ? DIRIND_ANONYMOUS : DIRIND_ONEHOP;
563 directory_initiate_command_routerstatus(rs, dir_purpose,
564 router_purpose,
565 indirection,
566 resource, NULL, 0,
567 if_modified_since);
568 } else {
569 log_notice(LD_DIR,
570 "While fetching directory info, "
571 "no running dirservers known. Will try again later. "
572 "(purpose %d)", dir_purpose);
573 if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
574 /* remember we tried them all and failed. */
575 directory_all_unreachable(time(NULL));
580 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
581 * directory authority other than ourself. Only for use by authorities when
582 * searching for missing information while voting. */
583 void
584 directory_get_from_all_authorities(uint8_t dir_purpose,
585 uint8_t router_purpose,
586 const char *resource)
588 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
589 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
591 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
592 dir_server_t *, ds) {
593 routerstatus_t *rs;
594 if (router_digest_is_me(ds->digest))
595 continue;
596 if (!(ds->type & V3_DIRINFO))
597 continue;
598 rs = &ds->fake_status;
599 directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
600 DIRIND_ONEHOP, resource, NULL,
601 0, 0);
602 } SMARTLIST_FOREACH_END(ds);
605 /** Return true iff <b>ind</b> requires a multihop circuit. */
606 static int
607 dirind_is_anon(dir_indirection_t ind)
609 return ind == DIRIND_ANON_DIRPORT || ind == DIRIND_ANONYMOUS;
612 /** Same as directory_initiate_command_routerstatus(), but accepts
613 * rendezvous data to fetch a hidden service descriptor. */
614 void
615 directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
616 uint8_t dir_purpose,
617 uint8_t router_purpose,
618 dir_indirection_t indirection,
619 const char *resource,
620 const char *payload,
621 size_t payload_len,
622 time_t if_modified_since,
623 const rend_data_t *rend_query)
625 const or_options_t *options = get_options();
626 const node_t *node;
627 tor_addr_t addr;
628 const int anonymized_connection = dirind_is_anon(indirection);
629 node = node_get_by_id(status->identity_digest);
631 if (!node && anonymized_connection) {
632 log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
633 "don't have its router descriptor.",
634 routerstatus_describe(status));
635 return;
637 tor_addr_from_ipv4h(&addr, status->addr);
639 if (options->ExcludeNodes && options->StrictNodes &&
640 routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
641 log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
642 "it's in our ExcludedNodes list and StrictNodes is set. "
643 "Skipping. This choice might make your Tor not work.",
644 routerstatus_describe(status),
645 dir_conn_purpose_to_string(dir_purpose));
646 return;
649 directory_initiate_command_rend(&addr,
650 status->or_port, status->dir_port,
651 status->identity_digest,
652 dir_purpose, router_purpose,
653 indirection, resource,
654 payload, payload_len, if_modified_since,
655 rend_query);
658 /** Launch a new connection to the directory server <b>status</b> to
659 * upload or download a server or rendezvous
660 * descriptor. <b>dir_purpose</b> determines what
661 * kind of directory connection we're launching, and must be one of
662 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC_V2}. <b>router_purpose</b>
663 * specifies the descriptor purposes we have in mind (currently only
664 * used for FETCH_DIR).
666 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
667 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
669 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
670 * want to fetch.
672 void
673 directory_initiate_command_routerstatus(const routerstatus_t *status,
674 uint8_t dir_purpose,
675 uint8_t router_purpose,
676 dir_indirection_t indirection,
677 const char *resource,
678 const char *payload,
679 size_t payload_len,
680 time_t if_modified_since)
682 directory_initiate_command_routerstatus_rend(status, dir_purpose,
683 router_purpose,
684 indirection, resource,
685 payload, payload_len,
686 if_modified_since, NULL);
689 /** Return true iff <b>conn</b> is the client side of a directory connection
690 * we launched to ourself in order to determine the reachability of our
691 * dir_port. */
692 static int
693 directory_conn_is_self_reachability_test(dir_connection_t *conn)
695 if (conn->requested_resource &&
696 !strcmpstart(conn->requested_resource,"authority")) {
697 const routerinfo_t *me = router_get_my_routerinfo();
698 if (me &&
699 router_digest_is_me(conn->identity_digest) &&
700 tor_addr_eq_ipv4h(&conn->base_.addr, me->addr) && /*XXXX prop 118*/
701 me->dir_port == conn->base_.port)
702 return 1;
704 return 0;
707 /** Called when we are unable to complete the client's request to a directory
708 * server due to a network error: Mark the router as down and try again if
709 * possible.
711 static void
712 connection_dir_request_failed(dir_connection_t *conn)
714 if (directory_conn_is_self_reachability_test(conn)) {
715 return; /* this was a test fetch. don't retry. */
717 if (!entry_list_is_constrained(get_options()))
718 router_set_status(conn->identity_digest, 0); /* don't try him again */
719 if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
720 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
721 log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
722 "directory server at '%s'; retrying",
723 conn->base_.address);
724 if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
725 connection_dir_bridge_routerdesc_failed(conn);
726 connection_dir_download_routerdesc_failed(conn);
727 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
728 if (conn->requested_resource)
729 networkstatus_consensus_download_failed(0, conn->requested_resource);
730 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
731 log_info(LD_DIR, "Giving up on certificate fetch from directory server "
732 "at '%s'; retrying",
733 conn->base_.address);
734 connection_dir_download_cert_failed(conn, 0);
735 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
736 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
737 conn->base_.address);
738 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
739 log_info(LD_DIR, "Giving up downloading votes from '%s'",
740 conn->base_.address);
741 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
742 log_info(LD_DIR, "Giving up on downloading microdescriptors from "
743 "directory server at '%s'; will retry", conn->base_.address);
744 connection_dir_download_routerdesc_failed(conn);
748 /** Helper: Attempt to fetch directly the descriptors of each bridge
749 * listed in <b>failed</b>.
751 static void
752 connection_dir_retry_bridges(smartlist_t *descs)
754 char digest[DIGEST_LEN];
755 SMARTLIST_FOREACH(descs, const char *, cp,
757 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
758 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
759 escaped(cp));
760 continue;
762 retry_bridge_descriptor_fetch_directly(digest);
766 /** Called when an attempt to download one or more router descriptors
767 * or extra-info documents on connection <b>conn</b> failed.
769 static void
770 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
772 /* No need to increment the failure count for routerdescs, since
773 * it's not their fault. */
775 /* No need to relaunch descriptor downloads here: we already do it
776 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
777 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
778 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
779 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
781 (void) conn;
784 /** Called when an attempt to download a bridge's routerdesc from
785 * one of the authorities failed due to a network error. If
786 * possible attempt to download descriptors from the bridge directly.
788 static void
789 connection_dir_bridge_routerdesc_failed(dir_connection_t *conn)
791 smartlist_t *which = NULL;
793 /* Requests for bridge descriptors are in the form 'fp/', so ignore
794 anything else. */
795 if (!conn->requested_resource || strcmpstart(conn->requested_resource,"fp/"))
796 return;
798 which = smartlist_new();
799 dir_split_resource_into_fingerprints(conn->requested_resource
800 + strlen("fp/"),
801 which, NULL, 0);
803 tor_assert(conn->base_.purpose != DIR_PURPOSE_FETCH_EXTRAINFO);
804 if (smartlist_len(which)) {
805 connection_dir_retry_bridges(which);
806 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
808 smartlist_free(which);
811 /** Called when an attempt to fetch a certificate fails. */
812 static void
813 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
815 const char *fp_pfx = "fp/";
816 const char *fpsk_pfx = "fp-sk/";
817 smartlist_t *failed;
818 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
820 if (!conn->requested_resource)
821 return;
822 failed = smartlist_new();
824 * We have two cases download by fingerprint (resource starts
825 * with "fp/") or download by fingerprint/signing key pair
826 * (resource starts with "fp-sk/").
828 if (!strcmpstart(conn->requested_resource, fp_pfx)) {
829 /* Download by fingerprint case */
830 dir_split_resource_into_fingerprints(conn->requested_resource +
831 strlen(fp_pfx),
832 failed, NULL, DSR_HEX);
833 SMARTLIST_FOREACH_BEGIN(failed, char *, cp) {
834 /* Null signing key digest indicates download by fp only */
835 authority_cert_dl_failed(cp, NULL, status);
836 tor_free(cp);
837 } SMARTLIST_FOREACH_END(cp);
838 } else if (!strcmpstart(conn->requested_resource, fpsk_pfx)) {
839 /* Download by (fp,sk) pairs */
840 dir_split_resource_into_fingerprint_pairs(conn->requested_resource +
841 strlen(fpsk_pfx), failed);
842 SMARTLIST_FOREACH_BEGIN(failed, fp_pair_t *, cp) {
843 authority_cert_dl_failed(cp->first, cp->second, status);
844 tor_free(cp);
845 } SMARTLIST_FOREACH_END(cp);
846 } else {
847 log_warn(LD_DIR,
848 "Don't know what to do with failure for cert fetch %s",
849 conn->requested_resource);
852 smartlist_free(failed);
854 update_certificate_downloads(time(NULL));
857 /** Evaluate the situation and decide if we should use an encrypted
858 * "begindir-style" connection for this directory request.
859 * 1) If or_port is 0, or it's a direct conn and or_port is firewalled
860 * or we're a dir mirror, no.
861 * 2) If we prefer to avoid begindir conns, and we're not fetching or
862 * publishing a bridge relay descriptor, no.
863 * 3) Else yes.
865 static int
866 directory_command_should_use_begindir(const or_options_t *options,
867 const tor_addr_t *addr,
868 int or_port, uint8_t router_purpose,
869 dir_indirection_t indirection)
871 (void) router_purpose;
872 if (!or_port)
873 return 0; /* We don't know an ORPort -- no chance. */
874 if (indirection == DIRIND_DIRECT_CONN || indirection == DIRIND_ANON_DIRPORT)
875 return 0;
876 if (indirection == DIRIND_ONEHOP)
877 if (!fascist_firewall_allows_address_or(addr, or_port) ||
878 directory_fetches_from_authorities(options))
879 return 0; /* We're firewalled or are acting like a relay -- also no. */
880 return 1;
883 /** Helper for directory_initiate_command_routerstatus: send the
884 * command to a server whose address is <b>address</b>, whose IP is
885 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
886 * <b>supports_begindir</b>, and whose identity key digest is
887 * <b>digest</b>. */
888 void
889 directory_initiate_command(const tor_addr_t *_addr,
890 uint16_t or_port, uint16_t dir_port,
891 const char *digest,
892 uint8_t dir_purpose, uint8_t router_purpose,
893 dir_indirection_t indirection, const char *resource,
894 const char *payload, size_t payload_len,
895 time_t if_modified_since)
897 directory_initiate_command_rend(_addr, or_port, dir_port,
898 digest, dir_purpose,
899 router_purpose, indirection,
900 resource, payload, payload_len,
901 if_modified_since, NULL);
904 /** Return non-zero iff a directory connection with purpose
905 * <b>dir_purpose</b> reveals sensitive information about a Tor
906 * instance's client activities. (Such connections must be performed
907 * through normal three-hop Tor circuits.) */
908 static int
909 is_sensitive_dir_purpose(uint8_t dir_purpose)
911 return ((dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2) ||
912 (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
913 (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
916 /** Same as directory_initiate_command(), but accepts rendezvous data to
917 * fetch a hidden service descriptor. */
918 static void
919 directory_initiate_command_rend(const tor_addr_t *_addr,
920 uint16_t or_port, uint16_t dir_port,
921 const char *digest,
922 uint8_t dir_purpose, uint8_t router_purpose,
923 dir_indirection_t indirection,
924 const char *resource,
925 const char *payload, size_t payload_len,
926 time_t if_modified_since,
927 const rend_data_t *rend_query)
929 dir_connection_t *conn;
930 const or_options_t *options = get_options();
931 int socket_error = 0;
932 int use_begindir = directory_command_should_use_begindir(options, _addr,
933 or_port, router_purpose, indirection);
934 const int anonymized_connection = dirind_is_anon(indirection);
935 tor_addr_t addr;
937 tor_assert(_addr);
938 tor_assert(or_port || dir_port);
939 tor_assert(digest);
941 tor_addr_copy(&addr, _addr);
943 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
944 anonymized_connection, use_begindir);
946 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
948 #ifndef NON_ANONYMOUS_MODE_ENABLED
949 tor_assert(!(is_sensitive_dir_purpose(dir_purpose) &&
950 !anonymized_connection));
951 #else
952 (void)is_sensitive_dir_purpose;
953 #endif
955 /* ensure that we don't make direct connections when a SOCKS server is
956 * configured. */
957 if (!anonymized_connection && !use_begindir && !options->HTTPProxy &&
958 (options->Socks4Proxy || options->Socks5Proxy)) {
959 log_warn(LD_DIR, "Cannot connect to a directory server through a "
960 "SOCKS proxy!");
961 return;
964 conn = dir_connection_new(tor_addr_family(&addr));
966 /* set up conn so it's got all the data we need to remember */
967 tor_addr_copy(&conn->base_.addr, &addr);
968 conn->base_.port = use_begindir ? or_port : dir_port;
969 conn->base_.address = tor_dup_addr(&addr);
970 memcpy(conn->identity_digest, digest, DIGEST_LEN);
972 conn->base_.purpose = dir_purpose;
973 conn->router_purpose = router_purpose;
975 /* give it an initial state */
976 conn->base_.state = DIR_CONN_STATE_CONNECTING;
978 /* decide whether we can learn our IP address from this conn */
979 /* XXXX This is a bad name for this field now. */
980 conn->dirconn_direct = !anonymized_connection;
982 /* copy rendezvous data, if any */
983 if (rend_query)
984 conn->rend_data = rend_data_dup(rend_query);
986 if (!anonymized_connection && !use_begindir) {
987 /* then we want to connect to dirport directly */
989 if (options->HTTPProxy) {
990 tor_addr_copy(&addr, &options->HTTPProxyAddr);
991 dir_port = options->HTTPProxyPort;
994 switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr,
995 dir_port, &socket_error)) {
996 case -1:
997 connection_mark_for_close(TO_CONN(conn));
998 return;
999 case 1:
1000 /* start flushing conn */
1001 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
1002 /* fall through */
1003 case 0:
1004 /* queue the command on the outbuf */
1005 directory_send_command(conn, dir_purpose, 1, resource,
1006 payload, payload_len,
1007 if_modified_since);
1008 connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT);
1009 /* writable indicates finish, readable indicates broken link,
1010 error indicates broken link in windowsland. */
1012 } else { /* we want to connect via a tor connection */
1013 entry_connection_t *linked_conn;
1014 /* Anonymized tunneled connections can never share a circuit.
1015 * One-hop directory connections can share circuits with each other
1016 * but nothing else. */
1017 int iso_flags = anonymized_connection ? ISO_STREAM : ISO_SESSIONGRP;
1019 /* If it's an anonymized connection, remember the fact that we
1020 * wanted it for later: maybe we'll want it again soon. */
1021 if (anonymized_connection && use_begindir)
1022 rep_hist_note_used_internal(time(NULL), 0, 1);
1023 else if (anonymized_connection && !use_begindir)
1024 rep_hist_note_used_port(time(NULL), conn->base_.port);
1026 /* make an AP connection
1027 * populate it and add it at the right state
1028 * hook up both sides
1030 linked_conn =
1031 connection_ap_make_link(TO_CONN(conn),
1032 conn->base_.address, conn->base_.port,
1033 digest,
1034 SESSION_GROUP_DIRCONN, iso_flags,
1035 use_begindir, conn->dirconn_direct);
1036 if (!linked_conn) {
1037 log_warn(LD_NET,"Making tunnel to dirserver failed.");
1038 connection_mark_for_close(TO_CONN(conn));
1039 return;
1042 if (connection_add(TO_CONN(conn)) < 0) {
1043 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
1044 connection_mark_for_close(TO_CONN(conn));
1045 return;
1047 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
1048 /* queue the command on the outbuf */
1049 directory_send_command(conn, dir_purpose, 0, resource,
1050 payload, payload_len,
1051 if_modified_since);
1053 connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
1054 IF_HAS_BUFFEREVENT(ENTRY_TO_CONN(linked_conn), {
1055 connection_watch_events(ENTRY_TO_CONN(linked_conn),
1056 READ_EVENT|WRITE_EVENT);
1057 }) ELSE_IF_NO_BUFFEREVENT
1058 connection_start_reading(ENTRY_TO_CONN(linked_conn));
1062 /** Return true iff anything we say on <b>conn</b> is being encrypted before
1063 * we send it to the client/server. */
1065 connection_dir_is_encrypted(dir_connection_t *conn)
1067 /* Right now it's sufficient to see if conn is or has been linked, since
1068 * the only thing it could be linked to is an edge connection on a
1069 * circuit, and the only way it could have been unlinked is at the edge
1070 * connection getting closed.
1072 return TO_CONN(conn)->linked;
1075 /** Helper for sorting
1077 * sort strings alphabetically
1079 static int
1080 compare_strs_(const void **a, const void **b)
1082 const char *s1 = *a, *s2 = *b;
1083 return strcmp(s1, s2);
1086 #define CONDITIONAL_CONSENSUS_FPR_LEN 3
1087 #if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
1088 #error "conditional consensus fingerprint length is larger than digest length"
1089 #endif
1091 /** Return the URL we should use for a consensus download.
1093 * This url depends on whether or not the server we go to
1094 * is sufficiently new to support conditional consensus downloading,
1095 * i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
1097 * If 'resource' is provided, it is the name of a consensus flavor to request.
1099 static char *
1100 directory_get_consensus_url(const char *resource)
1102 char *url = NULL;
1103 const char *hyphen, *flavor;
1104 if (resource==NULL || strcmp(resource, "ns")==0) {
1105 flavor = ""; /* Request ns consensuses as "", so older servers will work*/
1106 hyphen = "";
1107 } else {
1108 flavor = resource;
1109 hyphen = "-";
1113 char *authority_id_list;
1114 smartlist_t *authority_digests = smartlist_new();
1116 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
1117 dir_server_t *, ds) {
1118 char *hex;
1119 if (!(ds->type & V3_DIRINFO))
1120 continue;
1122 hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
1123 base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
1124 ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN);
1125 smartlist_add(authority_digests, hex);
1126 } SMARTLIST_FOREACH_END(ds);
1127 smartlist_sort(authority_digests, compare_strs_);
1128 authority_id_list = smartlist_join_strings(authority_digests,
1129 "+", 0, NULL);
1131 tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s/%s.z",
1132 hyphen, flavor, authority_id_list);
1134 SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
1135 smartlist_free(authority_digests);
1136 tor_free(authority_id_list);
1138 return url;
1141 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
1142 * are as in directory_initiate_command().
1144 static void
1145 directory_send_command(dir_connection_t *conn,
1146 int purpose, int direct, const char *resource,
1147 const char *payload, size_t payload_len,
1148 time_t if_modified_since)
1150 char proxystring[256];
1151 char hoststring[128];
1152 smartlist_t *headers = smartlist_new();
1153 char *url;
1154 char request[8192];
1155 const char *httpcommand = NULL;
1157 tor_assert(conn);
1158 tor_assert(conn->base_.type == CONN_TYPE_DIR);
1160 tor_free(conn->requested_resource);
1161 if (resource)
1162 conn->requested_resource = tor_strdup(resource);
1164 /* come up with a string for which Host: we want */
1165 if (conn->base_.port == 80) {
1166 strlcpy(hoststring, conn->base_.address, sizeof(hoststring));
1167 } else {
1168 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
1169 conn->base_.address, conn->base_.port);
1172 /* Format if-modified-since */
1173 if (if_modified_since) {
1174 char b[RFC1123_TIME_LEN+1];
1175 format_rfc1123_time(b, if_modified_since);
1176 smartlist_add_asprintf(headers, "If-Modified-Since: %s\r\n", b);
1179 /* come up with some proxy lines, if we're using one. */
1180 if (direct && get_options()->HTTPProxy) {
1181 char *base64_authenticator=NULL;
1182 const char *authenticator = get_options()->HTTPProxyAuthenticator;
1184 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
1185 if (authenticator) {
1186 base64_authenticator = alloc_http_authenticator(authenticator);
1187 if (!base64_authenticator)
1188 log_warn(LD_BUG, "Encoding http authenticator failed");
1190 if (base64_authenticator) {
1191 smartlist_add_asprintf(headers,
1192 "Proxy-Authorization: Basic %s\r\n",
1193 base64_authenticator);
1194 tor_free(base64_authenticator);
1196 } else {
1197 proxystring[0] = 0;
1200 switch (purpose) {
1201 case DIR_PURPOSE_FETCH_CONSENSUS:
1202 /* resource is optional. If present, it's a flavor name */
1203 tor_assert(!payload);
1204 httpcommand = "GET";
1205 url = directory_get_consensus_url(resource);
1206 log_info(LD_DIR, "Downloading consensus from %s using %s",
1207 hoststring, url);
1208 break;
1209 case DIR_PURPOSE_FETCH_CERTIFICATE:
1210 tor_assert(resource);
1211 tor_assert(!payload);
1212 httpcommand = "GET";
1213 tor_asprintf(&url, "/tor/keys/%s", resource);
1214 break;
1215 case DIR_PURPOSE_FETCH_STATUS_VOTE:
1216 tor_assert(resource);
1217 tor_assert(!payload);
1218 httpcommand = "GET";
1219 tor_asprintf(&url, "/tor/status-vote/next/%s.z", resource);
1220 break;
1221 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
1222 tor_assert(!resource);
1223 tor_assert(!payload);
1224 httpcommand = "GET";
1225 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
1226 break;
1227 case DIR_PURPOSE_FETCH_SERVERDESC:
1228 tor_assert(resource);
1229 httpcommand = "GET";
1230 tor_asprintf(&url, "/tor/server/%s", resource);
1231 break;
1232 case DIR_PURPOSE_FETCH_EXTRAINFO:
1233 tor_assert(resource);
1234 httpcommand = "GET";
1235 tor_asprintf(&url, "/tor/extra/%s", resource);
1236 break;
1237 case DIR_PURPOSE_FETCH_MICRODESC:
1238 tor_assert(resource);
1239 httpcommand = "GET";
1240 tor_asprintf(&url, "/tor/micro/%s", resource);
1241 break;
1242 case DIR_PURPOSE_UPLOAD_DIR: {
1243 const char *why = router_get_descriptor_gen_reason();
1244 tor_assert(!resource);
1245 tor_assert(payload);
1246 httpcommand = "POST";
1247 url = tor_strdup("/tor/");
1248 if (why) {
1249 smartlist_add_asprintf(headers, "X-Desc-Gen-Reason: %s\r\n", why);
1251 break;
1253 case DIR_PURPOSE_UPLOAD_VOTE:
1254 tor_assert(!resource);
1255 tor_assert(payload);
1256 httpcommand = "POST";
1257 url = tor_strdup("/tor/post/vote");
1258 break;
1259 case DIR_PURPOSE_UPLOAD_SIGNATURES:
1260 tor_assert(!resource);
1261 tor_assert(payload);
1262 httpcommand = "POST";
1263 url = tor_strdup("/tor/post/consensus-signature");
1264 break;
1265 case DIR_PURPOSE_FETCH_RENDDESC_V2:
1266 tor_assert(resource);
1267 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
1268 tor_assert(!payload);
1269 httpcommand = "GET";
1270 tor_asprintf(&url, "/tor/rendezvous2/%s", resource);
1271 break;
1272 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
1273 tor_assert(!resource);
1274 tor_assert(payload);
1275 httpcommand = "POST";
1276 url = tor_strdup("/tor/rendezvous2/publish");
1277 break;
1278 default:
1279 tor_assert(0);
1280 return;
1283 /* warn in the non-tunneled case */
1284 if (direct && (strlen(proxystring) + strlen(url) >= 4096)) {
1285 log_warn(LD_BUG,
1286 "Squid does not like URLs longer than 4095 bytes, and this "
1287 "one is %d bytes long: %s%s",
1288 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
1291 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
1292 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1293 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
1294 tor_free(url);
1296 if (!strcmp(httpcommand, "POST") || payload) {
1297 smartlist_add_asprintf(headers, "Content-Length: %lu\r\n",
1298 payload ? (unsigned long)payload_len : 0);
1302 char *header = smartlist_join_strings(headers, "", 0, NULL);
1303 tor_snprintf(request, sizeof(request), " HTTP/1.0\r\nHost: %s\r\n%s\r\n",
1304 hoststring, header);
1305 tor_free(header);
1308 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1310 if (payload) {
1311 /* then send the payload afterwards too */
1312 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
1315 SMARTLIST_FOREACH(headers, char *, h, tor_free(h));
1316 smartlist_free(headers);
1319 /** Parse an HTTP request string <b>headers</b> of the form
1320 * \verbatim
1321 * "\%s [http[s]://]\%s HTTP/1..."
1322 * \endverbatim
1323 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
1324 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
1325 * so it does. Return 0.
1326 * Otherwise, return -1.
1328 STATIC int
1329 parse_http_url(const char *headers, char **url)
1331 char *s, *start, *tmp;
1333 s = (char *)eat_whitespace_no_nl(headers);
1334 if (!*s) return -1;
1335 s = (char *)find_whitespace(s); /* get past GET/POST */
1336 if (!*s) return -1;
1337 s = (char *)eat_whitespace_no_nl(s);
1338 if (!*s) return -1;
1339 start = s; /* this is it, assuming it's valid */
1340 s = (char *)find_whitespace(start);
1341 if (!*s) return -1;
1343 /* tolerate the http[s] proxy style of putting the hostname in the url */
1344 if (s-start >= 4 && !strcmpstart(start,"http")) {
1345 tmp = start + 4;
1346 if (*tmp == 's')
1347 tmp++;
1348 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
1349 tmp = strchr(tmp+3, '/');
1350 if (tmp && tmp < s) {
1351 log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
1352 start = tmp;
1357 /* Check if the header is well formed (next sequence
1358 * should be HTTP/1.X\r\n). Assumes we're supporting 1.0? */
1360 unsigned minor_ver;
1361 char ch;
1362 char *e = (char *)eat_whitespace_no_nl(s);
1363 if (2 != tor_sscanf(e, "HTTP/1.%u%c", &minor_ver, &ch)) {
1364 return -1;
1366 if (ch != '\r')
1367 return -1;
1370 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
1371 *url = tor_malloc(s - start + 5);
1372 strlcpy(*url,"/tor", s-start+5);
1373 strlcat((*url)+4, start, s-start+1);
1374 } else {
1375 *url = tor_strndup(start, s-start);
1377 return 0;
1380 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1381 * <b>which</b>. The key should be given with a terminating colon and space;
1382 * this function copies everything after, up to but not including the
1383 * following \\r\\n. */
1384 static char *
1385 http_get_header(const char *headers, const char *which)
1387 const char *cp = headers;
1388 while (cp) {
1389 if (!strcasecmpstart(cp, which)) {
1390 char *eos;
1391 cp += strlen(which);
1392 if ((eos = strchr(cp,'\r')))
1393 return tor_strndup(cp, eos-cp);
1394 else
1395 return tor_strdup(cp);
1397 cp = strchr(cp, '\n');
1398 if (cp)
1399 ++cp;
1401 return NULL;
1404 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1405 * <b>conn</b>-\>address to describe our best guess of the address that
1406 * originated this HTTP request. */
1407 static void
1408 http_set_address_origin(const char *headers, connection_t *conn)
1410 char *fwd;
1412 fwd = http_get_header(headers, "Forwarded-For: ");
1413 if (!fwd)
1414 fwd = http_get_header(headers, "X-Forwarded-For: ");
1415 if (fwd) {
1416 tor_addr_t toraddr;
1417 if (tor_addr_parse(&toraddr,fwd) == -1 ||
1418 tor_addr_is_internal(&toraddr,0)) {
1419 log_debug(LD_DIR, "Ignoring local/internal IP %s", escaped(fwd));
1420 tor_free(fwd);
1421 return;
1424 tor_free(conn->address);
1425 conn->address = tor_strdup(fwd);
1426 tor_free(fwd);
1430 /** Parse an HTTP response string <b>headers</b> of the form
1431 * \verbatim
1432 * "HTTP/1.\%d \%d\%s\r\n...".
1433 * \endverbatim
1435 * If it's well-formed, assign the status code to *<b>code</b> and
1436 * return 0. Otherwise, return -1.
1438 * On success: If <b>date</b> is provided, set *date to the Date
1439 * header in the http headers, or 0 if no such header is found. If
1440 * <b>compression</b> is provided, set *<b>compression</b> to the
1441 * compression method given in the Content-Encoding header, or 0 if no
1442 * such header is found, or -1 if the value of the header is not
1443 * recognized. If <b>reason</b> is provided, strdup the reason string
1444 * into it.
1447 parse_http_response(const char *headers, int *code, time_t *date,
1448 compress_method_t *compression, char **reason)
1450 unsigned n1, n2;
1451 char datestr[RFC1123_TIME_LEN+1];
1452 smartlist_t *parsed_headers;
1453 tor_assert(headers);
1454 tor_assert(code);
1456 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1458 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
1459 (n1 != 0 && n1 != 1) ||
1460 (n2 < 100 || n2 >= 600)) {
1461 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1462 return -1;
1464 *code = n2;
1466 parsed_headers = smartlist_new();
1467 smartlist_split_string(parsed_headers, headers, "\n",
1468 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1469 if (reason) {
1470 smartlist_t *status_line_elements = smartlist_new();
1471 tor_assert(smartlist_len(parsed_headers));
1472 smartlist_split_string(status_line_elements,
1473 smartlist_get(parsed_headers, 0),
1474 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1475 tor_assert(smartlist_len(status_line_elements) <= 3);
1476 if (smartlist_len(status_line_elements) == 3) {
1477 *reason = smartlist_get(status_line_elements, 2);
1478 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1480 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1481 smartlist_free(status_line_elements);
1483 if (date) {
1484 *date = 0;
1485 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1486 if (!strcmpstart(s, "Date: ")) {
1487 strlcpy(datestr, s+6, sizeof(datestr));
1488 /* This will do nothing on failure, so we don't need to check
1489 the result. We shouldn't warn, since there are many other valid
1490 date formats besides the one we use. */
1491 parse_rfc1123_time(datestr, date);
1492 break;
1495 if (compression) {
1496 const char *enc = NULL;
1497 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1498 if (!strcmpstart(s, "Content-Encoding: ")) {
1499 enc = s+18; break;
1501 if (!enc || !strcmp(enc, "identity")) {
1502 *compression = NO_METHOD;
1503 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1504 *compression = ZLIB_METHOD;
1505 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1506 *compression = GZIP_METHOD;
1507 } else {
1508 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1509 escaped(enc));
1510 *compression = UNKNOWN_METHOD;
1513 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1514 smartlist_free(parsed_headers);
1516 return 0;
1519 /** Return true iff <b>body</b> doesn't start with a plausible router or
1520 * network-status or microdescriptor opening. This is a sign of possible
1521 * compression. */
1522 static int
1523 body_is_plausible(const char *body, size_t len, int purpose)
1525 int i;
1526 if (len == 0)
1527 return 1; /* empty bodies don't need decompression */
1528 if (len < 32)
1529 return 0;
1530 if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
1531 return (!strcmpstart(body,"onion-key"));
1533 if (1) {
1534 if (!strcmpstart(body,"router") ||
1535 !strcmpstart(body,"network-status"))
1536 return 1;
1537 for (i=0;i<32;++i) {
1538 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1539 return 0;
1542 return 1;
1545 /** Called when we've just fetched a bunch of router descriptors in
1546 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1547 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1548 * is true, or identity digests otherwise. Parse the descriptors, validate
1549 * them, and annotate them as having purpose <b>purpose</b> and as having been
1550 * downloaded from <b>source</b>.
1552 * Return the number of routers actually added. */
1553 static int
1554 load_downloaded_routers(const char *body, smartlist_t *which,
1555 int descriptor_digests,
1556 int router_purpose,
1557 const char *source)
1559 char buf[256];
1560 char time_buf[ISO_TIME_LEN+1];
1561 int added = 0;
1562 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1563 format_iso_time(time_buf, time(NULL));
1564 tor_assert(source);
1566 if (tor_snprintf(buf, sizeof(buf),
1567 "@downloaded-at %s\n"
1568 "@source %s\n"
1569 "%s%s%s", time_buf, escaped(source),
1570 !general ? "@purpose " : "",
1571 !general ? router_purpose_to_string(router_purpose) : "",
1572 !general ? "\n" : "")<0)
1573 return added;
1575 added = router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1576 descriptor_digests, buf);
1577 if (general)
1578 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
1579 count_loading_descriptors_progress());
1580 return added;
1583 /** We are a client, and we've finished reading the server's
1584 * response. Parse it and act appropriately.
1586 * If we're still happy with using this directory server in the future, return
1587 * 0. Otherwise return -1; and the caller should consider trying the request
1588 * again.
1590 * The caller will take care of marking the connection for close.
1592 static int
1593 connection_dir_client_reached_eof(dir_connection_t *conn)
1595 char *body;
1596 char *headers;
1597 char *reason = NULL;
1598 size_t body_len = 0, orig_len = 0;
1599 int status_code;
1600 time_t date_header = 0;
1601 long apparent_skew;
1602 compress_method_t compression;
1603 int plausible;
1604 int skewed = 0;
1605 int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1606 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
1607 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
1608 int was_compressed = 0;
1609 time_t now = time(NULL);
1610 int src_code;
1612 switch (connection_fetch_from_buf_http(TO_CONN(conn),
1613 &headers, MAX_HEADERS_SIZE,
1614 &body, &body_len, MAX_DIR_DL_SIZE,
1615 allow_partial)) {
1616 case -1: /* overflow */
1617 log_warn(LD_PROTOCOL,
1618 "'fetch' response too large (server '%s:%d'). Closing.",
1619 conn->base_.address, conn->base_.port);
1620 return -1;
1621 case 0:
1622 log_info(LD_HTTP,
1623 "'fetch' response not all here, but we're at eof. Closing.");
1624 return -1;
1625 /* case 1, fall through */
1627 orig_len = body_len;
1629 if (parse_http_response(headers, &status_code, &date_header,
1630 &compression, &reason) < 0) {
1631 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1632 conn->base_.address, conn->base_.port);
1633 tor_free(body); tor_free(headers);
1634 return -1;
1636 if (!reason) reason = tor_strdup("[no reason given]");
1638 log_debug(LD_DIR,
1639 "Received response from directory server '%s:%d': %d %s "
1640 "(purpose: %d)",
1641 conn->base_.address, conn->base_.port, status_code,
1642 escaped(reason),
1643 conn->base_.purpose);
1645 /* now check if it's got any hints for us about our IP address. */
1646 if (conn->dirconn_direct) {
1647 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1648 if (guess) {
1649 router_new_address_suggestion(guess, conn);
1650 tor_free(guess);
1654 if (date_header > 0) {
1655 /* The date header was written very soon after we sent our request,
1656 * so compute the skew as the difference between sending the request
1657 * and the date header. (We used to check now-date_header, but that's
1658 * inaccurate if we spend a lot of time downloading.)
1660 apparent_skew = conn->base_.timestamp_lastwritten - date_header;
1661 if (labs(apparent_skew)>ALLOW_DIRECTORY_TIME_SKEW) {
1662 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1663 clock_skew_warning(TO_CONN(conn), apparent_skew, trusted, LD_HTTP,
1664 "directory", "DIRSERV");
1665 skewed = 1; /* don't check the recommended-versions line */
1666 } else {
1667 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1668 "we are %ld seconds skewed. (That's okay.)", apparent_skew);
1671 (void) skewed; /* skewed isn't used yet. */
1673 if (status_code == 503) {
1674 routerstatus_t *rs;
1675 dir_server_t *ds;
1676 const char *id_digest = conn->identity_digest;
1677 log_info(LD_DIR,"Received http status code %d (%s) from server "
1678 "'%s:%d'. I'll try again soon.",
1679 status_code, escaped(reason), conn->base_.address,
1680 conn->base_.port);
1681 if ((rs = router_get_mutable_consensus_status_by_id(id_digest)))
1682 rs->last_dir_503_at = now;
1683 if ((ds = router_get_fallback_dirserver_by_digest(id_digest)))
1684 ds->fake_status.last_dir_503_at = now;
1686 tor_free(body); tor_free(headers); tor_free(reason);
1687 return -1;
1690 plausible = body_is_plausible(body, body_len, conn->base_.purpose);
1691 if (compression != NO_METHOD || !plausible) {
1692 char *new_body = NULL;
1693 size_t new_len = 0;
1694 compress_method_t guessed = detect_compression_method(body, body_len);
1695 if (compression == UNKNOWN_METHOD || guessed != compression) {
1696 /* Tell the user if we don't believe what we're told about compression.*/
1697 const char *description1, *description2;
1698 if (compression == ZLIB_METHOD)
1699 description1 = "as deflated";
1700 else if (compression == GZIP_METHOD)
1701 description1 = "as gzipped";
1702 else if (compression == NO_METHOD)
1703 description1 = "as uncompressed";
1704 else
1705 description1 = "with an unknown Content-Encoding";
1706 if (guessed == ZLIB_METHOD)
1707 description2 = "deflated";
1708 else if (guessed == GZIP_METHOD)
1709 description2 = "gzipped";
1710 else if (!plausible)
1711 description2 = "confusing binary junk";
1712 else
1713 description2 = "uncompressed";
1715 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1716 "but it seems to be %s.%s",
1717 conn->base_.address, conn->base_.port, description1,
1718 description2,
1719 (compression>0 && guessed>0)?" Trying both.":"");
1721 /* Try declared compression first if we can. */
1722 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1723 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1724 !allow_partial, LOG_PROTOCOL_WARN);
1725 /* Okay, if that didn't work, and we think that it was compressed
1726 * differently, try that. */
1727 if (!new_body &&
1728 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1729 compression != guessed)
1730 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1731 !allow_partial, LOG_PROTOCOL_WARN);
1732 /* If we're pretty sure that we have a compressed directory, and
1733 * we didn't manage to uncompress it, then warn and bail. */
1734 if (!plausible && !new_body) {
1735 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1736 "Unable to decompress HTTP body (server '%s:%d').",
1737 conn->base_.address, conn->base_.port);
1738 tor_free(body); tor_free(headers); tor_free(reason);
1739 return -1;
1741 if (new_body) {
1742 tor_free(body);
1743 body = new_body;
1744 body_len = new_len;
1745 was_compressed = 1;
1749 if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1750 int r;
1751 const char *flavname = conn->requested_resource;
1752 if (status_code != 200) {
1753 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1754 tor_log(severity, LD_DIR,
1755 "Received http status code %d (%s) from server "
1756 "'%s:%d' while fetching consensus directory.",
1757 status_code, escaped(reason), conn->base_.address,
1758 conn->base_.port);
1759 tor_free(body); tor_free(headers); tor_free(reason);
1760 networkstatus_consensus_download_failed(status_code, flavname);
1761 return -1;
1763 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1764 "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
1765 if ((r=networkstatus_set_current_consensus(body, flavname, 0))<0) {
1766 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1767 "Unable to load %s consensus directory downloaded from "
1768 "server '%s:%d'. I'll try again soon.",
1769 flavname, conn->base_.address, conn->base_.port);
1770 tor_free(body); tor_free(headers); tor_free(reason);
1771 networkstatus_consensus_download_failed(0, flavname);
1772 return -1;
1774 /* launches router downloads as needed */
1775 routers_update_all_from_networkstatus(now, 3);
1776 update_microdescs_from_networkstatus(now);
1777 update_microdesc_downloads(now);
1778 directory_info_has_arrived(now, 0);
1779 log_info(LD_DIR, "Successfully loaded consensus.");
1782 if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1783 if (status_code != 200) {
1784 log_warn(LD_DIR,
1785 "Received http status code %d (%s) from server "
1786 "'%s:%d' while fetching \"/tor/keys/%s\".",
1787 status_code, escaped(reason), conn->base_.address,
1788 conn->base_.port, conn->requested_resource);
1789 connection_dir_download_cert_failed(conn, status_code);
1790 tor_free(body); tor_free(headers); tor_free(reason);
1791 return -1;
1793 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1794 "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
1797 * Tell trusted_dirs_load_certs_from_string() whether it was by fp
1798 * or fp-sk pair.
1800 src_code = -1;
1801 if (!strcmpstart(conn->requested_resource, "fp/")) {
1802 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST;
1803 } else if (!strcmpstart(conn->requested_resource, "fp-sk/")) {
1804 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST;
1807 if (src_code != -1) {
1808 if (trusted_dirs_load_certs_from_string(body, src_code, 1)<0) {
1809 log_warn(LD_DIR, "Unable to parse fetched certificates");
1810 /* if we fetched more than one and only some failed, the successful
1811 * ones got flushed to disk so it's safe to call this on them */
1812 connection_dir_download_cert_failed(conn, status_code);
1813 } else {
1814 directory_info_has_arrived(now, 0);
1815 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1817 } else {
1818 log_warn(LD_DIR,
1819 "Couldn't figure out what to do with fetched certificates for "
1820 "unknown resource %s",
1821 conn->requested_resource);
1822 connection_dir_download_cert_failed(conn, status_code);
1825 if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1826 const char *msg;
1827 int st;
1828 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1829 (int)body_len, conn->base_.address, conn->base_.port);
1830 if (status_code != 200) {
1831 log_warn(LD_DIR,
1832 "Received http status code %d (%s) from server "
1833 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1834 status_code, escaped(reason), conn->base_.address,
1835 conn->base_.port, conn->requested_resource);
1836 tor_free(body); tor_free(headers); tor_free(reason);
1837 return -1;
1839 dirvote_add_vote(body, &msg, &st);
1840 if (st > 299) {
1841 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1842 } else {
1843 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1846 if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1847 const char *msg = NULL;
1848 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1849 (int)body_len, conn->base_.address, conn->base_.port);
1850 if (status_code != 200) {
1851 log_warn(LD_DIR,
1852 "Received http status code %d (%s) from server '%s:%d' while fetching "
1853 "\"/tor/status-vote/next/consensus-signatures.z\".",
1854 status_code, escaped(reason), conn->base_.address,
1855 conn->base_.port);
1856 tor_free(body); tor_free(headers); tor_free(reason);
1857 return -1;
1859 if (dirvote_add_signatures(body, conn->base_.address, &msg)<0) {
1860 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1861 conn->base_.address, conn->base_.port, msg?msg:"???");
1865 if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1866 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1867 int was_ei = conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1868 smartlist_t *which = NULL;
1869 int n_asked_for = 0;
1870 int descriptor_digests = conn->requested_resource &&
1871 !strcmpstart(conn->requested_resource,"d/");
1872 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1873 was_ei ? "extra server info" : "server info",
1874 (int)body_len, conn->base_.address, conn->base_.port);
1875 if (conn->requested_resource &&
1876 (!strcmpstart(conn->requested_resource,"d/") ||
1877 !strcmpstart(conn->requested_resource,"fp/"))) {
1878 which = smartlist_new();
1879 dir_split_resource_into_fingerprints(conn->requested_resource +
1880 (descriptor_digests ? 2 : 3),
1881 which, NULL, 0);
1882 n_asked_for = smartlist_len(which);
1884 if (status_code != 200) {
1885 int dir_okay = status_code == 404 ||
1886 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1887 /* 404 means that it didn't have them; no big deal.
1888 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1889 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1890 "Received http status code %d (%s) from server '%s:%d' "
1891 "while fetching \"/tor/server/%s\". I'll try again soon.",
1892 status_code, escaped(reason), conn->base_.address,
1893 conn->base_.port, conn->requested_resource);
1894 if (!which) {
1895 connection_dir_download_routerdesc_failed(conn);
1896 } else {
1897 dir_routerdesc_download_failed(which, status_code,
1898 conn->router_purpose,
1899 was_ei, descriptor_digests);
1900 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1901 smartlist_free(which);
1903 tor_free(body); tor_free(headers); tor_free(reason);
1904 return dir_okay ? 0 : -1;
1906 /* Learn the routers, assuming we requested by fingerprint or "all"
1907 * or "authority".
1909 * We use "authority" to fetch our own descriptor for
1910 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1911 * the output of "authority" requests unless we are using bridges,
1912 * since otherwise they'll be the response from reachability tests,
1913 * and we don't really want to add that to our routerlist. */
1914 if (which || (conn->requested_resource &&
1915 (!strcmpstart(conn->requested_resource, "all") ||
1916 (!strcmpstart(conn->requested_resource, "authority") &&
1917 get_options()->UseBridges)))) {
1918 /* as we learn from them, we remove them from 'which' */
1919 if (was_ei) {
1920 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1921 descriptor_digests);
1922 } else {
1923 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1924 // descriptor_digests, conn->router_purpose);
1925 if (load_downloaded_routers(body, which, descriptor_digests,
1926 conn->router_purpose,
1927 conn->base_.address))
1928 directory_info_has_arrived(now, 0);
1931 if (which) { /* mark remaining ones as failed */
1932 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1933 n_asked_for-smartlist_len(which), n_asked_for,
1934 was_ei ? "extra-info documents" : "router descriptors",
1935 conn->base_.address, (int)conn->base_.port);
1936 if (smartlist_len(which)) {
1937 dir_routerdesc_download_failed(which, status_code,
1938 conn->router_purpose,
1939 was_ei, descriptor_digests);
1941 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1942 smartlist_free(which);
1944 if (directory_conn_is_self_reachability_test(conn))
1945 router_dirport_found_reachable();
1947 if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
1948 smartlist_t *which = NULL;
1949 log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
1950 "size %d) from server '%s:%d'",
1951 status_code, (int)body_len, conn->base_.address,
1952 conn->base_.port);
1953 tor_assert(conn->requested_resource &&
1954 !strcmpstart(conn->requested_resource, "d/"));
1955 which = smartlist_new();
1956 dir_split_resource_into_fingerprints(conn->requested_resource+2,
1957 which, NULL,
1958 DSR_DIGEST256|DSR_BASE64);
1959 if (status_code != 200) {
1960 log_info(LD_DIR, "Received status code %d (%s) from server "
1961 "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again "
1962 "soon.",
1963 status_code, escaped(reason), conn->base_.address,
1964 (int)conn->base_.port, conn->requested_resource);
1965 dir_microdesc_download_failed(which, status_code);
1966 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1967 smartlist_free(which);
1968 tor_free(body); tor_free(headers); tor_free(reason);
1969 return 0;
1970 } else {
1971 smartlist_t *mds;
1972 mds = microdescs_add_to_cache(get_microdesc_cache(),
1973 body, body+body_len, SAVED_NOWHERE, 0,
1974 now, which);
1975 if (smartlist_len(which)) {
1976 /* Mark remaining ones as failed. */
1977 dir_microdesc_download_failed(which, status_code);
1979 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
1980 count_loading_descriptors_progress());
1981 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1982 smartlist_free(which);
1983 smartlist_free(mds);
1987 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1988 switch (status_code) {
1989 case 200: {
1990 dir_server_t *ds =
1991 router_get_trusteddirserver_by_digest(conn->identity_digest);
1992 char *rejected_hdr = http_get_header(headers,
1993 "X-Descriptor-Not-New: ");
1994 if (rejected_hdr) {
1995 if (!strcmp(rejected_hdr, "Yes")) {
1996 log_info(LD_GENERAL,
1997 "Authority '%s' declined our descriptor (not new)",
1998 ds->nickname);
1999 /* XXXX use this information; be sure to upload next one
2000 * sooner. -NM */
2001 /* XXXX023 On further thought, the task above implies that we're
2002 * basing our regenerate-descriptor time on when we uploaded the
2003 * last descriptor, not on the published time of the last
2004 * descriptor. If those are different, that's a bad thing to
2005 * do. -NM */
2007 tor_free(rejected_hdr);
2009 log_info(LD_GENERAL,"eof (status 200) after uploading server "
2010 "descriptor: finished.");
2011 control_event_server_status(
2012 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
2013 conn->base_.address, conn->base_.port);
2015 ds->has_accepted_serverdesc = 1;
2016 if (directories_have_accepted_server_descriptor())
2017 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
2019 break;
2020 case 400:
2021 log_warn(LD_GENERAL,"http status 400 (%s) response from "
2022 "dirserver '%s:%d'. Please correct.",
2023 escaped(reason), conn->base_.address, conn->base_.port);
2024 control_event_server_status(LOG_WARN,
2025 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
2026 conn->base_.address, conn->base_.port, escaped(reason));
2027 break;
2028 default:
2029 log_warn(LD_GENERAL,
2030 "http status %d (%s) reason unexpected while uploading "
2031 "descriptor to server '%s:%d').",
2032 status_code, escaped(reason), conn->base_.address,
2033 conn->base_.port);
2034 break;
2036 /* return 0 in all cases, since we don't want to mark any
2037 * dirservers down just because they don't like us. */
2040 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
2041 switch (status_code) {
2042 case 200: {
2043 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
2044 conn->base_.address, conn->base_.port);
2046 break;
2047 case 400:
2048 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
2049 "vote to dirserver '%s:%d'. Please correct.",
2050 escaped(reason), conn->base_.address, conn->base_.port);
2051 break;
2052 default:
2053 log_warn(LD_GENERAL,
2054 "http status %d (%s) reason unexpected while uploading "
2055 "vote to server '%s:%d').",
2056 status_code, escaped(reason), conn->base_.address,
2057 conn->base_.port);
2058 break;
2060 /* return 0 in all cases, since we don't want to mark any
2061 * dirservers down just because they don't like us. */
2064 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
2065 switch (status_code) {
2066 case 200: {
2067 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
2068 conn->base_.address, conn->base_.port);
2070 break;
2071 case 400:
2072 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
2073 "signatures to dirserver '%s:%d'. Please correct.",
2074 escaped(reason), conn->base_.address, conn->base_.port);
2075 break;
2076 default:
2077 log_warn(LD_GENERAL,
2078 "http status %d (%s) reason unexpected while uploading "
2079 "signatures to server '%s:%d').",
2080 status_code, escaped(reason), conn->base_.address,
2081 conn->base_.port);
2082 break;
2084 /* return 0 in all cases, since we don't want to mark any
2085 * dirservers down just because they don't like us. */
2088 if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
2089 #define SEND_HS_DESC_FAILED_EVENT(reason) ( \
2090 control_event_hs_descriptor_failed(conn->rend_data, \
2091 conn->identity_digest, \
2092 reason) )
2093 #define SEND_HS_DESC_FAILED_CONTENT() ( \
2094 control_event_hs_descriptor_content(conn->rend_data->onion_address, \
2095 conn->requested_resource, \
2096 conn->identity_digest, \
2097 NULL) )
2098 tor_assert(conn->rend_data);
2099 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
2100 "(%s))",
2101 (int)body_len, status_code, escaped(reason));
2102 switch (status_code) {
2103 case 200:
2105 rend_cache_entry_t *entry = NULL;
2107 switch (rend_cache_store_v2_desc_as_client(body,
2108 conn->requested_resource, conn->rend_data,
2109 &entry)) {
2110 case RCS_BADDESC:
2111 case RCS_NOTDIR: /* Impossible */
2112 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
2113 "Retrying at another directory.");
2114 /* We'll retry when connection_about_to_close_connection()
2115 * cleans this dir conn up. */
2116 SEND_HS_DESC_FAILED_EVENT("BAD_DESC");
2117 SEND_HS_DESC_FAILED_CONTENT();
2118 break;
2119 case RCS_OKAY:
2120 default:
2122 char service_id[REND_SERVICE_ID_LEN_BASE32 + 1];
2123 /* Should never be NULL here for an OKAY returned code. */
2124 tor_assert(entry);
2125 rend_get_service_id(entry->parsed->pk, service_id);
2127 /* success. notify pending connections about this. */
2128 log_info(LD_REND, "Successfully fetched v2 rendezvous "
2129 "descriptor.");
2130 control_event_hs_descriptor_received(service_id,
2131 conn->rend_data,
2132 conn->identity_digest);
2133 control_event_hs_descriptor_content(service_id,
2134 conn->requested_resource,
2135 conn->identity_digest,
2136 body);
2137 conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
2138 rend_client_desc_trynow(service_id);
2139 memwipe(service_id, 0, sizeof(service_id));
2140 break;
2143 break;
2145 case 404:
2146 /* Not there. We'll retry when
2147 * connection_about_to_close_connection() cleans this conn up. */
2148 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
2149 "Retrying at another directory.");
2150 SEND_HS_DESC_FAILED_EVENT("NOT_FOUND");
2151 SEND_HS_DESC_FAILED_CONTENT();
2152 break;
2153 case 400:
2154 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
2155 "http status 400 (%s). Dirserver didn't like our "
2156 "v2 rendezvous query? Retrying at another directory.",
2157 escaped(reason));
2158 SEND_HS_DESC_FAILED_EVENT("QUERY_REJECTED");
2159 SEND_HS_DESC_FAILED_CONTENT();
2160 break;
2161 default:
2162 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
2163 "http status %d (%s) response unexpected while "
2164 "fetching v2 hidden service descriptor (server '%s:%d'). "
2165 "Retrying at another directory.",
2166 status_code, escaped(reason), conn->base_.address,
2167 conn->base_.port);
2168 SEND_HS_DESC_FAILED_EVENT("UNEXPECTED");
2169 SEND_HS_DESC_FAILED_CONTENT();
2170 break;
2174 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
2175 #define SEND_HS_DESC_UPLOAD_FAILED_EVENT(reason) ( \
2176 control_event_hs_descriptor_upload_failed(conn->identity_digest, \
2177 reason) )
2178 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
2179 "(%s))",
2180 status_code, escaped(reason));
2181 switch (status_code) {
2182 case 200:
2183 log_info(LD_REND,
2184 "Uploading rendezvous descriptor: finished with status "
2185 "200 (%s)", escaped(reason));
2186 control_event_hs_descriptor_uploaded(conn->identity_digest);
2187 rend_service_desc_has_uploaded(conn->rend_data);
2188 break;
2189 case 400:
2190 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
2191 "'%s:%d'. Malformed rendezvous descriptor?",
2192 escaped(reason), conn->base_.address, conn->base_.port);
2193 SEND_HS_DESC_UPLOAD_FAILED_EVENT("UPLOAD_REJECTED");
2194 break;
2195 default:
2196 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
2197 "'%s:%d').",
2198 status_code, escaped(reason), conn->base_.address,
2199 conn->base_.port);
2200 SEND_HS_DESC_UPLOAD_FAILED_EVENT("UNEXPECTED");
2201 break;
2204 note_client_request(conn->base_.purpose, was_compressed, orig_len);
2205 tor_free(body); tor_free(headers); tor_free(reason);
2206 return 0;
2209 /** Called when a directory connection reaches EOF. */
2211 connection_dir_reached_eof(dir_connection_t *conn)
2213 int retval;
2214 if (conn->base_.state != DIR_CONN_STATE_CLIENT_READING) {
2215 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
2216 conn->base_.state);
2217 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
2218 connection_mark_for_close(TO_CONN(conn));
2219 return -1;
2222 retval = connection_dir_client_reached_eof(conn);
2223 if (retval == 0) /* success */
2224 conn->base_.state = DIR_CONN_STATE_CLIENT_FINISHED;
2225 connection_mark_for_close(TO_CONN(conn));
2226 return retval;
2229 /** If any directory object is arriving, and it's over 10MB large, we're
2230 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
2231 * ask for more than 96 router descriptors at a time.)
2233 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
2235 #define MAX_VOTE_DL_SIZE (MAX_DIRECTORY_OBJECT_SIZE * 5)
2237 /** Read handler for directory connections. (That's connections <em>to</em>
2238 * directory servers and connections <em>at</em> directory servers.)
2241 connection_dir_process_inbuf(dir_connection_t *conn)
2243 size_t max_size;
2244 tor_assert(conn);
2245 tor_assert(conn->base_.type == CONN_TYPE_DIR);
2247 /* Directory clients write, then read data until they receive EOF;
2248 * directory servers read data until they get an HTTP command, then
2249 * write their response (when it's finished flushing, they mark for
2250 * close).
2253 /* If we're on the dirserver side, look for a command. */
2254 if (conn->base_.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
2255 if (directory_handle_command(conn) < 0) {
2256 connection_mark_for_close(TO_CONN(conn));
2257 return -1;
2259 return 0;
2262 max_size =
2263 (TO_CONN(conn)->purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) ?
2264 MAX_VOTE_DL_SIZE : MAX_DIRECTORY_OBJECT_SIZE;
2266 if (connection_get_inbuf_len(TO_CONN(conn)) > max_size) {
2267 log_warn(LD_HTTP,
2268 "Too much data received from directory connection (%s): "
2269 "denial of service attempt, or you need to upgrade?",
2270 conn->base_.address);
2271 connection_mark_for_close(TO_CONN(conn));
2272 return -1;
2275 if (!conn->base_.inbuf_reached_eof)
2276 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
2277 return 0;
2280 /** Called when we're about to finally unlink and free a directory connection:
2281 * perform necessary accounting and cleanup */
2282 void
2283 connection_dir_about_to_close(dir_connection_t *dir_conn)
2285 connection_t *conn = TO_CONN(dir_conn);
2287 if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
2288 /* It's a directory connection and connecting or fetching
2289 * failed: forget about this router, and maybe try again. */
2290 connection_dir_request_failed(dir_conn);
2292 /* If we were trying to fetch a v2 rend desc and did not succeed,
2293 * retry as needed. (If a fetch is successful, the connection state
2294 * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 to mark that
2295 * refetching is unnecessary.) */
2296 if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
2297 dir_conn->rend_data &&
2298 strlen(dir_conn->rend_data->onion_address) == REND_SERVICE_ID_LEN_BASE32)
2299 rend_client_refetch_v2_renddesc(dir_conn->rend_data);
2302 /** Create an http response for the client <b>conn</b> out of
2303 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
2305 static void
2306 write_http_status_line(dir_connection_t *conn, int status,
2307 const char *reason_phrase)
2309 char buf[256];
2310 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
2311 status, reason_phrase ? reason_phrase : "OK") < 0) {
2312 log_warn(LD_BUG,"status line too long.");
2313 return;
2315 log_debug(LD_DIRSERV,"Wrote status 'HTTP/1.0 %d %s'", status, reason_phrase);
2316 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
2319 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
2320 * with <b>type</b> as the Content-Type.
2322 * If <b>length</b> is nonnegative, it is the Content-Length.
2323 * If <b>encoding</b> is provided, it is the Content-Encoding.
2324 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
2325 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
2326 static void
2327 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
2328 const char *type, const char *encoding,
2329 const char *extra_headers,
2330 long cache_lifetime)
2332 char date[RFC1123_TIME_LEN+1];
2333 char tmp[1024];
2334 char *cp;
2335 time_t now = time(NULL);
2337 tor_assert(conn);
2339 format_rfc1123_time(date, now);
2340 cp = tmp;
2341 tor_snprintf(cp, sizeof(tmp),
2342 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
2343 date);
2344 cp += strlen(tmp);
2345 if (type) {
2346 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
2347 cp += strlen(cp);
2349 if (!is_local_addr(&conn->base_.addr)) {
2350 /* Don't report the source address for a nearby/private connection.
2351 * Otherwise we tend to mis-report in cases where incoming ports are
2352 * being forwarded to a Tor server running behind the firewall. */
2353 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2354 X_ADDRESS_HEADER "%s\r\n", conn->base_.address);
2355 cp += strlen(cp);
2357 if (encoding) {
2358 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2359 "Content-Encoding: %s\r\n", encoding);
2360 cp += strlen(cp);
2362 if (length >= 0) {
2363 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2364 "Content-Length: %ld\r\n", (long)length);
2365 cp += strlen(cp);
2367 if (cache_lifetime > 0) {
2368 char expbuf[RFC1123_TIME_LEN+1];
2369 format_rfc1123_time(expbuf, (time_t)(now + cache_lifetime));
2370 /* We could say 'Cache-control: max-age=%d' here if we start doing
2371 * http/1.1 */
2372 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2373 "Expires: %s\r\n", expbuf);
2374 cp += strlen(cp);
2375 } else if (cache_lifetime == 0) {
2376 /* We could say 'Cache-control: no-cache' here if we start doing
2377 * http/1.1 */
2378 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2379 cp += strlen(cp);
2381 if (extra_headers) {
2382 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2383 cp += strlen(cp);
2385 if (sizeof(tmp)-(cp-tmp) > 3)
2386 memcpy(cp, "\r\n", 3);
2387 else
2388 tor_assert(0);
2389 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2392 /** As write_http_response_header_impl, but sets encoding and content-typed
2393 * based on whether the response will be <b>compressed</b> or not. */
2394 static void
2395 write_http_response_header(dir_connection_t *conn, ssize_t length,
2396 int compressed, long cache_lifetime)
2398 write_http_response_header_impl(conn, length,
2399 compressed?"application/octet-stream":"text/plain",
2400 compressed?"deflate":"identity",
2401 NULL,
2402 cache_lifetime);
2405 #if defined(INSTRUMENT_DOWNLOADS) || defined(RUNNING_DOXYGEN)
2406 /* DOCDOC */
2407 typedef struct request_t {
2408 uint64_t bytes; /**< How many bytes have we transferred? */
2409 uint64_t count; /**< How many requests have we made? */
2410 } request_t;
2412 /** Map used to keep track of how much data we've up/downloaded in what kind
2413 * of request. Maps from request type to pointer to request_t. */
2414 static strmap_t *request_map = NULL;
2416 /** Record that a client request of <b>purpose</b> was made, and that
2417 * <b>bytes</b> bytes of possibly <b>compressed</b> data were sent/received.
2418 * Used to keep track of how much we've up/downloaded in what kind of
2419 * request. */
2420 static void
2421 note_client_request(int purpose, int compressed, size_t bytes)
2423 char *key;
2424 const char *kind = NULL;
2425 switch (purpose) {
2426 case DIR_PURPOSE_FETCH_CONSENSUS: kind = "dl/consensus"; break;
2427 case DIR_PURPOSE_FETCH_CERTIFICATE: kind = "dl/cert"; break;
2428 case DIR_PURPOSE_FETCH_STATUS_VOTE: kind = "dl/vote"; break;
2429 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: kind = "dl/detached_sig";
2430 break;
2431 case DIR_PURPOSE_FETCH_SERVERDESC: kind = "dl/server"; break;
2432 case DIR_PURPOSE_FETCH_EXTRAINFO: kind = "dl/extra"; break;
2433 case DIR_PURPOSE_UPLOAD_DIR: kind = "dl/ul-dir"; break;
2434 case DIR_PURPOSE_UPLOAD_VOTE: kind = "dl/ul-vote"; break;
2435 case DIR_PURPOSE_UPLOAD_SIGNATURES: kind = "dl/ul-sig"; break;
2436 case DIR_PURPOSE_FETCH_RENDDESC_V2: kind = "dl/rend2"; break;
2437 case DIR_PURPOSE_UPLOAD_RENDDESC_V2: kind = "dl/ul-rend2"; break;
2439 if (kind) {
2440 tor_asprintf(&key, "%s%s", kind, compressed?".z":"");
2441 } else {
2442 tor_asprintf(&key, "unknown purpose (%d)%s",
2443 purpose, compressed?".z":"");
2445 note_request(key, bytes);
2446 tor_free(key);
2449 /** Helper: initialize the request map to instrument downloads. */
2450 static void
2451 ensure_request_map_initialized(void)
2453 if (!request_map)
2454 request_map = strmap_new();
2457 /** Called when we just transmitted or received <b>bytes</b> worth of data
2458 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2459 * <b>bytes</b> to the total associated with key. */
2460 void
2461 note_request(const char *key, size_t bytes)
2463 request_t *r;
2464 ensure_request_map_initialized();
2466 r = strmap_get(request_map, key);
2467 if (!r) {
2468 r = tor_malloc_zero(sizeof(request_t));
2469 strmap_set(request_map, key, r);
2471 r->bytes += bytes;
2472 r->count++;
2475 /** Return a newly allocated string holding a summary of bytes used per
2476 * request type. */
2477 char *
2478 directory_dump_request_log(void)
2480 smartlist_t *lines;
2481 char *result;
2482 strmap_iter_t *iter;
2484 ensure_request_map_initialized();
2486 lines = smartlist_new();
2488 for (iter = strmap_iter_init(request_map);
2489 !strmap_iter_done(iter);
2490 iter = strmap_iter_next(request_map, iter)) {
2491 const char *key;
2492 void *val;
2493 request_t *r;
2494 strmap_iter_get(iter, &key, &val);
2495 r = val;
2496 smartlist_add_asprintf(lines, "%s "U64_FORMAT" "U64_FORMAT"\n",
2497 key, U64_PRINTF_ARG(r->bytes), U64_PRINTF_ARG(r->count));
2499 smartlist_sort_strings(lines);
2500 result = smartlist_join_strings(lines, "", 0, NULL);
2501 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2502 smartlist_free(lines);
2503 return result;
2505 #else
2506 static void
2507 note_client_request(int purpose, int compressed, size_t bytes)
2509 (void)purpose;
2510 (void)compressed;
2511 (void)bytes;
2514 void
2515 note_request(const char *key, size_t bytes)
2517 (void)key;
2518 (void)bytes;
2521 char *
2522 directory_dump_request_log(void)
2524 return tor_strdup("Not supported.");
2526 #endif
2528 /** Decide whether a client would accept the consensus we have.
2530 * Clients can say they only want a consensus if it's signed by more
2531 * than half the authorities in a list. They pass this list in
2532 * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
2534 * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
2535 * of the full authority identity digest. (Only strings of even length,
2536 * i.e. encodings of full bytes, are handled correctly. In the case
2537 * of an odd number of hex digits the last one is silently ignored.)
2539 * Returns 1 if more than half of the requested authorities signed the
2540 * consensus, 0 otherwise.
2543 client_likes_consensus(networkstatus_t *v, const char *want_url)
2545 smartlist_t *want_authorities = smartlist_new();
2546 int need_at_least;
2547 int have = 0;
2549 dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0);
2550 need_at_least = smartlist_len(want_authorities)/2+1;
2551 SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, d) {
2552 char want_digest[DIGEST_LEN];
2553 size_t want_len = strlen(d)/2;
2554 if (want_len > DIGEST_LEN)
2555 want_len = DIGEST_LEN;
2557 if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) {
2558 log_fn(LOG_PROTOCOL_WARN, LD_DIR,
2559 "Failed to decode requested authority digest %s.", escaped(d));
2560 continue;
2563 SMARTLIST_FOREACH_BEGIN(v->voters, networkstatus_voter_info_t *, vi) {
2564 if (smartlist_len(vi->sigs) &&
2565 tor_memeq(vi->identity_digest, want_digest, want_len)) {
2566 have++;
2567 break;
2569 } SMARTLIST_FOREACH_END(vi);
2571 /* early exit, if we already have enough */
2572 if (have >= need_at_least)
2573 break;
2574 } SMARTLIST_FOREACH_END(d);
2576 SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
2577 smartlist_free(want_authorities);
2578 return (have >= need_at_least);
2581 /** Return the compression level we should use for sending a compressed
2582 * response of size <b>n_bytes</b>. */
2583 static zlib_compression_level_t
2584 choose_compression_level(ssize_t n_bytes)
2586 if (! have_been_under_memory_pressure()) {
2587 return HIGH_COMPRESSION; /* we have plenty of RAM. */
2588 } else if (n_bytes < 0) {
2589 return HIGH_COMPRESSION; /* unknown; might be big. */
2590 } else if (n_bytes < 1024) {
2591 return LOW_COMPRESSION;
2592 } else if (n_bytes < 2048) {
2593 return MEDIUM_COMPRESSION;
2594 } else {
2595 return HIGH_COMPRESSION;
2599 /** Helper function: called when a dirserver gets a complete HTTP GET
2600 * request. Look for a request for a directory or for a rendezvous
2601 * service descriptor. On finding one, write a response into
2602 * conn-\>outbuf. If the request is unrecognized, send a 400.
2603 * Always return 0. */
2604 STATIC int
2605 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2606 const char *req_body, size_t req_body_len)
2608 size_t dlen;
2609 char *url, *url_mem, *header;
2610 const or_options_t *options = get_options();
2611 time_t if_modified_since = 0;
2612 int compressed;
2613 size_t url_len;
2615 /* We ignore the body of a GET request. */
2616 (void)req_body;
2617 (void)req_body_len;
2619 log_debug(LD_DIRSERV,"Received GET command.");
2621 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
2623 if (parse_http_url(headers, &url) < 0) {
2624 write_http_status_line(conn, 400, "Bad request");
2625 return 0;
2627 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2628 struct tm tm;
2629 if (parse_http_time(header, &tm) == 0) {
2630 if (tor_timegm(&tm, &if_modified_since)<0) {
2631 if_modified_since = 0;
2632 } else {
2633 log_debug(LD_DIRSERV, "If-Modified-Since is '%s'.", escaped(header));
2636 /* The correct behavior on a malformed If-Modified-Since header is to
2637 * act as if no If-Modified-Since header had been given. */
2638 tor_free(header);
2640 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
2642 url_mem = url;
2643 url_len = strlen(url);
2644 compressed = url_len > 2 && !strcmp(url+url_len-2, ".z");
2645 if (compressed) {
2646 url[url_len-2] = '\0';
2647 url_len -= 2;
2650 if (!strcmp(url,"/tor/")) {
2651 const char *frontpage = get_dirportfrontpage();
2653 if (frontpage) {
2654 dlen = strlen(frontpage);
2655 /* Let's return a disclaimer page (users shouldn't use V1 anymore,
2656 and caches don't fetch '/', so this is safe). */
2658 /* [We don't check for write_bucket_low here, since we want to serve
2659 * this page no matter what.] */
2660 note_request(url, dlen);
2661 write_http_response_header_impl(conn, dlen, "text/html", "identity",
2662 NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
2663 connection_write_to_buf(frontpage, dlen, TO_CONN(conn));
2664 goto done;
2666 /* if no disclaimer file, fall through and continue */
2669 if (!strcmpstart(url, "/tor/status-vote/current/consensus")) {
2670 /* v3 network status fetch. */
2671 smartlist_t *dir_fps = smartlist_new();
2672 const char *request_type = NULL;
2673 long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2675 if (1) {
2676 networkstatus_t *v;
2677 time_t now = time(NULL);
2678 const char *want_fps = NULL;
2679 char *flavor = NULL;
2680 int flav = FLAV_NS;
2681 #define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/"
2682 #define CONSENSUS_FLAVORED_PREFIX "/tor/status-vote/current/consensus-"
2683 /* figure out the flavor if any, and who we wanted to sign the thing */
2684 if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) {
2685 const char *f, *cp;
2686 f = url + strlen(CONSENSUS_FLAVORED_PREFIX);
2687 cp = strchr(f, '/');
2688 if (cp) {
2689 want_fps = cp+1;
2690 flavor = tor_strndup(f, cp-f);
2691 } else {
2692 flavor = tor_strdup(f);
2694 flav = networkstatus_parse_flavor_name(flavor);
2695 if (flav < 0)
2696 flav = FLAV_NS;
2697 } else {
2698 if (!strcmpstart(url, CONSENSUS_URL_PREFIX))
2699 want_fps = url+strlen(CONSENSUS_URL_PREFIX);
2702 v = networkstatus_get_latest_consensus_by_flavor(flav);
2704 if (v && want_fps &&
2705 !client_likes_consensus(v, want_fps)) {
2706 write_http_status_line(conn, 404, "Consensus not signed by sufficient "
2707 "number of requested authorities");
2708 smartlist_free(dir_fps);
2709 geoip_note_ns_response(GEOIP_REJECT_NOT_ENOUGH_SIGS);
2710 tor_free(flavor);
2711 goto done;
2715 char *fp = tor_malloc_zero(DIGEST_LEN);
2716 if (flavor)
2717 strlcpy(fp, flavor, DIGEST_LEN);
2718 tor_free(flavor);
2719 smartlist_add(dir_fps, fp);
2721 request_type = compressed?"v3.z":"v3";
2722 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2725 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2726 write_http_status_line(conn, 503, "Network status object unavailable");
2727 smartlist_free(dir_fps);
2728 geoip_note_ns_response(GEOIP_REJECT_UNAVAILABLE);
2729 goto done;
2732 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2733 write_http_status_line(conn, 404, "Not found");
2734 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2735 smartlist_free(dir_fps);
2736 geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
2737 goto done;
2738 } else if (!smartlist_len(dir_fps)) {
2739 write_http_status_line(conn, 304, "Not modified");
2740 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2741 smartlist_free(dir_fps);
2742 geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
2743 goto done;
2746 dlen = dirserv_estimate_data_size(dir_fps, 0, compressed);
2747 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2748 log_debug(LD_DIRSERV,
2749 "Client asked for network status lists, but we've been "
2750 "writing too many bytes lately. Sending 503 Dir busy.");
2751 write_http_status_line(conn, 503, "Directory busy, try again later");
2752 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2753 smartlist_free(dir_fps);
2755 geoip_note_ns_response(GEOIP_REJECT_BUSY);
2756 goto done;
2759 if (1) {
2760 struct in_addr in;
2761 tor_addr_t addr;
2762 if (tor_inet_aton((TO_CONN(conn))->address, &in)) {
2763 tor_addr_from_ipv4h(&addr, ntohl(in.s_addr));
2764 geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS,
2765 &addr, NULL,
2766 time(NULL));
2767 geoip_note_ns_response(GEOIP_SUCCESS);
2768 /* Note that a request for a network status has started, so that we
2769 * can measure the download time later on. */
2770 if (conn->dirreq_id)
2771 geoip_start_dirreq(conn->dirreq_id, dlen, DIRREQ_TUNNELED);
2772 else
2773 geoip_start_dirreq(TO_CONN(conn)->global_identifier, dlen,
2774 DIRREQ_DIRECT);
2778 // note_request(request_type,dlen);
2779 (void) request_type;
2780 write_http_response_header(conn, -1, compressed,
2781 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2782 conn->fingerprint_stack = dir_fps;
2783 if (! compressed)
2784 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
2786 /* Prime the connection with some data. */
2787 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2788 connection_dirserv_flushed_some(conn);
2789 goto done;
2792 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2793 !strcmpstart(url,"/tor/status-vote/next/")) {
2794 /* XXXX If-modified-since is only implemented for the current
2795 * consensus: that's probably fine, since it's the only vote document
2796 * people fetch much. */
2797 int current;
2798 ssize_t body_len = 0;
2799 ssize_t estimated_len = 0;
2800 smartlist_t *items = smartlist_new();
2801 smartlist_t *dir_items = smartlist_new();
2802 int lifetime = 60; /* XXXX023 should actually use vote intervals. */
2803 url += strlen("/tor/status-vote/");
2804 current = !strcmpstart(url, "current/");
2805 url = strchr(url, '/');
2806 tor_assert(url);
2807 ++url;
2808 if (!strcmp(url, "consensus")) {
2809 const char *item;
2810 tor_assert(!current); /* we handle current consensus specially above,
2811 * since it wants to be spooled. */
2812 if ((item = dirvote_get_pending_consensus(FLAV_NS)))
2813 smartlist_add(items, (char*)item);
2814 } else if (!current && !strcmp(url, "consensus-signatures")) {
2815 /* XXXX the spec says that we should implement
2816 * current/consensus-signatures too. It doesn't seem to be needed,
2817 * though. */
2818 const char *item;
2819 if ((item=dirvote_get_pending_detached_signatures()))
2820 smartlist_add(items, (char*)item);
2821 } else if (!strcmp(url, "authority")) {
2822 const cached_dir_t *d;
2823 int flags = DGV_BY_ID |
2824 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2825 if ((d=dirvote_get_vote(NULL, flags)))
2826 smartlist_add(dir_items, (cached_dir_t*)d);
2827 } else {
2828 const cached_dir_t *d;
2829 smartlist_t *fps = smartlist_new();
2830 int flags;
2831 if (!strcmpstart(url, "d/")) {
2832 url += 2;
2833 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2834 } else {
2835 flags = DGV_BY_ID |
2836 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2838 dir_split_resource_into_fingerprints(url, fps, NULL,
2839 DSR_HEX|DSR_SORT_UNIQ);
2840 SMARTLIST_FOREACH(fps, char *, fp, {
2841 if ((d = dirvote_get_vote(fp, flags)))
2842 smartlist_add(dir_items, (cached_dir_t*)d);
2843 tor_free(fp);
2845 smartlist_free(fps);
2847 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2848 write_http_status_line(conn, 404, "Not found");
2849 goto vote_done;
2851 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2852 body_len += compressed ? d->dir_z_len : d->dir_len);
2853 estimated_len += body_len;
2854 SMARTLIST_FOREACH(items, const char *, item, {
2855 size_t ln = strlen(item);
2856 if (compressed) {
2857 estimated_len += ln/2;
2858 } else {
2859 body_len += ln; estimated_len += ln;
2863 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
2864 write_http_status_line(conn, 503, "Directory busy, try again later");
2865 goto vote_done;
2867 write_http_response_header(conn, body_len ? body_len : -1, compressed,
2868 lifetime);
2870 if (smartlist_len(items)) {
2871 if (compressed) {
2872 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD,
2873 choose_compression_level(estimated_len));
2874 SMARTLIST_FOREACH(items, const char *, c,
2875 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2876 connection_write_to_buf_zlib("", 0, conn, 1);
2877 } else {
2878 SMARTLIST_FOREACH(items, const char *, c,
2879 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2881 } else {
2882 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2883 connection_write_to_buf(compressed ? d->dir_z : d->dir,
2884 compressed ? d->dir_z_len : d->dir_len,
2885 TO_CONN(conn)));
2887 vote_done:
2888 smartlist_free(items);
2889 smartlist_free(dir_items);
2890 goto done;
2893 if (!strcmpstart(url, "/tor/micro/d/")) {
2894 smartlist_t *fps = smartlist_new();
2896 dir_split_resource_into_fingerprints(url+strlen("/tor/micro/d/"),
2897 fps, NULL,
2898 DSR_DIGEST256|DSR_BASE64|DSR_SORT_UNIQ);
2900 if (!dirserv_have_any_microdesc(fps)) {
2901 write_http_status_line(conn, 404, "Not found");
2902 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
2903 smartlist_free(fps);
2904 goto done;
2906 dlen = dirserv_estimate_microdesc_size(fps, compressed);
2907 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2908 log_info(LD_DIRSERV,
2909 "Client asked for server descriptors, but we've been "
2910 "writing too many bytes lately. Sending 503 Dir busy.");
2911 write_http_status_line(conn, 503, "Directory busy, try again later");
2912 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
2913 smartlist_free(fps);
2914 goto done;
2917 write_http_response_header(conn, -1, compressed, MICRODESC_CACHE_LIFETIME);
2918 conn->dir_spool_src = DIR_SPOOL_MICRODESC;
2919 conn->fingerprint_stack = fps;
2921 if (compressed)
2922 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD,
2923 choose_compression_level(dlen));
2925 connection_dirserv_flushed_some(conn);
2926 goto done;
2929 if (!strcmpstart(url,"/tor/server/") ||
2930 (!options->BridgeAuthoritativeDir &&
2931 !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
2932 int res;
2933 const char *msg;
2934 const char *request_type = NULL;
2935 int cache_lifetime = 0;
2936 int is_extra = !strcmpstart(url,"/tor/extra/");
2937 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2938 conn->fingerprint_stack = smartlist_new();
2939 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2940 &msg,
2941 !connection_dir_is_encrypted(conn),
2942 is_extra);
2944 if (!strcmpstart(url, "fp/")) {
2945 request_type = compressed?"/tor/server/fp.z":"/tor/server/fp";
2946 if (smartlist_len(conn->fingerprint_stack) == 1)
2947 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2948 } else if (!strcmpstart(url, "authority")) {
2949 request_type = compressed?"/tor/server/authority.z":
2950 "/tor/server/authority";
2951 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2952 } else if (!strcmpstart(url, "all")) {
2953 request_type = compressed?"/tor/server/all.z":"/tor/server/all";
2954 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2955 } else if (!strcmpstart(url, "d/")) {
2956 request_type = compressed?"/tor/server/d.z":"/tor/server/d";
2957 if (smartlist_len(conn->fingerprint_stack) == 1)
2958 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2959 } else {
2960 request_type = "/tor/server/?";
2962 (void) request_type; /* usable for note_request. */
2963 if (!strcmpstart(url, "d/"))
2964 conn->dir_spool_src =
2965 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2966 else
2967 conn->dir_spool_src =
2968 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2970 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2971 conn->dir_spool_src)) {
2972 res = -1;
2973 msg = "Not found";
2976 if (res < 0)
2977 write_http_status_line(conn, 404, msg);
2978 else {
2979 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2980 1, compressed);
2981 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2982 log_info(LD_DIRSERV,
2983 "Client asked for server descriptors, but we've been "
2984 "writing too many bytes lately. Sending 503 Dir busy.");
2985 write_http_status_line(conn, 503, "Directory busy, try again later");
2986 conn->dir_spool_src = DIR_SPOOL_NONE;
2987 goto done;
2989 write_http_response_header(conn, -1, compressed, cache_lifetime);
2990 if (compressed)
2991 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD,
2992 choose_compression_level(dlen));
2993 /* Prime the connection with some data. */
2994 connection_dirserv_flushed_some(conn);
2996 goto done;
2999 if (!strcmpstart(url,"/tor/keys/")) {
3000 smartlist_t *certs = smartlist_new();
3001 ssize_t len = -1;
3002 if (!strcmp(url, "/tor/keys/all")) {
3003 authority_cert_get_all(certs);
3004 } else if (!strcmp(url, "/tor/keys/authority")) {
3005 authority_cert_t *cert = get_my_v3_authority_cert();
3006 if (cert)
3007 smartlist_add(certs, cert);
3008 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
3009 smartlist_t *fps = smartlist_new();
3010 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
3011 fps, NULL,
3012 DSR_HEX|DSR_SORT_UNIQ);
3013 SMARTLIST_FOREACH(fps, char *, d, {
3014 authority_cert_t *c = authority_cert_get_newest_by_id(d);
3015 if (c) smartlist_add(certs, c);
3016 tor_free(d);
3018 smartlist_free(fps);
3019 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
3020 smartlist_t *fps = smartlist_new();
3021 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
3022 fps, NULL,
3023 DSR_HEX|DSR_SORT_UNIQ);
3024 SMARTLIST_FOREACH(fps, char *, d, {
3025 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
3026 if (c) smartlist_add(certs, c);
3027 tor_free(d);
3029 smartlist_free(fps);
3030 } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
3031 smartlist_t *fp_sks = smartlist_new();
3032 dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
3033 fp_sks);
3034 SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
3035 authority_cert_t *c = authority_cert_get_by_digests(pair->first,
3036 pair->second);
3037 if (c) smartlist_add(certs, c);
3038 tor_free(pair);
3040 smartlist_free(fp_sks);
3041 } else {
3042 write_http_status_line(conn, 400, "Bad request");
3043 goto keys_done;
3045 if (!smartlist_len(certs)) {
3046 write_http_status_line(conn, 404, "Not found");
3047 goto keys_done;
3049 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3050 if (c->cache_info.published_on < if_modified_since)
3051 SMARTLIST_DEL_CURRENT(certs, c));
3052 if (!smartlist_len(certs)) {
3053 write_http_status_line(conn, 304, "Not modified");
3054 goto keys_done;
3056 len = 0;
3057 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3058 len += c->cache_info.signed_descriptor_len);
3060 if (global_write_bucket_low(TO_CONN(conn), compressed?len/2:len, 2)) {
3061 write_http_status_line(conn, 503, "Directory busy, try again later");
3062 goto keys_done;
3065 write_http_response_header(conn, compressed?-1:len, compressed, 60*60);
3066 if (compressed) {
3067 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD,
3068 choose_compression_level(len));
3069 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3070 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
3071 c->cache_info.signed_descriptor_len,
3072 conn, 0));
3073 connection_write_to_buf_zlib("", 0, conn, 1);
3074 } else {
3075 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3076 connection_write_to_buf(c->cache_info.signed_descriptor_body,
3077 c->cache_info.signed_descriptor_len,
3078 TO_CONN(conn)));
3080 keys_done:
3081 smartlist_free(certs);
3082 goto done;
3085 if (connection_dir_is_encrypted(conn) &&
3086 !strcmpstart(url,"/tor/rendezvous2/")) {
3087 /* Handle v2 rendezvous descriptor fetch request. */
3088 const char *descp;
3089 const char *query = url + strlen("/tor/rendezvous2/");
3090 if (rend_valid_descriptor_id(query)) {
3091 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
3092 safe_str(escaped(query)));
3093 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
3094 case 1: /* valid */
3095 write_http_response_header(conn, strlen(descp), 0, 0);
3096 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
3097 break;
3098 case 0: /* well-formed but not present */
3099 write_http_status_line(conn, 404, "Not found");
3100 break;
3101 case -1: /* not well-formed */
3102 write_http_status_line(conn, 400, "Bad request");
3103 break;
3105 } else { /* not well-formed */
3106 write_http_status_line(conn, 400, "Bad request");
3108 goto done;
3111 if (options->BridgeAuthoritativeDir &&
3112 options->BridgePassword_AuthDigest_ &&
3113 connection_dir_is_encrypted(conn) &&
3114 !strcmp(url,"/tor/networkstatus-bridges")) {
3115 char *status;
3116 char digest[DIGEST256_LEN];
3118 header = http_get_header(headers, "Authorization: Basic ");
3119 if (header)
3120 crypto_digest256(digest, header, strlen(header), DIGEST_SHA256);
3122 /* now make sure the password is there and right */
3123 if (!header ||
3124 tor_memneq(digest,
3125 options->BridgePassword_AuthDigest_, DIGEST256_LEN)) {
3126 write_http_status_line(conn, 404, "Not found");
3127 tor_free(header);
3128 goto done;
3130 tor_free(header);
3132 /* all happy now. send an answer. */
3133 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
3134 dlen = strlen(status);
3135 write_http_response_header(conn, dlen, 0, 0);
3136 connection_write_to_buf(status, dlen, TO_CONN(conn));
3137 tor_free(status);
3138 goto done;
3141 if (!strcmpstart(url,"/tor/bytes.txt")) {
3142 char *bytes = directory_dump_request_log();
3143 size_t len = strlen(bytes);
3144 write_http_response_header(conn, len, 0, 0);
3145 connection_write_to_buf(bytes, len, TO_CONN(conn));
3146 tor_free(bytes);
3147 goto done;
3150 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
3151 rewritten to /tor/robots.txt */
3152 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
3153 size_t len = strlen(robots);
3154 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
3155 connection_write_to_buf(robots, len, TO_CONN(conn));
3156 goto done;
3159 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
3160 #define ADD_MALLINFO_LINE(x) do { \
3161 smartlist_add_asprintf(lines, "%s %d\n", #x, mi.x); \
3162 }while(0);
3164 if (!strcmp(url,"/tor/mallinfo.txt") &&
3165 (tor_addr_eq_ipv4h(&conn->base_.addr, 0x7f000001ul))) {
3166 char *result;
3167 size_t len;
3168 struct mallinfo mi;
3169 smartlist_t *lines;
3171 memset(&mi, 0, sizeof(mi));
3172 mi = mallinfo();
3173 lines = smartlist_new();
3175 ADD_MALLINFO_LINE(arena)
3176 ADD_MALLINFO_LINE(ordblks)
3177 ADD_MALLINFO_LINE(smblks)
3178 ADD_MALLINFO_LINE(hblks)
3179 ADD_MALLINFO_LINE(hblkhd)
3180 ADD_MALLINFO_LINE(usmblks)
3181 ADD_MALLINFO_LINE(fsmblks)
3182 ADD_MALLINFO_LINE(uordblks)
3183 ADD_MALLINFO_LINE(fordblks)
3184 ADD_MALLINFO_LINE(keepcost)
3186 result = smartlist_join_strings(lines, "", 0, NULL);
3187 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
3188 smartlist_free(lines);
3190 len = strlen(result);
3191 write_http_response_header(conn, len, 0, 0);
3192 connection_write_to_buf(result, len, TO_CONN(conn));
3193 tor_free(result);
3194 goto done;
3196 #endif
3198 /* we didn't recognize the url */
3199 write_http_status_line(conn, 404, "Not found");
3201 done:
3202 tor_free(url_mem);
3203 return 0;
3206 /** Helper function: called when a dirserver gets a complete HTTP POST
3207 * request. Look for an uploaded server descriptor or rendezvous
3208 * service descriptor. On finding one, process it and write a
3209 * response into conn-\>outbuf. If the request is unrecognized, send a
3210 * 400. Always return 0. */
3211 static int
3212 directory_handle_command_post(dir_connection_t *conn, const char *headers,
3213 const char *body, size_t body_len)
3215 char *url = NULL;
3216 const or_options_t *options = get_options();
3218 log_debug(LD_DIRSERV,"Received POST command.");
3220 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
3222 if (parse_http_url(headers, &url) < 0) {
3223 write_http_status_line(conn, 400, "Bad request");
3224 return 0;
3226 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
3228 /* Handle v2 rendezvous service publish request. */
3229 if (connection_dir_is_encrypted(conn) &&
3230 !strcmpstart(url,"/tor/rendezvous2/publish")) {
3231 switch (rend_cache_store_v2_desc_as_dir(body)) {
3232 case RCS_NOTDIR:
3233 log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
3234 "since we're not currently a hidden service directory.",
3235 (int)body_len, conn->base_.address);
3236 write_http_status_line(conn, 503, "Currently not acting as v2 "
3237 "hidden service directory");
3238 break;
3239 case RCS_BADDESC:
3240 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
3241 (int)body_len, conn->base_.address);
3242 write_http_status_line(conn, 400,
3243 "Invalid v2 service descriptor rejected");
3244 break;
3245 case RCS_OKAY:
3246 default:
3247 write_http_status_line(conn, 200, "Service descriptor (v2) stored");
3248 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
3250 goto done;
3253 if (!authdir_mode(options)) {
3254 /* we just provide cached directories; we don't want to
3255 * receive anything. */
3256 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
3257 "accept posted server descriptors");
3258 goto done;
3261 if (authdir_mode_handles_descs(options, -1) &&
3262 !strcmp(url,"/tor/")) { /* server descriptor post */
3263 const char *msg = "[None]";
3264 uint8_t purpose = authdir_mode_bridge(options) ?
3265 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
3266 was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
3267 conn->base_.address, &msg);
3268 tor_assert(msg);
3270 if (r == ROUTER_ADDED_NOTIFY_GENERATOR) {
3271 /* Accepted with a message. */
3272 log_info(LD_DIRSERV,
3273 "Problematic router descriptor or extra-info from %s "
3274 "(\"%s\").",
3275 conn->base_.address, msg);
3276 write_http_status_line(conn, 400, msg);
3277 } else if (r == ROUTER_ADDED_SUCCESSFULLY) {
3278 write_http_status_line(conn, 200, msg);
3279 } else if (WRA_WAS_OUTDATED(r)) {
3280 write_http_response_header_impl(conn, -1, NULL, NULL,
3281 "X-Descriptor-Not-New: Yes\r\n", -1);
3282 } else {
3283 log_info(LD_DIRSERV,
3284 "Rejected router descriptor or extra-info from %s "
3285 "(\"%s\").",
3286 conn->base_.address, msg);
3287 write_http_status_line(conn, 400, msg);
3289 goto done;
3292 if (authdir_mode_v3(options) &&
3293 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
3294 const char *msg = "OK";
3295 int status;
3296 if (dirvote_add_vote(body, &msg, &status)) {
3297 write_http_status_line(conn, status, "Vote stored");
3298 } else {
3299 tor_assert(msg);
3300 log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").",
3301 conn->base_.address, msg);
3302 write_http_status_line(conn, status, msg);
3304 goto done;
3307 if (authdir_mode_v3(options) &&
3308 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
3309 const char *msg = NULL;
3310 if (dirvote_add_signatures(body, conn->base_.address, &msg)>=0) {
3311 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
3312 } else {
3313 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
3314 conn->base_.address, msg?msg:"???");
3315 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
3317 goto done;
3320 /* we didn't recognize the url */
3321 write_http_status_line(conn, 404, "Not found");
3323 done:
3324 tor_free(url);
3325 return 0;
3328 /** Called when a dirserver receives data on a directory connection;
3329 * looks for an HTTP request. If the request is complete, remove it
3330 * from the inbuf, try to process it; otherwise, leave it on the
3331 * buffer. Return a 0 on success, or -1 on error.
3333 static int
3334 directory_handle_command(dir_connection_t *conn)
3336 char *headers=NULL, *body=NULL;
3337 size_t body_len=0;
3338 int r;
3340 tor_assert(conn);
3341 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3343 switch (connection_fetch_from_buf_http(TO_CONN(conn),
3344 &headers, MAX_HEADERS_SIZE,
3345 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
3346 case -1: /* overflow */
3347 log_warn(LD_DIRSERV,
3348 "Request too large from address '%s' to DirPort. Closing.",
3349 safe_str(conn->base_.address));
3350 return -1;
3351 case 0:
3352 log_debug(LD_DIRSERV,"command not all here yet.");
3353 return 0;
3354 /* case 1, fall through */
3357 http_set_address_origin(headers, TO_CONN(conn));
3358 // we should escape headers here as well,
3359 // but we can't call escaped() twice, as it uses the same buffer
3360 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, escaped(body));
3362 if (!strncasecmp(headers,"GET",3))
3363 r = directory_handle_command_get(conn, headers, body, body_len);
3364 else if (!strncasecmp(headers,"POST",4))
3365 r = directory_handle_command_post(conn, headers, body, body_len);
3366 else {
3367 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
3368 "Got headers %s with unknown command. Closing.",
3369 escaped(headers));
3370 r = -1;
3373 tor_free(headers); tor_free(body);
3374 return r;
3377 /** Write handler for directory connections; called when all data has
3378 * been flushed. Close the connection or wait for a response as
3379 * appropriate.
3382 connection_dir_finished_flushing(dir_connection_t *conn)
3384 tor_assert(conn);
3385 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3387 /* Note that we have finished writing the directory response. For direct
3388 * connections this means we're done; for tunneled connections it's only
3389 * an intermediate step. */
3390 if (conn->dirreq_id)
3391 geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
3392 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3393 else
3394 geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
3395 DIRREQ_DIRECT,
3396 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3397 switch (conn->base_.state) {
3398 case DIR_CONN_STATE_CONNECTING:
3399 case DIR_CONN_STATE_CLIENT_SENDING:
3400 log_debug(LD_DIR,"client finished sending command.");
3401 conn->base_.state = DIR_CONN_STATE_CLIENT_READING;
3402 return 0;
3403 case DIR_CONN_STATE_SERVER_WRITING:
3404 if (conn->dir_spool_src != DIR_SPOOL_NONE) {
3405 #ifdef USE_BUFFEREVENTS
3406 /* This can happen with paired bufferevents, since a paired connection
3407 * can flush immediately when you write to it, making the subsequent
3408 * check in connection_handle_write_cb() decide that the connection
3409 * is flushed. */
3410 log_debug(LD_DIRSERV, "Emptied a dirserv buffer, but still spooling.");
3411 #else
3412 log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
3413 connection_mark_for_close(TO_CONN(conn));
3414 #endif
3415 } else {
3416 log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
3417 connection_mark_for_close(TO_CONN(conn));
3419 return 0;
3420 default:
3421 log_warn(LD_BUG,"called in unexpected state %d.",
3422 conn->base_.state);
3423 tor_fragile_assert();
3424 return -1;
3426 return 0;
3429 /** Connected handler for directory connections: begin sending data to the
3430 * server */
3432 connection_dir_finished_connecting(dir_connection_t *conn)
3434 tor_assert(conn);
3435 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3436 tor_assert(conn->base_.state == DIR_CONN_STATE_CONNECTING);
3438 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
3439 conn->base_.address,conn->base_.port);
3441 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
3442 return 0;
3445 /** Decide which download schedule we want to use based on descriptor type
3446 * in <b>dls</b> and whether we are acting as directory <b>server</b>, and
3447 * then return a list of int pointers defining download delays in seconds.
3448 * Helper function for download_status_increment_failure() and
3449 * download_status_reset(). */
3450 static const smartlist_t *
3451 find_dl_schedule_and_len(download_status_t *dls, int server)
3453 switch (dls->schedule) {
3454 case DL_SCHED_GENERIC:
3455 if (server)
3456 return get_options()->TestingServerDownloadSchedule;
3457 else
3458 return get_options()->TestingClientDownloadSchedule;
3459 case DL_SCHED_CONSENSUS:
3460 if (server)
3461 return get_options()->TestingServerConsensusDownloadSchedule;
3462 else
3463 return get_options()->TestingClientConsensusDownloadSchedule;
3464 case DL_SCHED_BRIDGE:
3465 return get_options()->TestingBridgeDownloadSchedule;
3466 default:
3467 tor_assert(0);
3470 /* Impossible, but gcc will fail with -Werror without a `return`. */
3471 return NULL;
3474 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
3475 * <b>status_code</b>. Increment the failure count (if the code indicates a
3476 * real failure) and set <b>dls</b>-\>next_attempt_at to an appropriate time
3477 * in the future. */
3478 time_t
3479 download_status_increment_failure(download_status_t *dls, int status_code,
3480 const char *item, int server, time_t now)
3482 const smartlist_t *schedule;
3483 int increment;
3484 tor_assert(dls);
3485 if (status_code != 503 || server) {
3486 if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1)
3487 ++dls->n_download_failures;
3490 schedule = find_dl_schedule_and_len(dls, server);
3492 if (dls->n_download_failures < smartlist_len(schedule))
3493 increment = *(int *)smartlist_get(schedule, dls->n_download_failures);
3494 else if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
3495 increment = INT_MAX;
3496 else
3497 increment = *(int *)smartlist_get(schedule, smartlist_len(schedule) - 1);
3499 if (increment < INT_MAX)
3500 dls->next_attempt_at = now+increment;
3501 else
3502 dls->next_attempt_at = TIME_MAX;
3504 if (item) {
3505 if (increment == 0)
3506 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
3507 item, (int)dls->n_download_failures);
3508 else if (dls->next_attempt_at < TIME_MAX)
3509 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
3510 item, (int)dls->n_download_failures,
3511 (int)(dls->next_attempt_at-now));
3512 else
3513 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
3514 item, (int)dls->n_download_failures);
3516 return dls->next_attempt_at;
3519 /** Reset <b>dls</b> so that it will be considered downloadable
3520 * immediately, and/or to show that we don't need it anymore.
3522 * (We find the zeroth element of the download schedule, and set
3523 * next_attempt_at to be the appropriate offset from 'now'. In most
3524 * cases this means setting it to 'now', so the item will be immediately
3525 * downloadable; in the case of bridge descriptors, the zeroth element
3526 * is an hour from now.) */
3527 void
3528 download_status_reset(download_status_t *dls)
3530 if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
3531 return; /* Don't reset this. */
3533 const smartlist_t *schedule = find_dl_schedule_and_len(
3534 dls, get_options()->DirPort_set);
3536 dls->n_download_failures = 0;
3537 dls->next_attempt_at = time(NULL) + *(int *)smartlist_get(schedule, 0);
3540 /** Return the number of failures on <b>dls</b> since the last success (if
3541 * any). */
3543 download_status_get_n_failures(const download_status_t *dls)
3545 return dls->n_download_failures;
3548 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
3549 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
3550 * either as descriptor digests or as identity digests based on
3551 * <b>was_descriptor_digests</b>).
3553 static void
3554 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
3555 int router_purpose,
3556 int was_extrainfo, int was_descriptor_digests)
3558 char digest[DIGEST_LEN];
3559 time_t now = time(NULL);
3560 int server = directory_fetches_from_authorities(get_options());
3561 if (!was_descriptor_digests) {
3562 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
3563 tor_assert(!was_extrainfo);
3564 connection_dir_retry_bridges(failed);
3566 return; /* FFFF should implement for other-than-router-purpose someday */
3568 SMARTLIST_FOREACH_BEGIN(failed, const char *, cp) {
3569 download_status_t *dls = NULL;
3570 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) {
3571 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
3572 continue;
3574 if (was_extrainfo) {
3575 signed_descriptor_t *sd =
3576 router_get_by_extrainfo_digest(digest);
3577 if (sd)
3578 dls = &sd->ei_dl_status;
3579 } else {
3580 dls = router_get_dl_status_by_descriptor_digest(digest);
3582 if (!dls || dls->n_download_failures >=
3583 get_options()->TestingDescriptorMaxDownloadTries)
3584 continue;
3585 download_status_increment_failure(dls, status_code, cp, server, now);
3586 } SMARTLIST_FOREACH_END(cp);
3588 /* No need to relaunch descriptor downloads here: we already do it
3589 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3592 /** Called when a connection to download microdescriptors has failed in whole
3593 * or in part. <b>failed</b> is a list of every microdesc digest we didn't
3594 * get. <b>status_code</b> is the http status code we received. Reschedule the
3595 * microdesc downloads as appropriate. */
3596 static void
3597 dir_microdesc_download_failed(smartlist_t *failed,
3598 int status_code)
3600 networkstatus_t *consensus
3601 = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
3602 routerstatus_t *rs;
3603 download_status_t *dls;
3604 time_t now = time(NULL);
3605 int server = directory_fetches_from_authorities(get_options());
3607 if (! consensus)
3608 return;
3609 SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
3610 rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
3611 if (!rs)
3612 continue;
3613 dls = &rs->dl_status;
3614 if (dls->n_download_failures >=
3615 get_options()->TestingMicrodescMaxDownloadTries)
3616 continue;
3618 char buf[BASE64_DIGEST256_LEN+1];
3619 digest256_to_base64(buf, d);
3620 download_status_increment_failure(dls, status_code, buf,
3621 server, now);
3623 } SMARTLIST_FOREACH_END(d);
3626 /** Helper. Compare two fp_pair_t objects, and return negative, 0, or
3627 * positive as appropriate. */
3628 static int
3629 compare_pairs_(const void **a, const void **b)
3631 const fp_pair_t *fp1 = *a, *fp2 = *b;
3632 int r;
3633 if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
3634 return r;
3635 else
3636 return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
3639 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
3640 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
3641 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
3642 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
3644 dir_split_resource_into_fingerprint_pairs(const char *res,
3645 smartlist_t *pairs_out)
3647 smartlist_t *pairs_tmp = smartlist_new();
3648 smartlist_t *pairs_result = smartlist_new();
3650 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
3651 if (smartlist_len(pairs_tmp)) {
3652 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
3653 size_t last_len = strlen(last);
3654 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3655 last[last_len-2] = '\0';
3658 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
3659 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
3660 log_info(LD_DIR,
3661 "Skipping digest pair %s with non-standard length.", escaped(cp));
3662 } else if (cp[HEX_DIGEST_LEN] != '-') {
3663 log_info(LD_DIR,
3664 "Skipping digest pair %s with missing dash.", escaped(cp));
3665 } else {
3666 fp_pair_t pair;
3667 if (base16_decode(pair.first, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0 ||
3668 base16_decode(pair.second,
3669 DIGEST_LEN, cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN)<0) {
3670 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
3671 } else {
3672 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
3675 tor_free(cp);
3676 } SMARTLIST_FOREACH_END(cp);
3677 smartlist_free(pairs_tmp);
3679 /* Uniq-and-sort */
3680 smartlist_sort(pairs_result, compare_pairs_);
3681 smartlist_uniq(pairs_result, compare_pairs_, tor_free_);
3683 smartlist_add_all(pairs_out, pairs_result);
3684 smartlist_free(pairs_result);
3685 return 0;
3688 /** Given a directory <b>resource</b> request, containing zero
3689 * or more strings separated by plus signs, followed optionally by ".z", store
3690 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3691 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
3693 * If (flags & DSR_HEX), then delete all elements that aren't hex digests, and
3694 * decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as
3695 * a separator, delete all the elements that aren't base64-encoded digests,
3696 * and decode the rest. If (flags & DSR_DIGEST256), these digests should be
3697 * 256 bits long; else they should be 160.
3699 * If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates.
3702 dir_split_resource_into_fingerprints(const char *resource,
3703 smartlist_t *fp_out, int *compressed_out,
3704 int flags)
3706 const int decode_hex = flags & DSR_HEX;
3707 const int decode_base64 = flags & DSR_BASE64;
3708 const int digests_are_256 = flags & DSR_DIGEST256;
3709 const int sort_uniq = flags & DSR_SORT_UNIQ;
3711 const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
3712 const int hex_digest_len = digests_are_256 ?
3713 HEX_DIGEST256_LEN : HEX_DIGEST_LEN;
3714 const int base64_digest_len = digests_are_256 ?
3715 BASE64_DIGEST256_LEN : BASE64_DIGEST_LEN;
3716 smartlist_t *fp_tmp = smartlist_new();
3718 tor_assert(!(decode_hex && decode_base64));
3719 tor_assert(fp_out);
3721 smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
3722 if (compressed_out)
3723 *compressed_out = 0;
3724 if (smartlist_len(fp_tmp)) {
3725 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3726 size_t last_len = strlen(last);
3727 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3728 last[last_len-2] = '\0';
3729 if (compressed_out)
3730 *compressed_out = 1;
3733 if (decode_hex || decode_base64) {
3734 const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
3735 int i;
3736 char *cp, *d = NULL;
3737 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3738 cp = smartlist_get(fp_tmp, i);
3739 if (strlen(cp) != encoded_len) {
3740 log_info(LD_DIR,
3741 "Skipping digest %s with non-standard length.", escaped(cp));
3742 smartlist_del_keeporder(fp_tmp, i--);
3743 goto again;
3745 d = tor_malloc_zero(digest_len);
3746 if (decode_hex ?
3747 (base16_decode(d, digest_len, cp, hex_digest_len)<0) :
3748 (base64_decode(d, digest_len, cp, base64_digest_len)<0)) {
3749 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3750 smartlist_del_keeporder(fp_tmp, i--);
3751 goto again;
3753 smartlist_set(fp_tmp, i, d);
3754 d = NULL;
3755 again:
3756 tor_free(cp);
3757 tor_free(d);
3760 if (sort_uniq) {
3761 if (decode_hex || decode_base64) {
3762 if (digests_are_256) {
3763 smartlist_sort_digests256(fp_tmp);
3764 smartlist_uniq_digests256(fp_tmp);
3765 } else {
3766 smartlist_sort_digests(fp_tmp);
3767 smartlist_uniq_digests(fp_tmp);
3769 } else {
3770 smartlist_sort_strings(fp_tmp);
3771 smartlist_uniq_strings(fp_tmp);
3774 smartlist_add_all(fp_out, fp_tmp);
3775 smartlist_free(fp_tmp);
3776 return 0;