In routerlist_assert_ok(), check r2 before taking &(r2->cache_info)
[tor.git] / src / or / directory.c
blob298271f3666f1661e34d072eda08936af8f5d522
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2013, 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 "rendclient.h"
24 #include "rendcommon.h"
25 #include "rephist.h"
26 #include "router.h"
27 #include "routerlist.h"
28 #include "routerparse.h"
29 #include "routerset.h"
31 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
32 #ifndef OPENBSD
33 #include <malloc.h>
34 #endif
35 #endif
37 /**
38 * \file directory.c
39 * \brief Code to send and fetch directories and router
40 * descriptors via HTTP. Directories use dirserv.c to generate the
41 * results; clients use routers.c to parse them.
42 **/
44 /* In-points to directory.c:
46 * - directory_post_to_dirservers(), called from
47 * router_upload_dir_desc_to_dirservers() in router.c
48 * upload_service_descriptor() in rendservice.c
49 * - directory_get_from_dirserver(), called from
50 * rend_client_refetch_renddesc() in rendclient.c
51 * run_scheduled_events() in main.c
52 * do_hup() in main.c
53 * - connection_dir_process_inbuf(), called from
54 * connection_process_inbuf() in connection.c
55 * - connection_dir_finished_flushing(), called from
56 * connection_finished_flushing() in connection.c
57 * - connection_dir_finished_connecting(), called from
58 * connection_finished_connecting() in connection.c
60 static void directory_send_command(dir_connection_t *conn,
61 int purpose, int direct, const char *resource,
62 const char *payload, size_t payload_len,
63 time_t if_modified_since);
64 static int directory_handle_command(dir_connection_t *conn);
65 static int body_is_plausible(const char *body, size_t body_len, int purpose);
66 static int purpose_needs_anonymity(uint8_t dir_purpose,
67 uint8_t router_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 true iff <b>identity_digest</b> is the digest of a router we
201 * believe to support extrainfo downloads. (If <b>is_authority</b> we do
202 * additional checking that's only valid for authorities.) */
204 router_supports_extrainfo(const char *identity_digest, int is_authority)
206 const node_t *node = node_get_by_id(identity_digest);
208 if (node && node->ri) {
209 if (node->ri->caches_extra_info)
210 return 1;
212 if (is_authority) {
213 return 1;
215 return 0;
218 /** Return true iff any trusted directory authority has accepted our
219 * server descriptor.
221 * We consider any authority sufficient because waiting for all of
222 * them means it never happens while any authority is down; we don't
223 * go for something more complex in the middle (like \>1/3 or \>1/2 or
224 * \>=1/2) because that doesn't seem necessary yet.
227 directories_have_accepted_server_descriptor(void)
229 const smartlist_t *servers = router_get_trusted_dir_servers();
230 const or_options_t *options = get_options();
231 SMARTLIST_FOREACH(servers, dir_server_t *, d, {
232 if ((d->type & options->PublishServerDescriptor_) &&
233 d->has_accepted_serverdesc) {
234 return 1;
237 return 0;
240 /** Start a connection to every suitable directory authority, using
241 * connection purpose <b>dir_purpose</b> and uploading <b>payload</b>
242 * (of length <b>payload_len</b>). The dir_purpose should be one of
243 * 'DIR_PURPOSE_UPLOAD_{DIR|VOTE|SIGNATURES}'.
245 * <b>router_purpose</b> describes the type of descriptor we're
246 * publishing, if we're publishing a descriptor -- e.g. general or bridge.
248 * <b>type</b> specifies what sort of dir authorities (V3,
249 * BRIDGE, etc) we should upload to.
251 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
252 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
253 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
254 * to all authorities, and the extra-info document to all authorities that
255 * support it.
257 void
258 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
259 dirinfo_type_t type,
260 const char *payload,
261 size_t payload_len, size_t extrainfo_len)
263 const or_options_t *options = get_options();
264 dir_indirection_t indirection;
265 const smartlist_t *dirservers = router_get_trusted_dir_servers();
266 int found = 0;
267 const int exclude_self = (dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
268 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES);
269 tor_assert(dirservers);
270 /* This tries dirservers which we believe to be down, but ultimately, that's
271 * harmless, and we may as well err on the side of getting things uploaded.
273 SMARTLIST_FOREACH_BEGIN(dirservers, dir_server_t *, ds) {
274 routerstatus_t *rs = &(ds->fake_status);
275 size_t upload_len = payload_len;
276 tor_addr_t ds_addr;
278 if ((type & ds->type) == 0)
279 continue;
281 if (exclude_self && router_digest_is_me(ds->digest)) {
282 /* we don't upload to ourselves, but at least there's now at least
283 * one authority of this type that has what we wanted to upload. */
284 found = 1;
285 continue;
288 if (options->StrictNodes &&
289 routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) {
290 log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
291 "it's in our ExcludedNodes list and StrictNodes is set. "
292 "Skipping.",
293 ds->nickname,
294 dir_conn_purpose_to_string(dir_purpose));
295 continue;
298 found = 1; /* at least one authority of this type was listed */
299 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
300 ds->has_accepted_serverdesc = 0;
302 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
303 upload_len += extrainfo_len;
304 log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
305 (int) extrainfo_len);
307 tor_addr_from_ipv4h(&ds_addr, ds->addr);
308 if (purpose_needs_anonymity(dir_purpose, router_purpose)) {
309 indirection = DIRIND_ANONYMOUS;
310 } else if (!fascist_firewall_allows_address_dir(&ds_addr,ds->dir_port)) {
311 if (fascist_firewall_allows_address_or(&ds_addr,ds->or_port))
312 indirection = DIRIND_ONEHOP;
313 else
314 indirection = DIRIND_ANONYMOUS;
315 } else {
316 indirection = DIRIND_DIRECT_CONN;
318 directory_initiate_command_routerstatus(rs, dir_purpose,
319 router_purpose,
320 indirection,
321 NULL, payload, upload_len, 0);
322 } SMARTLIST_FOREACH_END(ds);
323 if (!found) {
324 char *s = authdir_type_to_string(type);
325 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
326 "of type '%s', but no authorities of that type listed!", s);
327 tor_free(s);
331 /** Return true iff, according to the values in <b>options</b>, we should be
332 * using directory guards for direct downloads of directory information. */
333 static int
334 should_use_directory_guards(const or_options_t *options)
336 /* Public (non-bridge) servers never use directory guards. */
337 if (public_server_mode(options))
338 return 0;
339 /* If guards are disabled, or directory guards are disabled, we can't
340 * use directory guards.
342 if (!options->UseEntryGuards || !options->UseEntryGuardsAsDirGuards)
343 return 0;
344 /* If we're configured to fetch directory info aggressively or of a
345 * nonstandard type, don't use directory guards. */
346 if (options->DownloadExtraInfo || options->FetchDirInfoEarly ||
347 options->FetchDirInfoExtraEarly || options->FetchUselessDescriptors)
348 return 0;
349 return 1;
352 /** Pick an unconstrained directory server from among our guards, the latest
353 * networkstatus, or the fallback dirservers, for use in downloading
354 * information of type <b>type</b>, and return its routerstatus. */
355 static const routerstatus_t *
356 directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags,
357 uint8_t dir_purpose)
359 const routerstatus_t *rs = NULL;
360 const or_options_t *options = get_options();
362 if (options->UseBridges)
363 log_warn(LD_BUG, "Called when we have UseBridges set.");
365 if (should_use_directory_guards(options)) {
366 const node_t *node = choose_random_dirguard(type);
367 if (node)
368 rs = node->rs;
369 } else {
370 /* anybody with a non-zero dirport will do */
371 rs = router_pick_directory_server(type, pds_flags);
373 if (!rs) {
374 log_info(LD_DIR, "No router found for %s; falling back to "
375 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
376 rs = router_pick_fallback_dirserver(type, pds_flags);
379 return rs;
382 /** Start a connection to a random running directory server, using
383 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
384 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
385 * Use <b>pds_flags</b> as arguments to router_pick_directory_server()
386 * or router_pick_trusteddirserver().
388 void
389 directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
390 const char *resource, int pds_flags)
392 const routerstatus_t *rs = NULL;
393 const or_options_t *options = get_options();
394 int prefer_authority = directory_fetches_from_authorities(options);
395 int require_authority = 0;
396 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
397 dirinfo_type_t type;
398 time_t if_modified_since = 0;
400 /* FFFF we could break this switch into its own function, and call
401 * it elsewhere in directory.c. -RD */
402 switch (dir_purpose) {
403 case DIR_PURPOSE_FETCH_EXTRAINFO:
404 type = EXTRAINFO_DIRINFO |
405 (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
406 V3_DIRINFO);
407 break;
408 case DIR_PURPOSE_FETCH_SERVERDESC:
409 type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
410 V3_DIRINFO);
411 break;
412 case DIR_PURPOSE_FETCH_STATUS_VOTE:
413 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
414 case DIR_PURPOSE_FETCH_CERTIFICATE:
415 type = V3_DIRINFO;
416 break;
417 case DIR_PURPOSE_FETCH_CONSENSUS:
418 type = V3_DIRINFO;
419 if (resource && !strcmp(resource,"microdesc"))
420 type |= MICRODESC_DIRINFO;
421 break;
422 case DIR_PURPOSE_FETCH_MICRODESC:
423 type = MICRODESC_DIRINFO;
424 break;
425 default:
426 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
427 return;
430 if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
431 int flav = FLAV_NS;
432 networkstatus_t *v;
433 if (resource)
434 flav = networkstatus_parse_flavor_name(resource);
436 if (flav != -1) {
437 /* IF we have a parsed consensus of this type, we can do an
438 * if-modified-time based on it. */
439 v = networkstatus_get_latest_consensus_by_flavor(flav);
440 if (v)
441 if_modified_since = v->valid_after + 180;
442 } else {
443 /* Otherwise it might be a consensus we don't parse, but which we
444 * do cache. Look at the cached copy, perhaps. */
445 cached_dir_t *cd = dirserv_get_consensus(resource);
446 if (cd)
447 if_modified_since = cd->published + 180;
451 if (!options->FetchServerDescriptors)
452 return;
454 if (!get_via_tor) {
455 if (options->UseBridges && type != BRIDGE_DIRINFO) {
456 /* We want to ask a running bridge for which we have a descriptor.
458 * When we ask choose_random_entry() for a bridge, we specify what
459 * sort of dir fetch we'll be doing, so it won't return a bridge
460 * that can't answer our question.
462 /* XXX024 Not all bridges handle conditional consensus downloading,
463 * so, for now, never assume the server supports that. -PP */
464 const node_t *node = choose_random_dirguard(type);
465 if (node && node->ri) {
466 /* every bridge has a routerinfo. */
467 tor_addr_t addr;
468 routerinfo_t *ri = node->ri;
469 node_get_addr(node, &addr);
470 directory_initiate_command(&addr,
471 ri->or_port, 0/*no dirport*/,
472 ri->cache_info.identity_digest,
473 dir_purpose,
474 router_purpose,
475 DIRIND_ONEHOP,
476 resource, NULL, 0, if_modified_since);
477 } else
478 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
479 "nodes are available yet.");
480 return;
481 } else {
482 if (prefer_authority || type == BRIDGE_DIRINFO) {
483 /* only ask authdirservers, and don't ask myself */
484 rs = router_pick_trusteddirserver(type, pds_flags);
485 if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
486 PDS_NO_EXISTING_MICRODESC_FETCH))) {
487 /* We don't want to fetch from any authorities that we're currently
488 * fetching server descriptors from, and we got no match. Did we
489 * get no match because all the authorities have connections
490 * fetching server descriptors (in which case we should just
491 * return,) or because all the authorities are down or on fire or
492 * unreachable or something (in which case we should go on with
493 * our fallback code)? */
494 pds_flags &= ~(PDS_NO_EXISTING_SERVERDESC_FETCH|
495 PDS_NO_EXISTING_MICRODESC_FETCH);
496 rs = router_pick_trusteddirserver(type, pds_flags);
497 if (rs) {
498 log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
499 "are in use.");
500 return;
503 if (rs == NULL && require_authority) {
504 log_info(LD_DIR, "No authorities were available for %s: will try "
505 "later.", dir_conn_purpose_to_string(dir_purpose));
506 return;
509 if (!rs && type != BRIDGE_DIRINFO) {
510 /* */
511 rs = directory_pick_generic_dirserver(type, pds_flags,
512 dir_purpose);
513 if (!rs) {
514 /*XXXX024 I'm pretty sure this can never do any good, since
515 * rs isn't set. */
516 get_via_tor = 1; /* last resort: try routing it via Tor */
520 } else { /* get_via_tor */
521 /* Never use fascistfirewall; we're going via Tor. */
522 if (1) {
523 /* anybody with a non-zero dirport will do. Disregard firewalls. */
524 pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
525 rs = router_pick_directory_server(type, pds_flags);
526 /* If we have any hope of building an indirect conn, we know some router
527 * descriptors. If (rs==NULL), we can't build circuits anyway, so
528 * there's no point in falling back to the authorities in this case. */
532 if (rs) {
533 const dir_indirection_t indirection =
534 get_via_tor ? DIRIND_ANONYMOUS : DIRIND_ONEHOP;
535 directory_initiate_command_routerstatus(rs, dir_purpose,
536 router_purpose,
537 indirection,
538 resource, NULL, 0,
539 if_modified_since);
540 } else {
541 log_notice(LD_DIR,
542 "While fetching directory info, "
543 "no running dirservers known. Will try again later. "
544 "(purpose %d)", dir_purpose);
545 if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
546 /* remember we tried them all and failed. */
547 directory_all_unreachable(time(NULL));
552 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
553 * directory authority other than ourself. Only for use by authorities when
554 * searching for missing information while voting. */
555 void
556 directory_get_from_all_authorities(uint8_t dir_purpose,
557 uint8_t router_purpose,
558 const char *resource)
560 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
561 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
563 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
564 dir_server_t *, ds) {
565 routerstatus_t *rs;
566 if (router_digest_is_me(ds->digest))
567 continue;
568 if (!(ds->type & V3_DIRINFO))
569 continue;
570 rs = &ds->fake_status;
571 directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
572 DIRIND_ONEHOP, resource, NULL,
573 0, 0);
574 } SMARTLIST_FOREACH_END(ds);
577 /** Return true iff <b>ind</b> requires a multihop circuit. */
578 static int
579 dirind_is_anon(dir_indirection_t ind)
581 return ind == DIRIND_ANON_DIRPORT || ind == DIRIND_ANONYMOUS;
584 /** Same as directory_initiate_command_routerstatus(), but accepts
585 * rendezvous data to fetch a hidden service descriptor. */
586 void
587 directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
588 uint8_t dir_purpose,
589 uint8_t router_purpose,
590 dir_indirection_t indirection,
591 const char *resource,
592 const char *payload,
593 size_t payload_len,
594 time_t if_modified_since,
595 const rend_data_t *rend_query)
597 const or_options_t *options = get_options();
598 const node_t *node;
599 tor_addr_t addr;
600 const int anonymized_connection = dirind_is_anon(indirection);
601 node = node_get_by_id(status->identity_digest);
603 if (!node && anonymized_connection) {
604 log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
605 "don't have its router descriptor.",
606 routerstatus_describe(status));
607 return;
609 tor_addr_from_ipv4h(&addr, status->addr);
611 if (options->ExcludeNodes && options->StrictNodes &&
612 routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
613 log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
614 "it's in our ExcludedNodes list and StrictNodes is set. "
615 "Skipping. This choice might make your Tor not work.",
616 routerstatus_describe(status),
617 dir_conn_purpose_to_string(dir_purpose));
618 return;
621 directory_initiate_command_rend(&addr,
622 status->or_port, status->dir_port,
623 status->identity_digest,
624 dir_purpose, router_purpose,
625 indirection, resource,
626 payload, payload_len, if_modified_since,
627 rend_query);
630 /** Launch a new connection to the directory server <b>status</b> to
631 * upload or download a server or rendezvous
632 * descriptor. <b>dir_purpose</b> determines what
633 * kind of directory connection we're launching, and must be one of
634 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC_V2}. <b>router_purpose</b>
635 * specifies the descriptor purposes we have in mind (currently only
636 * used for FETCH_DIR).
638 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
639 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
641 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
642 * want to fetch.
644 void
645 directory_initiate_command_routerstatus(const routerstatus_t *status,
646 uint8_t dir_purpose,
647 uint8_t router_purpose,
648 dir_indirection_t indirection,
649 const char *resource,
650 const char *payload,
651 size_t payload_len,
652 time_t if_modified_since)
654 directory_initiate_command_routerstatus_rend(status, dir_purpose,
655 router_purpose,
656 indirection, resource,
657 payload, payload_len,
658 if_modified_since, NULL);
661 /** Return true iff <b>conn</b> is the client side of a directory connection
662 * we launched to ourself in order to determine the reachability of our
663 * dir_port. */
664 static int
665 directory_conn_is_self_reachability_test(dir_connection_t *conn)
667 if (conn->requested_resource &&
668 !strcmpstart(conn->requested_resource,"authority")) {
669 const routerinfo_t *me = router_get_my_routerinfo();
670 if (me &&
671 router_digest_is_me(conn->identity_digest) &&
672 tor_addr_eq_ipv4h(&conn->base_.addr, me->addr) && /*XXXX prop 118*/
673 me->dir_port == conn->base_.port)
674 return 1;
676 return 0;
679 /** Called when we are unable to complete the client's request to a directory
680 * server due to a network error: Mark the router as down and try again if
681 * possible.
683 static void
684 connection_dir_request_failed(dir_connection_t *conn)
686 if (directory_conn_is_self_reachability_test(conn)) {
687 return; /* this was a test fetch. don't retry. */
689 if (!entry_list_is_constrained(get_options()))
690 router_set_status(conn->identity_digest, 0); /* don't try him again */
691 if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
692 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
693 log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
694 "directory server at '%s'; retrying",
695 conn->base_.address);
696 if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
697 connection_dir_bridge_routerdesc_failed(conn);
698 connection_dir_download_routerdesc_failed(conn);
699 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
700 if (conn->requested_resource)
701 networkstatus_consensus_download_failed(0, conn->requested_resource);
702 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
703 log_info(LD_DIR, "Giving up on certificate fetch from directory server "
704 "at '%s'; retrying",
705 conn->base_.address);
706 connection_dir_download_cert_failed(conn, 0);
707 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
708 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
709 conn->base_.address);
710 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
711 log_info(LD_DIR, "Giving up downloading votes from '%s'",
712 conn->base_.address);
713 } else if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
714 log_info(LD_DIR, "Giving up on downloading microdescriptors from "
715 "directory server at '%s'; will retry", conn->base_.address);
716 connection_dir_download_routerdesc_failed(conn);
720 /** Helper: Attempt to fetch directly the descriptors of each bridge
721 * listed in <b>failed</b>.
723 static void
724 connection_dir_retry_bridges(smartlist_t *descs)
726 char digest[DIGEST_LEN];
727 SMARTLIST_FOREACH(descs, const char *, cp,
729 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
730 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
731 escaped(cp));
732 continue;
734 retry_bridge_descriptor_fetch_directly(digest);
738 /** Called when an attempt to download one or more router descriptors
739 * or extra-info documents on connection <b>conn</b> failed.
741 static void
742 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
744 /* No need to increment the failure count for routerdescs, since
745 * it's not their fault. */
747 /* No need to relaunch descriptor downloads here: we already do it
748 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
749 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
750 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
751 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
753 (void) conn;
756 /** Called when an attempt to download a bridge's routerdesc from
757 * one of the authorities failed due to a network error. If
758 * possible attempt to download descriptors from the bridge directly.
760 static void
761 connection_dir_bridge_routerdesc_failed(dir_connection_t *conn)
763 smartlist_t *which = NULL;
765 /* Requests for bridge descriptors are in the form 'fp/', so ignore
766 anything else. */
767 if (!conn->requested_resource || strcmpstart(conn->requested_resource,"fp/"))
768 return;
770 which = smartlist_new();
771 dir_split_resource_into_fingerprints(conn->requested_resource
772 + strlen("fp/"),
773 which, NULL, 0);
775 tor_assert(conn->base_.purpose != DIR_PURPOSE_FETCH_EXTRAINFO);
776 if (smartlist_len(which)) {
777 connection_dir_retry_bridges(which);
778 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
780 smartlist_free(which);
783 /** Called when an attempt to fetch a certificate fails. */
784 static void
785 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
787 const char *fp_pfx = "fp/";
788 const char *fpsk_pfx = "fp-sk/";
789 smartlist_t *failed;
790 tor_assert(conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
792 if (!conn->requested_resource)
793 return;
794 failed = smartlist_new();
796 * We have two cases download by fingerprint (resource starts
797 * with "fp/") or download by fingerprint/signing key pair
798 * (resource starts with "fp-sk/").
800 if (!strcmpstart(conn->requested_resource, fp_pfx)) {
801 /* Download by fingerprint case */
802 dir_split_resource_into_fingerprints(conn->requested_resource +
803 strlen(fp_pfx),
804 failed, NULL, DSR_HEX);
805 SMARTLIST_FOREACH_BEGIN(failed, char *, cp) {
806 /* Null signing key digest indicates download by fp only */
807 authority_cert_dl_failed(cp, NULL, status);
808 tor_free(cp);
809 } SMARTLIST_FOREACH_END(cp);
810 } else if (!strcmpstart(conn->requested_resource, fpsk_pfx)) {
811 /* Download by (fp,sk) pairs */
812 dir_split_resource_into_fingerprint_pairs(conn->requested_resource +
813 strlen(fpsk_pfx), failed);
814 SMARTLIST_FOREACH_BEGIN(failed, fp_pair_t *, cp) {
815 authority_cert_dl_failed(cp->first, cp->second, status);
816 tor_free(cp);
817 } SMARTLIST_FOREACH_END(cp);
818 } else {
819 log_warn(LD_DIR,
820 "Don't know what to do with failure for cert fetch %s",
821 conn->requested_resource);
824 smartlist_free(failed);
826 update_certificate_downloads(time(NULL));
829 /** Evaluate the situation and decide if we should use an encrypted
830 * "begindir-style" connection for this directory request.
831 * 1) If or_port is 0, or it's a direct conn and or_port is firewalled
832 * or we're a dir mirror, no.
833 * 2) If we prefer to avoid begindir conns, and we're not fetching or
834 * publishing a bridge relay descriptor, no.
835 * 3) Else yes.
837 static int
838 directory_command_should_use_begindir(const or_options_t *options,
839 const tor_addr_t *addr,
840 int or_port, uint8_t router_purpose,
841 dir_indirection_t indirection)
843 (void) router_purpose;
844 if (!or_port)
845 return 0; /* We don't know an ORPort -- no chance. */
846 if (indirection == DIRIND_DIRECT_CONN || indirection == DIRIND_ANON_DIRPORT)
847 return 0;
848 if (indirection == DIRIND_ONEHOP)
849 if (!fascist_firewall_allows_address_or(addr, or_port) ||
850 directory_fetches_from_authorities(options))
851 return 0; /* We're firewalled or are acting like a relay -- also no. */
852 return 1;
855 /** Helper for directory_initiate_command_routerstatus: send the
856 * command to a server whose address is <b>address</b>, whose IP is
857 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
858 * <b>supports_begindir</b>, and whose identity key digest is
859 * <b>digest</b>. */
860 void
861 directory_initiate_command(const tor_addr_t *_addr,
862 uint16_t or_port, uint16_t dir_port,
863 const char *digest,
864 uint8_t dir_purpose, uint8_t router_purpose,
865 dir_indirection_t indirection, const char *resource,
866 const char *payload, size_t payload_len,
867 time_t if_modified_since)
869 directory_initiate_command_rend(_addr, or_port, dir_port,
870 digest, dir_purpose,
871 router_purpose, indirection,
872 resource, payload, payload_len,
873 if_modified_since, NULL);
876 /** Return non-zero iff a directory connection with purpose
877 * <b>dir_purpose</b> reveals sensitive information about a Tor
878 * instance's client activities. (Such connections must be performed
879 * through normal three-hop Tor circuits.) */
880 static int
881 is_sensitive_dir_purpose(uint8_t dir_purpose)
883 return ((dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2) ||
884 (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
885 (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
888 /** Same as directory_initiate_command(), but accepts rendezvous data to
889 * fetch a hidden service descriptor. */
890 static void
891 directory_initiate_command_rend(const tor_addr_t *_addr,
892 uint16_t or_port, uint16_t dir_port,
893 const char *digest,
894 uint8_t dir_purpose, uint8_t router_purpose,
895 dir_indirection_t indirection,
896 const char *resource,
897 const char *payload, size_t payload_len,
898 time_t if_modified_since,
899 const rend_data_t *rend_query)
901 dir_connection_t *conn;
902 const or_options_t *options = get_options();
903 int socket_error = 0;
904 int use_begindir = directory_command_should_use_begindir(options, _addr,
905 or_port, router_purpose, indirection);
906 const int anonymized_connection = dirind_is_anon(indirection);
907 tor_addr_t addr;
909 tor_assert(_addr);
910 tor_assert(or_port || dir_port);
911 tor_assert(digest);
913 tor_addr_copy(&addr, _addr);
915 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
916 anonymized_connection, use_begindir);
918 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
920 #ifndef NON_ANONYMOUS_MODE_ENABLED
921 tor_assert(!(is_sensitive_dir_purpose(dir_purpose) &&
922 !anonymized_connection));
923 #else
924 (void)is_sensitive_dir_purpose;
925 #endif
927 /* ensure that we don't make direct connections when a SOCKS server is
928 * configured. */
929 if (!anonymized_connection && !use_begindir && !options->HTTPProxy &&
930 (options->Socks4Proxy || options->Socks5Proxy)) {
931 log_warn(LD_DIR, "Cannot connect to a directory server through a "
932 "SOCKS proxy!");
933 return;
936 conn = dir_connection_new(tor_addr_family(&addr));
938 /* set up conn so it's got all the data we need to remember */
939 tor_addr_copy(&conn->base_.addr, &addr);
940 conn->base_.port = use_begindir ? or_port : dir_port;
941 conn->base_.address = tor_dup_addr(&addr);
942 memcpy(conn->identity_digest, digest, DIGEST_LEN);
944 conn->base_.purpose = dir_purpose;
945 conn->router_purpose = router_purpose;
947 /* give it an initial state */
948 conn->base_.state = DIR_CONN_STATE_CONNECTING;
950 /* decide whether we can learn our IP address from this conn */
951 /* XXXX This is a bad name for this field now. */
952 conn->dirconn_direct = !anonymized_connection;
954 /* copy rendezvous data, if any */
955 if (rend_query)
956 conn->rend_data = rend_data_dup(rend_query);
958 if (!anonymized_connection && !use_begindir) {
959 /* then we want to connect to dirport directly */
961 if (options->HTTPProxy) {
962 tor_addr_copy(&addr, &options->HTTPProxyAddr);
963 dir_port = options->HTTPProxyPort;
966 switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr,
967 dir_port, &socket_error)) {
968 case -1:
969 connection_dir_request_failed(conn); /* retry if we want */
970 /* XXX we only pass 'conn' above, not 'resource', 'payload',
971 * etc. So in many situations it can't retry! -RD */
972 connection_free(TO_CONN(conn));
973 return;
974 case 1:
975 /* start flushing conn */
976 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
977 /* fall through */
978 case 0:
979 /* queue the command on the outbuf */
980 directory_send_command(conn, dir_purpose, 1, resource,
981 payload, payload_len,
982 if_modified_since);
983 connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT);
984 /* writable indicates finish, readable indicates broken link,
985 error indicates broken link in windowsland. */
987 } else { /* we want to connect via a tor connection */
988 entry_connection_t *linked_conn;
989 /* Anonymized tunneled connections can never share a circuit.
990 * One-hop directory connections can share circuits with each other
991 * but nothing else. */
992 int iso_flags = anonymized_connection ? ISO_STREAM : ISO_SESSIONGRP;
994 /* If it's an anonymized connection, remember the fact that we
995 * wanted it for later: maybe we'll want it again soon. */
996 if (anonymized_connection && use_begindir)
997 rep_hist_note_used_internal(time(NULL), 0, 1);
998 else if (anonymized_connection && !use_begindir)
999 rep_hist_note_used_port(time(NULL), conn->base_.port);
1001 /* make an AP connection
1002 * populate it and add it at the right state
1003 * hook up both sides
1005 linked_conn =
1006 connection_ap_make_link(TO_CONN(conn),
1007 conn->base_.address, conn->base_.port,
1008 digest,
1009 SESSION_GROUP_DIRCONN, iso_flags,
1010 use_begindir, conn->dirconn_direct);
1011 if (!linked_conn) {
1012 log_warn(LD_NET,"Making tunnel to dirserver failed.");
1013 connection_mark_for_close(TO_CONN(conn));
1014 return;
1017 if (connection_add(TO_CONN(conn)) < 0) {
1018 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
1019 connection_mark_for_close(TO_CONN(conn));
1020 return;
1022 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING;
1023 /* queue the command on the outbuf */
1024 directory_send_command(conn, dir_purpose, 0, resource,
1025 payload, payload_len,
1026 if_modified_since);
1028 connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
1029 IF_HAS_BUFFEREVENT(ENTRY_TO_CONN(linked_conn), {
1030 connection_watch_events(ENTRY_TO_CONN(linked_conn),
1031 READ_EVENT|WRITE_EVENT);
1032 }) ELSE_IF_NO_BUFFEREVENT
1033 connection_start_reading(ENTRY_TO_CONN(linked_conn));
1037 /** Return true iff anything we say on <b>conn</b> is being encrypted before
1038 * we send it to the client/server. */
1040 connection_dir_is_encrypted(dir_connection_t *conn)
1042 /* Right now it's sufficient to see if conn is or has been linked, since
1043 * the only thing it could be linked to is an edge connection on a
1044 * circuit, and the only way it could have been unlinked is at the edge
1045 * connection getting closed.
1047 return TO_CONN(conn)->linked;
1050 /** Helper for sorting
1052 * sort strings alphabetically
1054 static int
1055 compare_strs_(const void **a, const void **b)
1057 const char *s1 = *a, *s2 = *b;
1058 return strcmp(s1, s2);
1061 #define CONDITIONAL_CONSENSUS_FPR_LEN 3
1062 #if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
1063 #error "conditional consensus fingerprint length is larger than digest length"
1064 #endif
1066 /** Return the URL we should use for a consensus download.
1068 * This url depends on whether or not the server we go to
1069 * is sufficiently new to support conditional consensus downloading,
1070 * i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
1072 * If 'resource' is provided, it is the name of a consensus flavor to request.
1074 static char *
1075 directory_get_consensus_url(const char *resource)
1077 char *url = NULL;
1078 const char *hyphen, *flavor;
1079 if (resource==NULL || strcmp(resource, "ns")==0) {
1080 flavor = ""; /* Request ns consensuses as "", so older servers will work*/
1081 hyphen = "";
1082 } else {
1083 flavor = resource;
1084 hyphen = "-";
1088 char *authority_id_list;
1089 smartlist_t *authority_digests = smartlist_new();
1091 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
1092 dir_server_t *, ds) {
1093 char *hex;
1094 if (!(ds->type & V3_DIRINFO))
1095 continue;
1097 hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
1098 base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
1099 ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN);
1100 smartlist_add(authority_digests, hex);
1101 } SMARTLIST_FOREACH_END(ds);
1102 smartlist_sort(authority_digests, compare_strs_);
1103 authority_id_list = smartlist_join_strings(authority_digests,
1104 "+", 0, NULL);
1106 tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s/%s.z",
1107 hyphen, flavor, authority_id_list);
1109 SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
1110 smartlist_free(authority_digests);
1111 tor_free(authority_id_list);
1113 return url;
1116 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
1117 * are as in directory_initiate_command().
1119 static void
1120 directory_send_command(dir_connection_t *conn,
1121 int purpose, int direct, const char *resource,
1122 const char *payload, size_t payload_len,
1123 time_t if_modified_since)
1125 char proxystring[256];
1126 char hoststring[128];
1127 smartlist_t *headers = smartlist_new();
1128 char *url;
1129 char request[8192];
1130 const char *httpcommand = NULL;
1132 tor_assert(conn);
1133 tor_assert(conn->base_.type == CONN_TYPE_DIR);
1135 tor_free(conn->requested_resource);
1136 if (resource)
1137 conn->requested_resource = tor_strdup(resource);
1139 /* come up with a string for which Host: we want */
1140 if (conn->base_.port == 80) {
1141 strlcpy(hoststring, conn->base_.address, sizeof(hoststring));
1142 } else {
1143 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
1144 conn->base_.address, conn->base_.port);
1147 /* Format if-modified-since */
1148 if (if_modified_since) {
1149 char b[RFC1123_TIME_LEN+1];
1150 format_rfc1123_time(b, if_modified_since);
1151 smartlist_add_asprintf(headers, "If-Modified-Since: %s\r\n", b);
1154 /* come up with some proxy lines, if we're using one. */
1155 if (direct && get_options()->HTTPProxy) {
1156 char *base64_authenticator=NULL;
1157 const char *authenticator = get_options()->HTTPProxyAuthenticator;
1159 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
1160 if (authenticator) {
1161 base64_authenticator = alloc_http_authenticator(authenticator);
1162 if (!base64_authenticator)
1163 log_warn(LD_BUG, "Encoding http authenticator failed");
1165 if (base64_authenticator) {
1166 smartlist_add_asprintf(headers,
1167 "Proxy-Authorization: Basic %s\r\n",
1168 base64_authenticator);
1169 tor_free(base64_authenticator);
1171 } else {
1172 proxystring[0] = 0;
1175 switch (purpose) {
1176 case DIR_PURPOSE_FETCH_CONSENSUS:
1177 /* resource is optional. If present, it's a flavor name */
1178 tor_assert(!payload);
1179 httpcommand = "GET";
1180 url = directory_get_consensus_url(resource);
1181 log_info(LD_DIR, "Downloading consensus from %s using %s",
1182 hoststring, url);
1183 break;
1184 case DIR_PURPOSE_FETCH_CERTIFICATE:
1185 tor_assert(resource);
1186 tor_assert(!payload);
1187 httpcommand = "GET";
1188 tor_asprintf(&url, "/tor/keys/%s", resource);
1189 break;
1190 case DIR_PURPOSE_FETCH_STATUS_VOTE:
1191 tor_assert(resource);
1192 tor_assert(!payload);
1193 httpcommand = "GET";
1194 tor_asprintf(&url, "/tor/status-vote/next/%s.z", resource);
1195 break;
1196 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
1197 tor_assert(!resource);
1198 tor_assert(!payload);
1199 httpcommand = "GET";
1200 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
1201 break;
1202 case DIR_PURPOSE_FETCH_SERVERDESC:
1203 tor_assert(resource);
1204 httpcommand = "GET";
1205 tor_asprintf(&url, "/tor/server/%s", resource);
1206 break;
1207 case DIR_PURPOSE_FETCH_EXTRAINFO:
1208 tor_assert(resource);
1209 httpcommand = "GET";
1210 tor_asprintf(&url, "/tor/extra/%s", resource);
1211 break;
1212 case DIR_PURPOSE_FETCH_MICRODESC:
1213 tor_assert(resource);
1214 httpcommand = "GET";
1215 tor_asprintf(&url, "/tor/micro/%s", resource);
1216 break;
1217 case DIR_PURPOSE_UPLOAD_DIR: {
1218 const char *why = router_get_descriptor_gen_reason();
1219 tor_assert(!resource);
1220 tor_assert(payload);
1221 httpcommand = "POST";
1222 url = tor_strdup("/tor/");
1223 if (why) {
1224 smartlist_add_asprintf(headers, "X-Desc-Gen-Reason: %s\r\n", why);
1226 break;
1228 case DIR_PURPOSE_UPLOAD_VOTE:
1229 tor_assert(!resource);
1230 tor_assert(payload);
1231 httpcommand = "POST";
1232 url = tor_strdup("/tor/post/vote");
1233 break;
1234 case DIR_PURPOSE_UPLOAD_SIGNATURES:
1235 tor_assert(!resource);
1236 tor_assert(payload);
1237 httpcommand = "POST";
1238 url = tor_strdup("/tor/post/consensus-signature");
1239 break;
1240 case DIR_PURPOSE_FETCH_RENDDESC_V2:
1241 tor_assert(resource);
1242 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
1243 tor_assert(!payload);
1244 httpcommand = "GET";
1245 tor_asprintf(&url, "/tor/rendezvous2/%s", resource);
1246 break;
1247 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
1248 tor_assert(!resource);
1249 tor_assert(payload);
1250 httpcommand = "POST";
1251 url = tor_strdup("/tor/rendezvous2/publish");
1252 break;
1253 default:
1254 tor_assert(0);
1255 return;
1258 if (strlen(proxystring) + strlen(url) >= 4096) {
1259 log_warn(LD_BUG,
1260 "Squid does not like URLs longer than 4095 bytes, and this "
1261 "one is %d bytes long: %s%s",
1262 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
1265 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
1266 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1267 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
1268 tor_free(url);
1270 if (!strcmp(httpcommand, "POST") || payload) {
1271 smartlist_add_asprintf(headers, "Content-Length: %lu\r\n",
1272 payload ? (unsigned long)payload_len : 0);
1276 char *header = smartlist_join_strings(headers, "", 0, NULL);
1277 tor_snprintf(request, sizeof(request), " HTTP/1.0\r\nHost: %s\r\n%s\r\n",
1278 hoststring, header);
1279 tor_free(header);
1282 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1284 if (payload) {
1285 /* then send the payload afterwards too */
1286 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
1289 SMARTLIST_FOREACH(headers, char *, h, tor_free(h));
1290 smartlist_free(headers);
1293 /** Parse an HTTP request string <b>headers</b> of the form
1294 * \verbatim
1295 * "\%s [http[s]://]\%s HTTP/1..."
1296 * \endverbatim
1297 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
1298 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
1299 * so it does. Return 0.
1300 * Otherwise, return -1.
1302 STATIC int
1303 parse_http_url(const char *headers, char **url)
1305 char *s, *start, *tmp;
1307 s = (char *)eat_whitespace_no_nl(headers);
1308 if (!*s) return -1;
1309 s = (char *)find_whitespace(s); /* get past GET/POST */
1310 if (!*s) return -1;
1311 s = (char *)eat_whitespace_no_nl(s);
1312 if (!*s) return -1;
1313 start = s; /* this is it, assuming it's valid */
1314 s = (char *)find_whitespace(start);
1315 if (!*s) return -1;
1317 /* tolerate the http[s] proxy style of putting the hostname in the url */
1318 if (s-start >= 4 && !strcmpstart(start,"http")) {
1319 tmp = start + 4;
1320 if (*tmp == 's')
1321 tmp++;
1322 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
1323 tmp = strchr(tmp+3, '/');
1324 if (tmp && tmp < s) {
1325 log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
1326 start = tmp;
1331 /* Check if the header is well formed (next sequence
1332 * should be HTTP/1.X\r\n). Assumes we're supporting 1.0? */
1334 unsigned minor_ver;
1335 char ch;
1336 char *e = (char *)eat_whitespace_no_nl(s);
1337 if (2 != tor_sscanf(e, "HTTP/1.%u%c", &minor_ver, &ch)) {
1338 return -1;
1340 if (ch != '\r')
1341 return -1;
1344 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
1345 *url = tor_malloc(s - start + 5);
1346 strlcpy(*url,"/tor", s-start+5);
1347 strlcat((*url)+4, start, s-start+1);
1348 } else {
1349 *url = tor_strndup(start, s-start);
1351 return 0;
1354 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1355 * <b>which</b>. The key should be given with a terminating colon and space;
1356 * this function copies everything after, up to but not including the
1357 * following \\r\\n. */
1358 static char *
1359 http_get_header(const char *headers, const char *which)
1361 const char *cp = headers;
1362 while (cp) {
1363 if (!strcasecmpstart(cp, which)) {
1364 char *eos;
1365 cp += strlen(which);
1366 if ((eos = strchr(cp,'\r')))
1367 return tor_strndup(cp, eos-cp);
1368 else
1369 return tor_strdup(cp);
1371 cp = strchr(cp, '\n');
1372 if (cp)
1373 ++cp;
1375 return NULL;
1378 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1379 * <b>conn</b>-\>address to describe our best guess of the address that
1380 * originated this HTTP request. */
1381 static void
1382 http_set_address_origin(const char *headers, connection_t *conn)
1384 char *fwd;
1386 fwd = http_get_header(headers, "Forwarded-For: ");
1387 if (!fwd)
1388 fwd = http_get_header(headers, "X-Forwarded-For: ");
1389 if (fwd) {
1390 tor_addr_t toraddr;
1391 if (tor_addr_parse(&toraddr,fwd) == -1 ||
1392 tor_addr_is_internal(&toraddr,0)) {
1393 log_debug(LD_DIR, "Ignoring local/internal IP %s", escaped(fwd));
1394 tor_free(fwd);
1395 return;
1398 tor_free(conn->address);
1399 conn->address = tor_strdup(fwd);
1400 tor_free(fwd);
1404 /** Parse an HTTP response string <b>headers</b> of the form
1405 * \verbatim
1406 * "HTTP/1.\%d \%d\%s\r\n...".
1407 * \endverbatim
1409 * If it's well-formed, assign the status code to *<b>code</b> and
1410 * return 0. Otherwise, return -1.
1412 * On success: If <b>date</b> is provided, set *date to the Date
1413 * header in the http headers, or 0 if no such header is found. If
1414 * <b>compression</b> is provided, set *<b>compression</b> to the
1415 * compression method given in the Content-Encoding header, or 0 if no
1416 * such header is found, or -1 if the value of the header is not
1417 * recognized. If <b>reason</b> is provided, strdup the reason string
1418 * into it.
1421 parse_http_response(const char *headers, int *code, time_t *date,
1422 compress_method_t *compression, char **reason)
1424 unsigned n1, n2;
1425 char datestr[RFC1123_TIME_LEN+1];
1426 smartlist_t *parsed_headers;
1427 tor_assert(headers);
1428 tor_assert(code);
1430 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1432 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
1433 (n1 != 0 && n1 != 1) ||
1434 (n2 < 100 || n2 >= 600)) {
1435 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1436 return -1;
1438 *code = n2;
1440 parsed_headers = smartlist_new();
1441 smartlist_split_string(parsed_headers, headers, "\n",
1442 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1443 if (reason) {
1444 smartlist_t *status_line_elements = smartlist_new();
1445 tor_assert(smartlist_len(parsed_headers));
1446 smartlist_split_string(status_line_elements,
1447 smartlist_get(parsed_headers, 0),
1448 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1449 tor_assert(smartlist_len(status_line_elements) <= 3);
1450 if (smartlist_len(status_line_elements) == 3) {
1451 *reason = smartlist_get(status_line_elements, 2);
1452 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1454 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1455 smartlist_free(status_line_elements);
1457 if (date) {
1458 *date = 0;
1459 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1460 if (!strcmpstart(s, "Date: ")) {
1461 strlcpy(datestr, s+6, sizeof(datestr));
1462 /* This will do nothing on failure, so we don't need to check
1463 the result. We shouldn't warn, since there are many other valid
1464 date formats besides the one we use. */
1465 parse_rfc1123_time(datestr, date);
1466 break;
1469 if (compression) {
1470 const char *enc = NULL;
1471 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1472 if (!strcmpstart(s, "Content-Encoding: ")) {
1473 enc = s+18; break;
1475 if (!enc || !strcmp(enc, "identity")) {
1476 *compression = NO_METHOD;
1477 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1478 *compression = ZLIB_METHOD;
1479 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1480 *compression = GZIP_METHOD;
1481 } else {
1482 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1483 escaped(enc));
1484 *compression = UNKNOWN_METHOD;
1487 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1488 smartlist_free(parsed_headers);
1490 return 0;
1493 /** Return true iff <b>body</b> doesn't start with a plausible router or
1494 * network-status or microdescriptor opening. This is a sign of possible
1495 * compression. */
1496 static int
1497 body_is_plausible(const char *body, size_t len, int purpose)
1499 int i;
1500 if (len == 0)
1501 return 1; /* empty bodies don't need decompression */
1502 if (len < 32)
1503 return 0;
1504 if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
1505 return (!strcmpstart(body,"onion-key"));
1507 if (1) {
1508 if (!strcmpstart(body,"router") ||
1509 !strcmpstart(body,"network-status"))
1510 return 1;
1511 for (i=0;i<32;++i) {
1512 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1513 return 0;
1516 return 1;
1519 /** Called when we've just fetched a bunch of router descriptors in
1520 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1521 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1522 * is true, or identity digests otherwise. Parse the descriptors, validate
1523 * them, and annotate them as having purpose <b>purpose</b> and as having been
1524 * downloaded from <b>source</b>.
1526 * Return the number of routers actually added. */
1527 static int
1528 load_downloaded_routers(const char *body, smartlist_t *which,
1529 int descriptor_digests,
1530 int router_purpose,
1531 const char *source)
1533 char buf[256];
1534 char time_buf[ISO_TIME_LEN+1];
1535 int added = 0;
1536 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1537 format_iso_time(time_buf, time(NULL));
1538 tor_assert(source);
1540 if (tor_snprintf(buf, sizeof(buf),
1541 "@downloaded-at %s\n"
1542 "@source %s\n"
1543 "%s%s%s", time_buf, escaped(source),
1544 !general ? "@purpose " : "",
1545 !general ? router_purpose_to_string(router_purpose) : "",
1546 !general ? "\n" : "")<0)
1547 return added;
1549 added = router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1550 descriptor_digests, buf);
1551 if (general)
1552 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
1553 count_loading_descriptors_progress());
1554 return added;
1557 /** We are a client, and we've finished reading the server's
1558 * response. Parse it and act appropriately.
1560 * If we're still happy with using this directory server in the future, return
1561 * 0. Otherwise return -1; and the caller should consider trying the request
1562 * again.
1564 * The caller will take care of marking the connection for close.
1566 static int
1567 connection_dir_client_reached_eof(dir_connection_t *conn)
1569 char *body;
1570 char *headers;
1571 char *reason = NULL;
1572 size_t body_len = 0, orig_len = 0;
1573 int status_code;
1574 time_t date_header = 0;
1575 long delta;
1576 compress_method_t compression;
1577 int plausible;
1578 int skewed = 0;
1579 int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1580 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
1581 conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
1582 int was_compressed = 0;
1583 time_t now = time(NULL);
1584 int src_code;
1586 switch (connection_fetch_from_buf_http(TO_CONN(conn),
1587 &headers, MAX_HEADERS_SIZE,
1588 &body, &body_len, MAX_DIR_DL_SIZE,
1589 allow_partial)) {
1590 case -1: /* overflow */
1591 log_warn(LD_PROTOCOL,
1592 "'fetch' response too large (server '%s:%d'). Closing.",
1593 conn->base_.address, conn->base_.port);
1594 return -1;
1595 case 0:
1596 log_info(LD_HTTP,
1597 "'fetch' response not all here, but we're at eof. Closing.");
1598 return -1;
1599 /* case 1, fall through */
1601 orig_len = body_len;
1603 if (parse_http_response(headers, &status_code, &date_header,
1604 &compression, &reason) < 0) {
1605 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1606 conn->base_.address, conn->base_.port);
1607 tor_free(body); tor_free(headers);
1608 return -1;
1610 if (!reason) reason = tor_strdup("[no reason given]");
1612 log_debug(LD_DIR,
1613 "Received response from directory server '%s:%d': %d %s "
1614 "(purpose: %d)",
1615 conn->base_.address, conn->base_.port, status_code,
1616 escaped(reason),
1617 conn->base_.purpose);
1619 /* now check if it's got any hints for us about our IP address. */
1620 if (conn->dirconn_direct) {
1621 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1622 if (guess) {
1623 router_new_address_suggestion(guess, conn);
1624 tor_free(guess);
1628 if (date_header > 0) {
1629 /* The date header was written very soon after we sent our request,
1630 * so compute the skew as the difference between sending the request
1631 * and the date header. (We used to check now-date_header, but that's
1632 * inaccurate if we spend a lot of time downloading.)
1634 delta = conn->base_.timestamp_lastwritten - date_header;
1635 if (labs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1636 char dbuf[64];
1637 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1638 format_time_interval(dbuf, sizeof(dbuf), delta);
1639 log_fn(trusted ? LOG_WARN : LOG_INFO,
1640 LD_HTTP,
1641 "Received directory with skewed time (server '%s:%d'): "
1642 "It seems that our clock is %s by %s, or that theirs is %s. "
1643 "Tor requires an accurate clock to work: please check your time, "
1644 "timezone, and date settings.",
1645 conn->base_.address, conn->base_.port,
1646 delta>0 ? "ahead" : "behind", dbuf,
1647 delta>0 ? "behind" : "ahead");
1648 skewed = 1; /* don't check the recommended-versions line */
1649 if (trusted)
1650 control_event_general_status(LOG_WARN,
1651 "CLOCK_SKEW SKEW=%ld SOURCE=DIRSERV:%s:%d",
1652 delta, conn->base_.address, conn->base_.port);
1653 } else {
1654 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1655 "we are %ld seconds skewed. (That's okay.)", delta);
1658 (void) skewed; /* skewed isn't used yet. */
1660 if (status_code == 503) {
1661 routerstatus_t *rs;
1662 dir_server_t *ds;
1663 const char *id_digest = conn->identity_digest;
1664 log_info(LD_DIR,"Received http status code %d (%s) from server "
1665 "'%s:%d'. I'll try again soon.",
1666 status_code, escaped(reason), conn->base_.address,
1667 conn->base_.port);
1668 if ((rs = router_get_mutable_consensus_status_by_id(id_digest)))
1669 rs->last_dir_503_at = now;
1670 if ((ds = router_get_fallback_dirserver_by_digest(id_digest)))
1671 ds->fake_status.last_dir_503_at = now;
1673 tor_free(body); tor_free(headers); tor_free(reason);
1674 return -1;
1677 plausible = body_is_plausible(body, body_len, conn->base_.purpose);
1678 if (compression != NO_METHOD || !plausible) {
1679 char *new_body = NULL;
1680 size_t new_len = 0;
1681 compress_method_t guessed = detect_compression_method(body, body_len);
1682 if (compression == UNKNOWN_METHOD || guessed != compression) {
1683 /* Tell the user if we don't believe what we're told about compression.*/
1684 const char *description1, *description2;
1685 if (compression == ZLIB_METHOD)
1686 description1 = "as deflated";
1687 else if (compression == GZIP_METHOD)
1688 description1 = "as gzipped";
1689 else if (compression == NO_METHOD)
1690 description1 = "as uncompressed";
1691 else
1692 description1 = "with an unknown Content-Encoding";
1693 if (guessed == ZLIB_METHOD)
1694 description2 = "deflated";
1695 else if (guessed == GZIP_METHOD)
1696 description2 = "gzipped";
1697 else if (!plausible)
1698 description2 = "confusing binary junk";
1699 else
1700 description2 = "uncompressed";
1702 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1703 "but it seems to be %s.%s",
1704 conn->base_.address, conn->base_.port, description1,
1705 description2,
1706 (compression>0 && guessed>0)?" Trying both.":"");
1708 /* Try declared compression first if we can. */
1709 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1710 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1711 !allow_partial, LOG_PROTOCOL_WARN);
1712 /* Okay, if that didn't work, and we think that it was compressed
1713 * differently, try that. */
1714 if (!new_body &&
1715 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1716 compression != guessed)
1717 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1718 !allow_partial, LOG_PROTOCOL_WARN);
1719 /* If we're pretty sure that we have a compressed directory, and
1720 * we didn't manage to uncompress it, then warn and bail. */
1721 if (!plausible && !new_body) {
1722 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1723 "Unable to decompress HTTP body (server '%s:%d').",
1724 conn->base_.address, conn->base_.port);
1725 tor_free(body); tor_free(headers); tor_free(reason);
1726 return -1;
1728 if (new_body) {
1729 tor_free(body);
1730 body = new_body;
1731 body_len = new_len;
1732 was_compressed = 1;
1736 if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1737 int r;
1738 const char *flavname = conn->requested_resource;
1739 if (status_code != 200) {
1740 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1741 tor_log(severity, LD_DIR,
1742 "Received http status code %d (%s) from server "
1743 "'%s:%d' while fetching consensus directory.",
1744 status_code, escaped(reason), conn->base_.address,
1745 conn->base_.port);
1746 tor_free(body); tor_free(headers); tor_free(reason);
1747 networkstatus_consensus_download_failed(status_code, flavname);
1748 return -1;
1750 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1751 "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
1752 if ((r=networkstatus_set_current_consensus(body, flavname, 0))<0) {
1753 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1754 "Unable to load %s consensus directory downloaded from "
1755 "server '%s:%d'. I'll try again soon.",
1756 flavname, conn->base_.address, conn->base_.port);
1757 tor_free(body); tor_free(headers); tor_free(reason);
1758 networkstatus_consensus_download_failed(0, flavname);
1759 return -1;
1761 /* launches router downloads as needed */
1762 routers_update_all_from_networkstatus(now, 3);
1763 update_microdescs_from_networkstatus(now);
1764 update_microdesc_downloads(now);
1765 directory_info_has_arrived(now, 0);
1766 log_info(LD_DIR, "Successfully loaded consensus.");
1769 if (conn->base_.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1770 if (status_code != 200) {
1771 log_warn(LD_DIR,
1772 "Received http status code %d (%s) from server "
1773 "'%s:%d' while fetching \"/tor/keys/%s\".",
1774 status_code, escaped(reason), conn->base_.address,
1775 conn->base_.port, conn->requested_resource);
1776 connection_dir_download_cert_failed(conn, status_code);
1777 tor_free(body); tor_free(headers); tor_free(reason);
1778 return -1;
1780 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1781 "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
1784 * Tell trusted_dirs_load_certs_from_string() whether it was by fp
1785 * or fp-sk pair.
1787 src_code = -1;
1788 if (!strcmpstart(conn->requested_resource, "fp/")) {
1789 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST;
1790 } else if (!strcmpstart(conn->requested_resource, "fp-sk/")) {
1791 src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST;
1794 if (src_code != -1) {
1795 if (trusted_dirs_load_certs_from_string(body, src_code, 1)<0) {
1796 log_warn(LD_DIR, "Unable to parse fetched certificates");
1797 /* if we fetched more than one and only some failed, the successful
1798 * ones got flushed to disk so it's safe to call this on them */
1799 connection_dir_download_cert_failed(conn, status_code);
1800 } else {
1801 directory_info_has_arrived(now, 0);
1802 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1804 } else {
1805 log_warn(LD_DIR,
1806 "Couldn't figure out what to do with fetched certificates for "
1807 "unknown resource %s",
1808 conn->requested_resource);
1809 connection_dir_download_cert_failed(conn, status_code);
1812 if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1813 const char *msg;
1814 int st;
1815 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1816 (int)body_len, conn->base_.address, conn->base_.port);
1817 if (status_code != 200) {
1818 log_warn(LD_DIR,
1819 "Received http status code %d (%s) from server "
1820 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1821 status_code, escaped(reason), conn->base_.address,
1822 conn->base_.port, conn->requested_resource);
1823 tor_free(body); tor_free(headers); tor_free(reason);
1824 return -1;
1826 dirvote_add_vote(body, &msg, &st);
1827 if (st > 299) {
1828 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1829 } else {
1830 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1833 if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1834 const char *msg = NULL;
1835 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1836 (int)body_len, conn->base_.address, conn->base_.port);
1837 if (status_code != 200) {
1838 log_warn(LD_DIR,
1839 "Received http status code %d (%s) from server '%s:%d' while fetching "
1840 "\"/tor/status-vote/next/consensus-signatures.z\".",
1841 status_code, escaped(reason), conn->base_.address,
1842 conn->base_.port);
1843 tor_free(body); tor_free(headers); tor_free(reason);
1844 return -1;
1846 if (dirvote_add_signatures(body, conn->base_.address, &msg)<0) {
1847 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1848 conn->base_.address, conn->base_.port, msg?msg:"???");
1852 if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1853 conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1854 int was_ei = conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1855 smartlist_t *which = NULL;
1856 int n_asked_for = 0;
1857 int descriptor_digests = conn->requested_resource &&
1858 !strcmpstart(conn->requested_resource,"d/");
1859 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1860 was_ei ? "extra server info" : "server info",
1861 (int)body_len, conn->base_.address, conn->base_.port);
1862 if (conn->requested_resource &&
1863 (!strcmpstart(conn->requested_resource,"d/") ||
1864 !strcmpstart(conn->requested_resource,"fp/"))) {
1865 which = smartlist_new();
1866 dir_split_resource_into_fingerprints(conn->requested_resource +
1867 (descriptor_digests ? 2 : 3),
1868 which, NULL, 0);
1869 n_asked_for = smartlist_len(which);
1871 if (status_code != 200) {
1872 int dir_okay = status_code == 404 ||
1873 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1874 /* 404 means that it didn't have them; no big deal.
1875 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1876 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1877 "Received http status code %d (%s) from server '%s:%d' "
1878 "while fetching \"/tor/server/%s\". I'll try again soon.",
1879 status_code, escaped(reason), conn->base_.address,
1880 conn->base_.port, conn->requested_resource);
1881 if (!which) {
1882 connection_dir_download_routerdesc_failed(conn);
1883 } else {
1884 dir_routerdesc_download_failed(which, status_code,
1885 conn->router_purpose,
1886 was_ei, descriptor_digests);
1887 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1888 smartlist_free(which);
1890 tor_free(body); tor_free(headers); tor_free(reason);
1891 return dir_okay ? 0 : -1;
1893 /* Learn the routers, assuming we requested by fingerprint or "all"
1894 * or "authority".
1896 * We use "authority" to fetch our own descriptor for
1897 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1898 * the output of "authority" requests unless we are using bridges,
1899 * since otherwise they'll be the response from reachability tests,
1900 * and we don't really want to add that to our routerlist. */
1901 if (which || (conn->requested_resource &&
1902 (!strcmpstart(conn->requested_resource, "all") ||
1903 (!strcmpstart(conn->requested_resource, "authority") &&
1904 get_options()->UseBridges)))) {
1905 /* as we learn from them, we remove them from 'which' */
1906 if (was_ei) {
1907 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1908 descriptor_digests);
1909 } else {
1910 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1911 // descriptor_digests, conn->router_purpose);
1912 if (load_downloaded_routers(body, which, descriptor_digests,
1913 conn->router_purpose,
1914 conn->base_.address))
1915 directory_info_has_arrived(now, 0);
1918 if (which) { /* mark remaining ones as failed */
1919 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1920 n_asked_for-smartlist_len(which), n_asked_for,
1921 was_ei ? "extra-info documents" : "router descriptors",
1922 conn->base_.address, (int)conn->base_.port);
1923 if (smartlist_len(which)) {
1924 dir_routerdesc_download_failed(which, status_code,
1925 conn->router_purpose,
1926 was_ei, descriptor_digests);
1928 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1929 smartlist_free(which);
1931 if (directory_conn_is_self_reachability_test(conn))
1932 router_dirport_found_reachable();
1934 if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
1935 smartlist_t *which = NULL;
1936 log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
1937 "size %d) from server '%s:%d'",
1938 status_code, (int)body_len, conn->base_.address,
1939 conn->base_.port);
1940 tor_assert(conn->requested_resource &&
1941 !strcmpstart(conn->requested_resource, "d/"));
1942 which = smartlist_new();
1943 dir_split_resource_into_fingerprints(conn->requested_resource+2,
1944 which, NULL,
1945 DSR_DIGEST256|DSR_BASE64);
1946 if (status_code != 200) {
1947 log_info(LD_DIR, "Received status code %d (%s) from server "
1948 "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again "
1949 "soon.",
1950 status_code, escaped(reason), conn->base_.address,
1951 (int)conn->base_.port, conn->requested_resource);
1952 dir_microdesc_download_failed(which, status_code);
1953 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1954 smartlist_free(which);
1955 tor_free(body); tor_free(headers); tor_free(reason);
1956 return 0;
1957 } else {
1958 smartlist_t *mds;
1959 mds = microdescs_add_to_cache(get_microdesc_cache(),
1960 body, body+body_len, SAVED_NOWHERE, 0,
1961 now, which);
1962 if (smartlist_len(which)) {
1963 /* Mark remaining ones as failed. */
1964 dir_microdesc_download_failed(which, status_code);
1966 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
1967 count_loading_descriptors_progress());
1968 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1969 smartlist_free(which);
1970 smartlist_free(mds);
1974 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1975 switch (status_code) {
1976 case 200: {
1977 dir_server_t *ds =
1978 router_get_trusteddirserver_by_digest(conn->identity_digest);
1979 char *rejected_hdr = http_get_header(headers,
1980 "X-Descriptor-Not-New: ");
1981 if (rejected_hdr) {
1982 if (!strcmp(rejected_hdr, "Yes")) {
1983 log_info(LD_GENERAL,
1984 "Authority '%s' declined our descriptor (not new)",
1985 ds->nickname);
1986 /* XXXX use this information; be sure to upload next one
1987 * sooner. -NM */
1988 /* XXXX023 On further thought, the task above implies that we're
1989 * basing our regenerate-descriptor time on when we uploaded the
1990 * last descriptor, not on the published time of the last
1991 * descriptor. If those are different, that's a bad thing to
1992 * do. -NM */
1994 tor_free(rejected_hdr);
1996 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1997 "descriptor: finished.");
1998 control_event_server_status(
1999 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
2000 conn->base_.address, conn->base_.port);
2002 ds->has_accepted_serverdesc = 1;
2003 if (directories_have_accepted_server_descriptor())
2004 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
2006 break;
2007 case 400:
2008 log_warn(LD_GENERAL,"http status 400 (%s) response from "
2009 "dirserver '%s:%d'. Please correct.",
2010 escaped(reason), conn->base_.address, conn->base_.port);
2011 control_event_server_status(LOG_WARN,
2012 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
2013 conn->base_.address, conn->base_.port, escaped(reason));
2014 break;
2015 default:
2016 log_warn(LD_GENERAL,
2017 "http status %d (%s) reason unexpected while uploading "
2018 "descriptor to server '%s:%d').",
2019 status_code, escaped(reason), conn->base_.address,
2020 conn->base_.port);
2021 break;
2023 /* return 0 in all cases, since we don't want to mark any
2024 * dirservers down just because they don't like us. */
2027 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
2028 switch (status_code) {
2029 case 200: {
2030 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
2031 conn->base_.address, conn->base_.port);
2033 break;
2034 case 400:
2035 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
2036 "vote to dirserver '%s:%d'. Please correct.",
2037 escaped(reason), conn->base_.address, conn->base_.port);
2038 break;
2039 default:
2040 log_warn(LD_GENERAL,
2041 "http status %d (%s) reason unexpected while uploading "
2042 "vote to server '%s:%d').",
2043 status_code, escaped(reason), conn->base_.address,
2044 conn->base_.port);
2045 break;
2047 /* return 0 in all cases, since we don't want to mark any
2048 * dirservers down just because they don't like us. */
2051 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
2052 switch (status_code) {
2053 case 200: {
2054 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
2055 conn->base_.address, conn->base_.port);
2057 break;
2058 case 400:
2059 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
2060 "signatures to dirserver '%s:%d'. Please correct.",
2061 escaped(reason), conn->base_.address, conn->base_.port);
2062 break;
2063 default:
2064 log_warn(LD_GENERAL,
2065 "http status %d (%s) reason unexpected while uploading "
2066 "signatures to server '%s:%d').",
2067 status_code, escaped(reason), conn->base_.address,
2068 conn->base_.port);
2069 break;
2071 /* return 0 in all cases, since we don't want to mark any
2072 * dirservers down just because they don't like us. */
2075 if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
2076 #define SEND_HS_DESC_FAILED_EVENT() ( \
2077 control_event_hs_descriptor_failed(conn->rend_data, \
2078 conn->identity_digest) )
2079 tor_assert(conn->rend_data);
2080 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
2081 "(%s))",
2082 (int)body_len, status_code, escaped(reason));
2083 switch (status_code) {
2084 case 200:
2085 switch (rend_cache_store_v2_desc_as_client(body, conn->rend_data)) {
2086 case RCS_BADDESC:
2087 case RCS_NOTDIR: /* Impossible */
2088 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
2089 "Retrying at another directory.");
2090 /* We'll retry when connection_about_to_close_connection()
2091 * cleans this dir conn up. */
2092 SEND_HS_DESC_FAILED_EVENT();
2093 break;
2094 case RCS_OKAY:
2095 default:
2096 /* success. notify pending connections about this. */
2097 log_info(LD_REND, "Successfully fetched v2 rendezvous "
2098 "descriptor.");
2099 control_event_hs_descriptor_received(conn->rend_data,
2100 conn->identity_digest);
2101 conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
2102 rend_client_desc_trynow(conn->rend_data->onion_address);
2103 break;
2105 break;
2106 case 404:
2107 /* Not there. We'll retry when
2108 * connection_about_to_close_connection() cleans this conn up. */
2109 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
2110 "Retrying at another directory.");
2111 SEND_HS_DESC_FAILED_EVENT();
2112 break;
2113 case 400:
2114 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
2115 "http status 400 (%s). Dirserver didn't like our "
2116 "v2 rendezvous query? Retrying at another directory.",
2117 escaped(reason));
2118 SEND_HS_DESC_FAILED_EVENT();
2119 break;
2120 default:
2121 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
2122 "http status %d (%s) response unexpected while "
2123 "fetching v2 hidden service descriptor (server '%s:%d'). "
2124 "Retrying at another directory.",
2125 status_code, escaped(reason), conn->base_.address,
2126 conn->base_.port);
2127 SEND_HS_DESC_FAILED_EVENT();
2128 break;
2132 if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
2133 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
2134 "(%s))",
2135 status_code, escaped(reason));
2136 switch (status_code) {
2137 case 200:
2138 log_info(LD_REND,
2139 "Uploading rendezvous descriptor: finished with status "
2140 "200 (%s)", escaped(reason));
2141 break;
2142 case 400:
2143 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
2144 "'%s:%d'. Malformed rendezvous descriptor?",
2145 escaped(reason), conn->base_.address, conn->base_.port);
2146 break;
2147 default:
2148 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
2149 "'%s:%d').",
2150 status_code, escaped(reason), conn->base_.address,
2151 conn->base_.port);
2152 break;
2155 note_client_request(conn->base_.purpose, was_compressed, orig_len);
2156 tor_free(body); tor_free(headers); tor_free(reason);
2157 return 0;
2160 /** Called when a directory connection reaches EOF. */
2162 connection_dir_reached_eof(dir_connection_t *conn)
2164 int retval;
2165 if (conn->base_.state != DIR_CONN_STATE_CLIENT_READING) {
2166 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
2167 conn->base_.state);
2168 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
2169 connection_mark_for_close(TO_CONN(conn));
2170 return -1;
2173 retval = connection_dir_client_reached_eof(conn);
2174 if (retval == 0) /* success */
2175 conn->base_.state = DIR_CONN_STATE_CLIENT_FINISHED;
2176 connection_mark_for_close(TO_CONN(conn));
2177 return retval;
2180 /** If any directory object is arriving, and it's over 10MB large, we're
2181 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
2182 * ask for more than 96 router descriptors at a time.)
2184 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
2186 /** Read handler for directory connections. (That's connections <em>to</em>
2187 * directory servers and connections <em>at</em> directory servers.)
2190 connection_dir_process_inbuf(dir_connection_t *conn)
2192 tor_assert(conn);
2193 tor_assert(conn->base_.type == CONN_TYPE_DIR);
2195 /* Directory clients write, then read data until they receive EOF;
2196 * directory servers read data until they get an HTTP command, then
2197 * write their response (when it's finished flushing, they mark for
2198 * close).
2201 /* If we're on the dirserver side, look for a command. */
2202 if (conn->base_.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
2203 if (directory_handle_command(conn) < 0) {
2204 connection_mark_for_close(TO_CONN(conn));
2205 return -1;
2207 return 0;
2210 if (connection_get_inbuf_len(TO_CONN(conn)) > MAX_DIRECTORY_OBJECT_SIZE) {
2211 log_warn(LD_HTTP, "Too much data received from directory connection: "
2212 "denial of service attempt, or you need to upgrade?");
2213 connection_mark_for_close(TO_CONN(conn));
2214 return -1;
2217 if (!conn->base_.inbuf_reached_eof)
2218 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
2219 return 0;
2222 /** Called when we're about to finally unlink and free a directory connection:
2223 * perform necessary accounting and cleanup */
2224 void
2225 connection_dir_about_to_close(dir_connection_t *dir_conn)
2227 connection_t *conn = TO_CONN(dir_conn);
2229 if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
2230 /* It's a directory connection and connecting or fetching
2231 * failed: forget about this router, and maybe try again. */
2232 connection_dir_request_failed(dir_conn);
2234 /* If we were trying to fetch a v2 rend desc and did not succeed,
2235 * retry as needed. (If a fetch is successful, the connection state
2236 * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 to mark that
2237 * refetching is unnecessary.) */
2238 if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
2239 dir_conn->rend_data &&
2240 strlen(dir_conn->rend_data->onion_address) == REND_SERVICE_ID_LEN_BASE32)
2241 rend_client_refetch_v2_renddesc(dir_conn->rend_data);
2244 /** Create an http response for the client <b>conn</b> out of
2245 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
2247 static void
2248 write_http_status_line(dir_connection_t *conn, int status,
2249 const char *reason_phrase)
2251 char buf[256];
2252 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
2253 status, reason_phrase ? reason_phrase : "OK") < 0) {
2254 log_warn(LD_BUG,"status line too long.");
2255 return;
2257 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
2260 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
2261 * with <b>type</b> as the Content-Type.
2263 * If <b>length</b> is nonnegative, it is the Content-Length.
2264 * If <b>encoding</b> is provided, it is the Content-Encoding.
2265 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
2266 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
2267 static void
2268 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
2269 const char *type, const char *encoding,
2270 const char *extra_headers,
2271 long cache_lifetime)
2273 char date[RFC1123_TIME_LEN+1];
2274 char tmp[1024];
2275 char *cp;
2276 time_t now = time(NULL);
2278 tor_assert(conn);
2280 format_rfc1123_time(date, now);
2281 cp = tmp;
2282 tor_snprintf(cp, sizeof(tmp),
2283 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
2284 date);
2285 cp += strlen(tmp);
2286 if (type) {
2287 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
2288 cp += strlen(cp);
2290 if (!is_local_addr(&conn->base_.addr)) {
2291 /* Don't report the source address for a nearby/private connection.
2292 * Otherwise we tend to mis-report in cases where incoming ports are
2293 * being forwarded to a Tor server running behind the firewall. */
2294 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2295 X_ADDRESS_HEADER "%s\r\n", conn->base_.address);
2296 cp += strlen(cp);
2298 if (encoding) {
2299 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2300 "Content-Encoding: %s\r\n", encoding);
2301 cp += strlen(cp);
2303 if (length >= 0) {
2304 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2305 "Content-Length: %ld\r\n", (long)length);
2306 cp += strlen(cp);
2308 if (cache_lifetime > 0) {
2309 char expbuf[RFC1123_TIME_LEN+1];
2310 format_rfc1123_time(expbuf, (time_t)(now + cache_lifetime));
2311 /* We could say 'Cache-control: max-age=%d' here if we start doing
2312 * http/1.1 */
2313 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2314 "Expires: %s\r\n", expbuf);
2315 cp += strlen(cp);
2316 } else if (cache_lifetime == 0) {
2317 /* We could say 'Cache-control: no-cache' here if we start doing
2318 * http/1.1 */
2319 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2320 cp += strlen(cp);
2322 if (extra_headers) {
2323 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2324 cp += strlen(cp);
2326 if (sizeof(tmp)-(cp-tmp) > 3)
2327 memcpy(cp, "\r\n", 3);
2328 else
2329 tor_assert(0);
2330 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2333 /** As write_http_response_header_impl, but sets encoding and content-typed
2334 * based on whether the response will be <b>compressed</b> or not. */
2335 static void
2336 write_http_response_header(dir_connection_t *conn, ssize_t length,
2337 int compressed, long cache_lifetime)
2339 write_http_response_header_impl(conn, length,
2340 compressed?"application/octet-stream":"text/plain",
2341 compressed?"deflate":"identity",
2342 NULL,
2343 cache_lifetime);
2346 #if defined(INSTRUMENT_DOWNLOADS) || defined(RUNNING_DOXYGEN)
2347 /* DOCDOC */
2348 typedef struct request_t {
2349 uint64_t bytes; /**< How many bytes have we transferred? */
2350 uint64_t count; /**< How many requests have we made? */
2351 } request_t;
2353 /** Map used to keep track of how much data we've up/downloaded in what kind
2354 * of request. Maps from request type to pointer to request_t. */
2355 static strmap_t *request_map = NULL;
2357 /** Record that a client request of <b>purpose</b> was made, and that
2358 * <b>bytes</b> bytes of possibly <b>compressed</b> data were sent/received.
2359 * Used to keep track of how much we've up/downloaded in what kind of
2360 * request. */
2361 static void
2362 note_client_request(int purpose, int compressed, size_t bytes)
2364 char *key;
2365 const char *kind = NULL;
2366 switch (purpose) {
2367 case DIR_PURPOSE_FETCH_CONSENSUS: kind = "dl/consensus"; break;
2368 case DIR_PURPOSE_FETCH_CERTIFICATE: kind = "dl/cert"; break;
2369 case DIR_PURPOSE_FETCH_STATUS_VOTE: kind = "dl/vote"; break;
2370 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: kind = "dl/detached_sig";
2371 break;
2372 case DIR_PURPOSE_FETCH_SERVERDESC: kind = "dl/server"; break;
2373 case DIR_PURPOSE_FETCH_EXTRAINFO: kind = "dl/extra"; break;
2374 case DIR_PURPOSE_UPLOAD_DIR: kind = "dl/ul-dir"; break;
2375 case DIR_PURPOSE_UPLOAD_VOTE: kind = "dl/ul-vote"; break;
2376 case DIR_PURPOSE_UPLOAD_SIGNATURES: kind = "dl/ul-sig"; break;
2377 case DIR_PURPOSE_FETCH_RENDDESC_V2: kind = "dl/rend2"; break;
2378 case DIR_PURPOSE_UPLOAD_RENDDESC_V2: kind = "dl/ul-rend2"; break;
2380 if (kind) {
2381 tor_asprintf(&key, "%s%s", kind, compressed?".z":"");
2382 } else {
2383 tor_asprintf(&key, "unknown purpose (%d)%s",
2384 purpose, compressed?".z":"");
2386 note_request(key, bytes);
2387 tor_free(key);
2390 /** Helper: initialize the request map to instrument downloads. */
2391 static void
2392 ensure_request_map_initialized(void)
2394 if (!request_map)
2395 request_map = strmap_new();
2398 /** Called when we just transmitted or received <b>bytes</b> worth of data
2399 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2400 * <b>bytes</b> to the total associated with key. */
2401 void
2402 note_request(const char *key, size_t bytes)
2404 request_t *r;
2405 ensure_request_map_initialized();
2407 r = strmap_get(request_map, key);
2408 if (!r) {
2409 r = tor_malloc_zero(sizeof(request_t));
2410 strmap_set(request_map, key, r);
2412 r->bytes += bytes;
2413 r->count++;
2416 /** Return a newly allocated string holding a summary of bytes used per
2417 * request type. */
2418 char *
2419 directory_dump_request_log(void)
2421 smartlist_t *lines;
2422 char *result;
2423 strmap_iter_t *iter;
2425 ensure_request_map_initialized();
2427 lines = smartlist_new();
2429 for (iter = strmap_iter_init(request_map);
2430 !strmap_iter_done(iter);
2431 iter = strmap_iter_next(request_map, iter)) {
2432 const char *key;
2433 void *val;
2434 request_t *r;
2435 strmap_iter_get(iter, &key, &val);
2436 r = val;
2437 smartlist_add_asprintf(lines, "%s "U64_FORMAT" "U64_FORMAT"\n",
2438 key, U64_PRINTF_ARG(r->bytes), U64_PRINTF_ARG(r->count));
2440 smartlist_sort_strings(lines);
2441 result = smartlist_join_strings(lines, "", 0, NULL);
2442 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2443 smartlist_free(lines);
2444 return result;
2446 #else
2447 static void
2448 note_client_request(int purpose, int compressed, size_t bytes)
2450 (void)purpose;
2451 (void)compressed;
2452 (void)bytes;
2455 void
2456 note_request(const char *key, size_t bytes)
2458 (void)key;
2459 (void)bytes;
2462 char *
2463 directory_dump_request_log(void)
2465 return tor_strdup("Not supported.");
2467 #endif
2469 /** Decide whether a client would accept the consensus we have.
2471 * Clients can say they only want a consensus if it's signed by more
2472 * than half the authorities in a list. They pass this list in
2473 * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
2475 * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
2476 * of the full authority identity digest. (Only strings of even length,
2477 * i.e. encodings of full bytes, are handled correctly. In the case
2478 * of an odd number of hex digits the last one is silently ignored.)
2480 * Returns 1 if more than half of the requested authorities signed the
2481 * consensus, 0 otherwise.
2484 client_likes_consensus(networkstatus_t *v, const char *want_url)
2486 smartlist_t *want_authorities = smartlist_new();
2487 int need_at_least;
2488 int have = 0;
2490 dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0);
2491 need_at_least = smartlist_len(want_authorities)/2+1;
2492 SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, d) {
2493 char want_digest[DIGEST_LEN];
2494 size_t want_len = strlen(d)/2;
2495 if (want_len > DIGEST_LEN)
2496 want_len = DIGEST_LEN;
2498 if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) {
2499 log_fn(LOG_PROTOCOL_WARN, LD_DIR,
2500 "Failed to decode requested authority digest %s.", escaped(d));
2501 continue;
2504 SMARTLIST_FOREACH_BEGIN(v->voters, networkstatus_voter_info_t *, vi) {
2505 if (smartlist_len(vi->sigs) &&
2506 tor_memeq(vi->identity_digest, want_digest, want_len)) {
2507 have++;
2508 break;
2510 } SMARTLIST_FOREACH_END(vi);
2512 /* early exit, if we already have enough */
2513 if (have >= need_at_least)
2514 break;
2515 } SMARTLIST_FOREACH_END(d);
2517 SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
2518 smartlist_free(want_authorities);
2519 return (have >= need_at_least);
2522 /** Helper function: called when a dirserver gets a complete HTTP GET
2523 * request. Look for a request for a directory or for a rendezvous
2524 * service descriptor. On finding one, write a response into
2525 * conn-\>outbuf. If the request is unrecognized, send a 400.
2526 * Always return 0. */
2527 static int
2528 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2529 const char *req_body, size_t req_body_len)
2531 size_t dlen;
2532 char *url, *url_mem, *header;
2533 const or_options_t *options = get_options();
2534 time_t if_modified_since = 0;
2535 int compressed;
2536 size_t url_len;
2538 /* We ignore the body of a GET request. */
2539 (void)req_body;
2540 (void)req_body_len;
2542 log_debug(LD_DIRSERV,"Received GET command.");
2544 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
2546 if (parse_http_url(headers, &url) < 0) {
2547 write_http_status_line(conn, 400, "Bad request");
2548 return 0;
2550 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2551 struct tm tm;
2552 if (parse_http_time(header, &tm) == 0) {
2553 if (tor_timegm(&tm, &if_modified_since)<0)
2554 if_modified_since = 0;
2556 /* The correct behavior on a malformed If-Modified-Since header is to
2557 * act as if no If-Modified-Since header had been given. */
2558 tor_free(header);
2560 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
2562 url_mem = url;
2563 url_len = strlen(url);
2564 compressed = url_len > 2 && !strcmp(url+url_len-2, ".z");
2565 if (compressed) {
2566 url[url_len-2] = '\0';
2567 url_len -= 2;
2570 if (!strcmp(url,"/tor/")) {
2571 const char *frontpage = get_dirportfrontpage();
2573 if (frontpage) {
2574 dlen = strlen(frontpage);
2575 /* Let's return a disclaimer page (users shouldn't use V1 anymore,
2576 and caches don't fetch '/', so this is safe). */
2578 /* [We don't check for write_bucket_low here, since we want to serve
2579 * this page no matter what.] */
2580 note_request(url, dlen);
2581 write_http_response_header_impl(conn, dlen, "text/html", "identity",
2582 NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
2583 connection_write_to_buf(frontpage, dlen, TO_CONN(conn));
2584 goto done;
2586 /* if no disclaimer file, fall through and continue */
2589 if (!strcmpstart(url, "/tor/status-vote/current/consensus")) {
2590 /* v3 network status fetch. */
2591 smartlist_t *dir_fps = smartlist_new();
2592 const char *request_type = NULL;
2593 long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2595 if (1) {
2596 networkstatus_t *v;
2597 time_t now = time(NULL);
2598 const char *want_fps = NULL;
2599 char *flavor = NULL;
2600 int flav = FLAV_NS;
2601 #define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/"
2602 #define CONSENSUS_FLAVORED_PREFIX "/tor/status-vote/current/consensus-"
2603 /* figure out the flavor if any, and who we wanted to sign the thing */
2604 if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) {
2605 const char *f, *cp;
2606 f = url + strlen(CONSENSUS_FLAVORED_PREFIX);
2607 cp = strchr(f, '/');
2608 if (cp) {
2609 want_fps = cp+1;
2610 flavor = tor_strndup(f, cp-f);
2611 } else {
2612 flavor = tor_strdup(f);
2614 flav = networkstatus_parse_flavor_name(flavor);
2615 if (flav < 0)
2616 flav = FLAV_NS;
2617 } else {
2618 if (!strcmpstart(url, CONSENSUS_URL_PREFIX))
2619 want_fps = url+strlen(CONSENSUS_URL_PREFIX);
2622 v = networkstatus_get_latest_consensus_by_flavor(flav);
2624 if (v && want_fps &&
2625 !client_likes_consensus(v, want_fps)) {
2626 write_http_status_line(conn, 404, "Consensus not signed by sufficient "
2627 "number of requested authorities");
2628 smartlist_free(dir_fps);
2629 geoip_note_ns_response(GEOIP_REJECT_NOT_ENOUGH_SIGS);
2630 tor_free(flavor);
2631 goto done;
2635 char *fp = tor_malloc_zero(DIGEST_LEN);
2636 if (flavor)
2637 strlcpy(fp, flavor, DIGEST_LEN);
2638 tor_free(flavor);
2639 smartlist_add(dir_fps, fp);
2641 request_type = compressed?"v3.z":"v3";
2642 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2645 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2646 write_http_status_line(conn, 503, "Network status object unavailable");
2647 smartlist_free(dir_fps);
2648 geoip_note_ns_response(GEOIP_REJECT_UNAVAILABLE);
2649 goto done;
2652 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2653 write_http_status_line(conn, 404, "Not found");
2654 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2655 smartlist_free(dir_fps);
2656 geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
2657 goto done;
2658 } else if (!smartlist_len(dir_fps)) {
2659 write_http_status_line(conn, 304, "Not modified");
2660 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2661 smartlist_free(dir_fps);
2662 geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
2663 goto done;
2666 dlen = dirserv_estimate_data_size(dir_fps, 0, compressed);
2667 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2668 log_debug(LD_DIRSERV,
2669 "Client asked for network status lists, but we've been "
2670 "writing too many bytes lately. Sending 503 Dir busy.");
2671 write_http_status_line(conn, 503, "Directory busy, try again later");
2672 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2673 smartlist_free(dir_fps);
2675 geoip_note_ns_response(GEOIP_REJECT_BUSY);
2676 goto done;
2679 if (1) {
2680 struct in_addr in;
2681 tor_addr_t addr;
2682 if (tor_inet_aton((TO_CONN(conn))->address, &in)) {
2683 tor_addr_from_ipv4h(&addr, ntohl(in.s_addr));
2684 geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS,
2685 &addr, NULL,
2686 time(NULL));
2687 geoip_note_ns_response(GEOIP_SUCCESS);
2688 /* Note that a request for a network status has started, so that we
2689 * can measure the download time later on. */
2690 if (conn->dirreq_id)
2691 geoip_start_dirreq(conn->dirreq_id, dlen, DIRREQ_TUNNELED);
2692 else
2693 geoip_start_dirreq(TO_CONN(conn)->global_identifier, dlen,
2694 DIRREQ_DIRECT);
2698 // note_request(request_type,dlen);
2699 (void) request_type;
2700 write_http_response_header(conn, -1, compressed,
2701 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2702 conn->fingerprint_stack = dir_fps;
2703 if (! compressed)
2704 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2706 /* Prime the connection with some data. */
2707 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2708 connection_dirserv_flushed_some(conn);
2709 goto done;
2712 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2713 !strcmpstart(url,"/tor/status-vote/next/")) {
2714 /* XXXX If-modified-since is only implemented for the current
2715 * consensus: that's probably fine, since it's the only vote document
2716 * people fetch much. */
2717 int current;
2718 ssize_t body_len = 0;
2719 ssize_t estimated_len = 0;
2720 smartlist_t *items = smartlist_new();
2721 smartlist_t *dir_items = smartlist_new();
2722 int lifetime = 60; /* XXXX023 should actually use vote intervals. */
2723 url += strlen("/tor/status-vote/");
2724 current = !strcmpstart(url, "current/");
2725 url = strchr(url, '/');
2726 tor_assert(url);
2727 ++url;
2728 if (!strcmp(url, "consensus")) {
2729 const char *item;
2730 tor_assert(!current); /* we handle current consensus specially above,
2731 * since it wants to be spooled. */
2732 if ((item = dirvote_get_pending_consensus(FLAV_NS)))
2733 smartlist_add(items, (char*)item);
2734 } else if (!current && !strcmp(url, "consensus-signatures")) {
2735 /* XXXX the spec says that we should implement
2736 * current/consensus-signatures too. It doesn't seem to be needed,
2737 * though. */
2738 const char *item;
2739 if ((item=dirvote_get_pending_detached_signatures()))
2740 smartlist_add(items, (char*)item);
2741 } else if (!strcmp(url, "authority")) {
2742 const cached_dir_t *d;
2743 int flags = DGV_BY_ID |
2744 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2745 if ((d=dirvote_get_vote(NULL, flags)))
2746 smartlist_add(dir_items, (cached_dir_t*)d);
2747 } else {
2748 const cached_dir_t *d;
2749 smartlist_t *fps = smartlist_new();
2750 int flags;
2751 if (!strcmpstart(url, "d/")) {
2752 url += 2;
2753 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2754 } else {
2755 flags = DGV_BY_ID |
2756 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2758 dir_split_resource_into_fingerprints(url, fps, NULL,
2759 DSR_HEX|DSR_SORT_UNIQ);
2760 SMARTLIST_FOREACH(fps, char *, fp, {
2761 if ((d = dirvote_get_vote(fp, flags)))
2762 smartlist_add(dir_items, (cached_dir_t*)d);
2763 tor_free(fp);
2765 smartlist_free(fps);
2767 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2768 write_http_status_line(conn, 404, "Not found");
2769 goto vote_done;
2771 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2772 body_len += compressed ? d->dir_z_len : d->dir_len);
2773 estimated_len += body_len;
2774 SMARTLIST_FOREACH(items, const char *, item, {
2775 size_t ln = strlen(item);
2776 if (compressed) {
2777 estimated_len += ln/2;
2778 } else {
2779 body_len += ln; estimated_len += ln;
2783 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
2784 write_http_status_line(conn, 503, "Directory busy, try again later.");
2785 goto vote_done;
2787 write_http_response_header(conn, body_len ? body_len : -1, compressed,
2788 lifetime);
2790 if (smartlist_len(items)) {
2791 if (compressed) {
2792 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2793 SMARTLIST_FOREACH(items, const char *, c,
2794 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2795 connection_write_to_buf_zlib("", 0, conn, 1);
2796 } else {
2797 SMARTLIST_FOREACH(items, const char *, c,
2798 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2800 } else {
2801 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2802 connection_write_to_buf(compressed ? d->dir_z : d->dir,
2803 compressed ? d->dir_z_len : d->dir_len,
2804 TO_CONN(conn)));
2806 vote_done:
2807 smartlist_free(items);
2808 smartlist_free(dir_items);
2809 goto done;
2812 if (!strcmpstart(url, "/tor/micro/d/")) {
2813 smartlist_t *fps = smartlist_new();
2815 dir_split_resource_into_fingerprints(url+strlen("/tor/micro/d/"),
2816 fps, NULL,
2817 DSR_DIGEST256|DSR_BASE64|DSR_SORT_UNIQ);
2819 if (!dirserv_have_any_microdesc(fps)) {
2820 write_http_status_line(conn, 404, "Not found");
2821 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
2822 smartlist_free(fps);
2823 goto done;
2825 dlen = dirserv_estimate_microdesc_size(fps, compressed);
2826 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2827 log_info(LD_DIRSERV,
2828 "Client asked for server descriptors, but we've been "
2829 "writing too many bytes lately. Sending 503 Dir busy.");
2830 write_http_status_line(conn, 503, "Directory busy, try again later");
2831 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
2832 smartlist_free(fps);
2833 goto done;
2836 write_http_response_header(conn, -1, compressed, MICRODESC_CACHE_LIFETIME);
2837 conn->dir_spool_src = DIR_SPOOL_MICRODESC;
2838 conn->fingerprint_stack = fps;
2840 if (compressed)
2841 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2843 connection_dirserv_flushed_some(conn);
2844 goto done;
2847 if (!strcmpstart(url,"/tor/server/") ||
2848 (!options->BridgeAuthoritativeDir &&
2849 !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
2850 int res;
2851 const char *msg;
2852 const char *request_type = NULL;
2853 int cache_lifetime = 0;
2854 int is_extra = !strcmpstart(url,"/tor/extra/");
2855 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2856 conn->fingerprint_stack = smartlist_new();
2857 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2858 &msg,
2859 !connection_dir_is_encrypted(conn),
2860 is_extra);
2862 if (!strcmpstart(url, "fp/")) {
2863 request_type = compressed?"/tor/server/fp.z":"/tor/server/fp";
2864 if (smartlist_len(conn->fingerprint_stack) == 1)
2865 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2866 } else if (!strcmpstart(url, "authority")) {
2867 request_type = compressed?"/tor/server/authority.z":
2868 "/tor/server/authority";
2869 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2870 } else if (!strcmpstart(url, "all")) {
2871 request_type = compressed?"/tor/server/all.z":"/tor/server/all";
2872 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2873 } else if (!strcmpstart(url, "d/")) {
2874 request_type = compressed?"/tor/server/d.z":"/tor/server/d";
2875 if (smartlist_len(conn->fingerprint_stack) == 1)
2876 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2877 } else {
2878 request_type = "/tor/server/?";
2880 (void) request_type; /* usable for note_request. */
2881 if (!strcmpstart(url, "d/"))
2882 conn->dir_spool_src =
2883 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2884 else
2885 conn->dir_spool_src =
2886 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2888 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2889 conn->dir_spool_src)) {
2890 res = -1;
2891 msg = "Not found";
2894 if (res < 0)
2895 write_http_status_line(conn, 404, msg);
2896 else {
2897 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2898 1, compressed);
2899 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2900 log_info(LD_DIRSERV,
2901 "Client asked for server descriptors, but we've been "
2902 "writing too many bytes lately. Sending 503 Dir busy.");
2903 write_http_status_line(conn, 503, "Directory busy, try again later");
2904 conn->dir_spool_src = DIR_SPOOL_NONE;
2905 goto done;
2907 write_http_response_header(conn, -1, compressed, cache_lifetime);
2908 if (compressed)
2909 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2910 /* Prime the connection with some data. */
2911 connection_dirserv_flushed_some(conn);
2913 goto done;
2916 if (!strcmpstart(url,"/tor/keys/")) {
2917 smartlist_t *certs = smartlist_new();
2918 ssize_t len = -1;
2919 if (!strcmp(url, "/tor/keys/all")) {
2920 authority_cert_get_all(certs);
2921 } else if (!strcmp(url, "/tor/keys/authority")) {
2922 authority_cert_t *cert = get_my_v3_authority_cert();
2923 if (cert)
2924 smartlist_add(certs, cert);
2925 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
2926 smartlist_t *fps = smartlist_new();
2927 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
2928 fps, NULL,
2929 DSR_HEX|DSR_SORT_UNIQ);
2930 SMARTLIST_FOREACH(fps, char *, d, {
2931 authority_cert_t *c = authority_cert_get_newest_by_id(d);
2932 if (c) smartlist_add(certs, c);
2933 tor_free(d);
2935 smartlist_free(fps);
2936 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
2937 smartlist_t *fps = smartlist_new();
2938 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
2939 fps, NULL,
2940 DSR_HEX|DSR_SORT_UNIQ);
2941 SMARTLIST_FOREACH(fps, char *, d, {
2942 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
2943 if (c) smartlist_add(certs, c);
2944 tor_free(d);
2946 smartlist_free(fps);
2947 } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
2948 smartlist_t *fp_sks = smartlist_new();
2949 dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
2950 fp_sks);
2951 SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
2952 authority_cert_t *c = authority_cert_get_by_digests(pair->first,
2953 pair->second);
2954 if (c) smartlist_add(certs, c);
2955 tor_free(pair);
2957 smartlist_free(fp_sks);
2958 } else {
2959 write_http_status_line(conn, 400, "Bad request");
2960 goto keys_done;
2962 if (!smartlist_len(certs)) {
2963 write_http_status_line(conn, 404, "Not found");
2964 goto keys_done;
2966 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2967 if (c->cache_info.published_on < if_modified_since)
2968 SMARTLIST_DEL_CURRENT(certs, c));
2969 if (!smartlist_len(certs)) {
2970 write_http_status_line(conn, 304, "Not modified");
2971 goto keys_done;
2973 len = 0;
2974 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2975 len += c->cache_info.signed_descriptor_len);
2977 if (global_write_bucket_low(TO_CONN(conn), compressed?len/2:len, 2)) {
2978 write_http_status_line(conn, 503, "Directory busy, try again later.");
2979 goto keys_done;
2982 write_http_response_header(conn, compressed?-1:len, compressed, 60*60);
2983 if (compressed) {
2984 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2985 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2986 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
2987 c->cache_info.signed_descriptor_len,
2988 conn, 0));
2989 connection_write_to_buf_zlib("", 0, conn, 1);
2990 } else {
2991 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2992 connection_write_to_buf(c->cache_info.signed_descriptor_body,
2993 c->cache_info.signed_descriptor_len,
2994 TO_CONN(conn)));
2996 keys_done:
2997 smartlist_free(certs);
2998 goto done;
3001 if (options->HidServDirectoryV2 &&
3002 connection_dir_is_encrypted(conn) &&
3003 !strcmpstart(url,"/tor/rendezvous2/")) {
3004 /* Handle v2 rendezvous descriptor fetch request. */
3005 const char *descp;
3006 const char *query = url + strlen("/tor/rendezvous2/");
3007 if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) {
3008 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
3009 safe_str(escaped(query)));
3010 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
3011 case 1: /* valid */
3012 write_http_response_header(conn, strlen(descp), 0, 0);
3013 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
3014 break;
3015 case 0: /* well-formed but not present */
3016 write_http_status_line(conn, 404, "Not found");
3017 break;
3018 case -1: /* not well-formed */
3019 write_http_status_line(conn, 400, "Bad request");
3020 break;
3022 } else { /* not well-formed */
3023 write_http_status_line(conn, 400, "Bad request");
3025 goto done;
3028 if (options->BridgeAuthoritativeDir &&
3029 options->BridgePassword_AuthDigest_ &&
3030 connection_dir_is_encrypted(conn) &&
3031 !strcmp(url,"/tor/networkstatus-bridges")) {
3032 char *status;
3033 char digest[DIGEST256_LEN];
3035 header = http_get_header(headers, "Authorization: Basic ");
3036 if (header)
3037 crypto_digest256(digest, header, strlen(header), DIGEST_SHA256);
3039 /* now make sure the password is there and right */
3040 if (!header ||
3041 tor_memneq(digest,
3042 options->BridgePassword_AuthDigest_, DIGEST256_LEN)) {
3043 write_http_status_line(conn, 404, "Not found");
3044 tor_free(header);
3045 goto done;
3047 tor_free(header);
3049 /* all happy now. send an answer. */
3050 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
3051 dlen = strlen(status);
3052 write_http_response_header(conn, dlen, 0, 0);
3053 connection_write_to_buf(status, dlen, TO_CONN(conn));
3054 tor_free(status);
3055 goto done;
3058 if (!strcmpstart(url,"/tor/bytes.txt")) {
3059 char *bytes = directory_dump_request_log();
3060 size_t len = strlen(bytes);
3061 write_http_response_header(conn, len, 0, 0);
3062 connection_write_to_buf(bytes, len, TO_CONN(conn));
3063 tor_free(bytes);
3064 goto done;
3067 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
3068 rewritten to /tor/robots.txt */
3069 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
3070 size_t len = strlen(robots);
3071 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
3072 connection_write_to_buf(robots, len, TO_CONN(conn));
3073 goto done;
3076 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
3077 #define ADD_MALLINFO_LINE(x) do { \
3078 smartlist_add_asprintf(lines, "%s %d\n", #x, mi.x); \
3079 }while(0);
3081 if (!strcmp(url,"/tor/mallinfo.txt") &&
3082 (tor_addr_eq_ipv4h(&conn->base_.addr, 0x7f000001ul))) {
3083 char *result;
3084 size_t len;
3085 struct mallinfo mi;
3086 smartlist_t *lines;
3088 memset(&mi, 0, sizeof(mi));
3089 mi = mallinfo();
3090 lines = smartlist_new();
3092 ADD_MALLINFO_LINE(arena)
3093 ADD_MALLINFO_LINE(ordblks)
3094 ADD_MALLINFO_LINE(smblks)
3095 ADD_MALLINFO_LINE(hblks)
3096 ADD_MALLINFO_LINE(hblkhd)
3097 ADD_MALLINFO_LINE(usmblks)
3098 ADD_MALLINFO_LINE(fsmblks)
3099 ADD_MALLINFO_LINE(uordblks)
3100 ADD_MALLINFO_LINE(fordblks)
3101 ADD_MALLINFO_LINE(keepcost)
3103 result = smartlist_join_strings(lines, "", 0, NULL);
3104 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
3105 smartlist_free(lines);
3107 len = strlen(result);
3108 write_http_response_header(conn, len, 0, 0);
3109 connection_write_to_buf(result, len, TO_CONN(conn));
3110 tor_free(result);
3111 goto done;
3113 #endif
3115 /* we didn't recognize the url */
3116 write_http_status_line(conn, 404, "Not found");
3118 done:
3119 tor_free(url_mem);
3120 return 0;
3123 /** Helper function: called when a dirserver gets a complete HTTP POST
3124 * request. Look for an uploaded server descriptor or rendezvous
3125 * service descriptor. On finding one, process it and write a
3126 * response into conn-\>outbuf. If the request is unrecognized, send a
3127 * 400. Always return 0. */
3128 static int
3129 directory_handle_command_post(dir_connection_t *conn, const char *headers,
3130 const char *body, size_t body_len)
3132 char *url = NULL;
3133 const or_options_t *options = get_options();
3135 log_debug(LD_DIRSERV,"Received POST command.");
3137 conn->base_.state = DIR_CONN_STATE_SERVER_WRITING;
3139 if (parse_http_url(headers, &url) < 0) {
3140 write_http_status_line(conn, 400, "Bad request");
3141 return 0;
3143 log_debug(LD_DIRSERV,"rewritten url as '%s'.", escaped(url));
3145 /* Handle v2 rendezvous service publish request. */
3146 if (options->HidServDirectoryV2 &&
3147 connection_dir_is_encrypted(conn) &&
3148 !strcmpstart(url,"/tor/rendezvous2/publish")) {
3149 switch (rend_cache_store_v2_desc_as_dir(body)) {
3150 case RCS_NOTDIR:
3151 log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
3152 "since we're not currently a hidden service directory.",
3153 (int)body_len, conn->base_.address);
3154 write_http_status_line(conn, 503, "Currently not acting as v2 "
3155 "hidden service directory");
3156 break;
3157 case RCS_BADDESC:
3158 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
3159 (int)body_len, conn->base_.address);
3160 write_http_status_line(conn, 400,
3161 "Invalid v2 service descriptor rejected");
3162 break;
3163 case RCS_OKAY:
3164 default:
3165 write_http_status_line(conn, 200, "Service descriptor (v2) stored");
3166 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
3168 goto done;
3171 if (!authdir_mode(options)) {
3172 /* we just provide cached directories; we don't want to
3173 * receive anything. */
3174 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
3175 "accept posted server descriptors");
3176 goto done;
3179 if (authdir_mode_handles_descs(options, -1) &&
3180 !strcmp(url,"/tor/")) { /* server descriptor post */
3181 const char *msg = "[None]";
3182 uint8_t purpose = authdir_mode_bridge(options) ?
3183 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
3184 was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
3185 conn->base_.address, &msg);
3186 tor_assert(msg);
3188 if (r == ROUTER_ADDED_NOTIFY_GENERATOR) {
3189 /* Accepted with a message. */
3190 log_info(LD_DIRSERV,
3191 "Problematic router descriptor or extra-info from %s "
3192 "(\"%s\").",
3193 conn->base_.address, msg);
3194 write_http_status_line(conn, 400, msg);
3195 } else if (r == ROUTER_ADDED_SUCCESSFULLY) {
3196 write_http_status_line(conn, 200, msg);
3197 } else if (WRA_WAS_OUTDATED(r)) {
3198 write_http_response_header_impl(conn, -1, NULL, NULL,
3199 "X-Descriptor-Not-New: Yes\r\n", -1);
3200 } else {
3201 log_info(LD_DIRSERV,
3202 "Rejected router descriptor or extra-info from %s "
3203 "(\"%s\").",
3204 conn->base_.address, msg);
3205 write_http_status_line(conn, 400, msg);
3207 goto done;
3210 if (authdir_mode_v3(options) &&
3211 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
3212 const char *msg = "OK";
3213 int status;
3214 if (dirvote_add_vote(body, &msg, &status)) {
3215 write_http_status_line(conn, status, "Vote stored");
3216 } else {
3217 tor_assert(msg);
3218 log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").",
3219 conn->base_.address, msg);
3220 write_http_status_line(conn, status, msg);
3222 goto done;
3225 if (authdir_mode_v3(options) &&
3226 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
3227 const char *msg = NULL;
3228 if (dirvote_add_signatures(body, conn->base_.address, &msg)>=0) {
3229 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
3230 } else {
3231 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
3232 conn->base_.address, msg?msg:"???");
3233 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
3235 goto done;
3238 /* we didn't recognize the url */
3239 write_http_status_line(conn, 404, "Not found");
3241 done:
3242 tor_free(url);
3243 return 0;
3246 /** Called when a dirserver receives data on a directory connection;
3247 * looks for an HTTP request. If the request is complete, remove it
3248 * from the inbuf, try to process it; otherwise, leave it on the
3249 * buffer. Return a 0 on success, or -1 on error.
3251 static int
3252 directory_handle_command(dir_connection_t *conn)
3254 char *headers=NULL, *body=NULL;
3255 size_t body_len=0;
3256 int r;
3258 tor_assert(conn);
3259 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3261 switch (connection_fetch_from_buf_http(TO_CONN(conn),
3262 &headers, MAX_HEADERS_SIZE,
3263 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
3264 case -1: /* overflow */
3265 log_warn(LD_DIRSERV,
3266 "Request too large from address '%s' to DirPort. Closing.",
3267 safe_str(conn->base_.address));
3268 return -1;
3269 case 0:
3270 log_debug(LD_DIRSERV,"command not all here yet.");
3271 return 0;
3272 /* case 1, fall through */
3275 http_set_address_origin(headers, TO_CONN(conn));
3276 // we should escape headers here as well,
3277 // but we can't call escaped() twice, as it uses the same buffer
3278 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, escaped(body));
3280 if (!strncasecmp(headers,"GET",3))
3281 r = directory_handle_command_get(conn, headers, body, body_len);
3282 else if (!strncasecmp(headers,"POST",4))
3283 r = directory_handle_command_post(conn, headers, body, body_len);
3284 else {
3285 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
3286 "Got headers %s with unknown command. Closing.",
3287 escaped(headers));
3288 r = -1;
3291 tor_free(headers); tor_free(body);
3292 return r;
3295 /** Write handler for directory connections; called when all data has
3296 * been flushed. Close the connection or wait for a response as
3297 * appropriate.
3300 connection_dir_finished_flushing(dir_connection_t *conn)
3302 tor_assert(conn);
3303 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3305 /* Note that we have finished writing the directory response. For direct
3306 * connections this means we're done, for tunneled connections its only
3307 * an intermediate step. */
3308 if (conn->dirreq_id)
3309 geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
3310 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3311 else
3312 geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
3313 DIRREQ_DIRECT,
3314 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3315 switch (conn->base_.state) {
3316 case DIR_CONN_STATE_CONNECTING:
3317 case DIR_CONN_STATE_CLIENT_SENDING:
3318 log_debug(LD_DIR,"client finished sending command.");
3319 conn->base_.state = DIR_CONN_STATE_CLIENT_READING;
3320 return 0;
3321 case DIR_CONN_STATE_SERVER_WRITING:
3322 if (conn->dir_spool_src != DIR_SPOOL_NONE) {
3323 #ifdef USE_BUFFEREVENTS
3324 /* This can happen with paired bufferevents, since a paired connection
3325 * can flush immediately when you write to it, making the subsequent
3326 * check in connection_handle_write_cb() decide that the connection
3327 * is flushed. */
3328 log_debug(LD_DIRSERV, "Emptied a dirserv buffer, but still spooling.");
3329 #else
3330 log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
3331 connection_mark_for_close(TO_CONN(conn));
3332 #endif
3333 } else {
3334 log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
3335 connection_mark_for_close(TO_CONN(conn));
3337 return 0;
3338 default:
3339 log_warn(LD_BUG,"called in unexpected state %d.",
3340 conn->base_.state);
3341 tor_fragile_assert();
3342 return -1;
3344 return 0;
3347 /** Connected handler for directory connections: begin sending data to the
3348 * server */
3350 connection_dir_finished_connecting(dir_connection_t *conn)
3352 tor_assert(conn);
3353 tor_assert(conn->base_.type == CONN_TYPE_DIR);
3354 tor_assert(conn->base_.state == DIR_CONN_STATE_CONNECTING);
3356 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
3357 conn->base_.address,conn->base_.port);
3359 conn->base_.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
3360 return 0;
3363 /** Decide which download schedule we want to use based on descriptor type
3364 * in <b>dls</b> and whether we are acting as directory <b>server</b>, and
3365 * then return a list of int pointers defining download delays in seconds.
3366 * Helper function for download_status_increment_failure() and
3367 * download_status_reset(). */
3368 static const smartlist_t *
3369 find_dl_schedule_and_len(download_status_t *dls, int server)
3371 switch (dls->schedule) {
3372 case DL_SCHED_GENERIC:
3373 if (server)
3374 return get_options()->TestingServerDownloadSchedule;
3375 else
3376 return get_options()->TestingClientDownloadSchedule;
3377 case DL_SCHED_CONSENSUS:
3378 if (server)
3379 return get_options()->TestingServerConsensusDownloadSchedule;
3380 else
3381 return get_options()->TestingClientConsensusDownloadSchedule;
3382 case DL_SCHED_BRIDGE:
3383 return get_options()->TestingBridgeDownloadSchedule;
3384 default:
3385 tor_assert(0);
3389 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
3390 * <b>status_code</b>. Increment the failure count (if the code indicates a
3391 * real failure) and set <b>dls</b>-\>next_attempt_at to an appropriate time
3392 * in the future. */
3393 time_t
3394 download_status_increment_failure(download_status_t *dls, int status_code,
3395 const char *item, int server, time_t now)
3397 const smartlist_t *schedule;
3398 int increment;
3399 tor_assert(dls);
3400 if (status_code != 503 || server) {
3401 if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1)
3402 ++dls->n_download_failures;
3405 schedule = find_dl_schedule_and_len(dls, server);
3407 if (dls->n_download_failures < smartlist_len(schedule))
3408 increment = *(int *)smartlist_get(schedule, dls->n_download_failures);
3409 else if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
3410 increment = INT_MAX;
3411 else
3412 increment = *(int *)smartlist_get(schedule, smartlist_len(schedule) - 1);
3414 if (increment < INT_MAX)
3415 dls->next_attempt_at = now+increment;
3416 else
3417 dls->next_attempt_at = TIME_MAX;
3419 if (item) {
3420 if (increment == 0)
3421 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
3422 item, (int)dls->n_download_failures);
3423 else if (dls->next_attempt_at < TIME_MAX)
3424 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
3425 item, (int)dls->n_download_failures,
3426 (int)(dls->next_attempt_at-now));
3427 else
3428 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
3429 item, (int)dls->n_download_failures);
3431 return dls->next_attempt_at;
3434 /** Reset <b>dls</b> so that it will be considered downloadable
3435 * immediately, and/or to show that we don't need it anymore.
3437 * (We find the zeroth element of the download schedule, and set
3438 * next_attempt_at to be the appropriate offset from 'now'. In most
3439 * cases this means setting it to 'now', so the item will be immediately
3440 * downloadable; in the case of bridge descriptors, the zeroth element
3441 * is an hour from now.) */
3442 void
3443 download_status_reset(download_status_t *dls)
3445 const smartlist_t *schedule = find_dl_schedule_and_len(
3446 dls, get_options()->DirPort_set);
3448 dls->n_download_failures = 0;
3449 dls->next_attempt_at = time(NULL) + *(int *)smartlist_get(schedule, 0);
3452 /** Return the number of failures on <b>dls</b> since the last success (if
3453 * any). */
3455 download_status_get_n_failures(const download_status_t *dls)
3457 return dls->n_download_failures;
3460 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
3461 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
3462 * either as descriptor digests or as identity digests based on
3463 * <b>was_descriptor_digests</b>).
3465 static void
3466 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
3467 int router_purpose,
3468 int was_extrainfo, int was_descriptor_digests)
3470 char digest[DIGEST_LEN];
3471 time_t now = time(NULL);
3472 int server = directory_fetches_from_authorities(get_options());
3473 if (!was_descriptor_digests) {
3474 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
3475 tor_assert(!was_extrainfo);
3476 connection_dir_retry_bridges(failed);
3478 return; /* FFFF should implement for other-than-router-purpose someday */
3480 SMARTLIST_FOREACH_BEGIN(failed, const char *, cp) {
3481 download_status_t *dls = NULL;
3482 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) {
3483 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
3484 continue;
3486 if (was_extrainfo) {
3487 signed_descriptor_t *sd =
3488 router_get_by_extrainfo_digest(digest);
3489 if (sd)
3490 dls = &sd->ei_dl_status;
3491 } else {
3492 dls = router_get_dl_status_by_descriptor_digest(digest);
3494 if (!dls || dls->n_download_failures >=
3495 get_options()->TestingDescriptorMaxDownloadTries)
3496 continue;
3497 download_status_increment_failure(dls, status_code, cp, server, now);
3498 } SMARTLIST_FOREACH_END(cp);
3500 /* No need to relaunch descriptor downloads here: we already do it
3501 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3504 /** Called when a connection to download microdescriptors has failed in whole
3505 * or in part. <b>failed</b> is a list of every microdesc digest we didn't
3506 * get. <b>status_code</b> is the http status code we received. Reschedule the
3507 * microdesc downloads as appropriate. */
3508 static void
3509 dir_microdesc_download_failed(smartlist_t *failed,
3510 int status_code)
3512 networkstatus_t *consensus
3513 = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
3514 routerstatus_t *rs;
3515 download_status_t *dls;
3516 time_t now = time(NULL);
3517 int server = directory_fetches_from_authorities(get_options());
3519 if (! consensus)
3520 return;
3521 SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
3522 rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
3523 if (!rs)
3524 continue;
3525 dls = &rs->dl_status;
3526 if (dls->n_download_failures >=
3527 get_options()->TestingMicrodescMaxDownloadTries)
3528 continue;
3530 char buf[BASE64_DIGEST256_LEN+1];
3531 digest256_to_base64(buf, d);
3532 download_status_increment_failure(dls, status_code, buf,
3533 server, now);
3535 } SMARTLIST_FOREACH_END(d);
3538 /** Helper. Compare two fp_pair_t objects, and return negative, 0, or
3539 * positive as appropriate. */
3540 static int
3541 compare_pairs_(const void **a, const void **b)
3543 const fp_pair_t *fp1 = *a, *fp2 = *b;
3544 int r;
3545 if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
3546 return r;
3547 else
3548 return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
3551 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
3552 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
3553 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
3554 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
3556 dir_split_resource_into_fingerprint_pairs(const char *res,
3557 smartlist_t *pairs_out)
3559 smartlist_t *pairs_tmp = smartlist_new();
3560 smartlist_t *pairs_result = smartlist_new();
3562 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
3563 if (smartlist_len(pairs_tmp)) {
3564 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
3565 size_t last_len = strlen(last);
3566 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3567 last[last_len-2] = '\0';
3570 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
3571 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
3572 log_info(LD_DIR,
3573 "Skipping digest pair %s with non-standard length.", escaped(cp));
3574 } else if (cp[HEX_DIGEST_LEN] != '-') {
3575 log_info(LD_DIR,
3576 "Skipping digest pair %s with missing dash.", escaped(cp));
3577 } else {
3578 fp_pair_t pair;
3579 if (base16_decode(pair.first, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0 ||
3580 base16_decode(pair.second,
3581 DIGEST_LEN, cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN)<0) {
3582 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
3583 } else {
3584 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
3587 tor_free(cp);
3588 } SMARTLIST_FOREACH_END(cp);
3589 smartlist_free(pairs_tmp);
3591 /* Uniq-and-sort */
3592 smartlist_sort(pairs_result, compare_pairs_);
3593 smartlist_uniq(pairs_result, compare_pairs_, tor_free_);
3595 smartlist_add_all(pairs_out, pairs_result);
3596 smartlist_free(pairs_result);
3597 return 0;
3600 /** Given a directory <b>resource</b> request, containing zero
3601 * or more strings separated by plus signs, followed optionally by ".z", store
3602 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3603 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
3605 * If (flags & DSR_HEX), then delete all elements that aren't hex digests, and
3606 * decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as
3607 * a separator, delete all the elements that aren't base64-encoded digests,
3608 * and decode the rest. If (flags & DSR_DIGEST256), these digests should be
3609 * 256 bits long; else they should be 160.
3611 * If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates.
3614 dir_split_resource_into_fingerprints(const char *resource,
3615 smartlist_t *fp_out, int *compressed_out,
3616 int flags)
3618 const int decode_hex = flags & DSR_HEX;
3619 const int decode_base64 = flags & DSR_BASE64;
3620 const int digests_are_256 = flags & DSR_DIGEST256;
3621 const int sort_uniq = flags & DSR_SORT_UNIQ;
3623 const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
3624 const int hex_digest_len = digests_are_256 ?
3625 HEX_DIGEST256_LEN : HEX_DIGEST_LEN;
3626 const int base64_digest_len = digests_are_256 ?
3627 BASE64_DIGEST256_LEN : BASE64_DIGEST_LEN;
3628 smartlist_t *fp_tmp = smartlist_new();
3630 tor_assert(!(decode_hex && decode_base64));
3631 tor_assert(fp_out);
3633 smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
3634 if (compressed_out)
3635 *compressed_out = 0;
3636 if (smartlist_len(fp_tmp)) {
3637 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3638 size_t last_len = strlen(last);
3639 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3640 last[last_len-2] = '\0';
3641 if (compressed_out)
3642 *compressed_out = 1;
3645 if (decode_hex || decode_base64) {
3646 const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
3647 int i;
3648 char *cp, *d = NULL;
3649 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3650 cp = smartlist_get(fp_tmp, i);
3651 if (strlen(cp) != encoded_len) {
3652 log_info(LD_DIR,
3653 "Skipping digest %s with non-standard length.", escaped(cp));
3654 smartlist_del_keeporder(fp_tmp, i--);
3655 goto again;
3657 d = tor_malloc_zero(digest_len);
3658 if (decode_hex ?
3659 (base16_decode(d, digest_len, cp, hex_digest_len)<0) :
3660 (base64_decode(d, digest_len, cp, base64_digest_len)<0)) {
3661 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3662 smartlist_del_keeporder(fp_tmp, i--);
3663 goto again;
3665 smartlist_set(fp_tmp, i, d);
3666 d = NULL;
3667 again:
3668 tor_free(cp);
3669 tor_free(d);
3672 if (sort_uniq) {
3673 if (decode_hex || decode_base64) {
3674 if (digests_are_256) {
3675 smartlist_sort_digests256(fp_tmp);
3676 smartlist_uniq_digests256(fp_tmp);
3677 } else {
3678 smartlist_sort_digests(fp_tmp);
3679 smartlist_uniq_digests(fp_tmp);
3681 } else {
3682 smartlist_sort_strings(fp_tmp);
3683 smartlist_uniq_strings(fp_tmp);
3686 smartlist_add_all(fp_out, fp_tmp);
3687 smartlist_free(fp_tmp);
3688 return 0;