Directory mirrors no longer include a guess at the client's IP
[tor.git] / src / or / directory.c
blob3eee6fa1cfdc13df3d38c1a2bb0374202799390c
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2008, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 /* $Id$ */
6 const char directory_c_id[] =
7 "$Id$";
9 #include "or.h"
10 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
11 #include <malloc.h>
12 #endif
14 /**
15 * \file directory.c
16 * \brief Code to send and fetch directories and router
17 * descriptors via HTTP. Directories use dirserv.c to generate the
18 * results; clients use routers.c to parse them.
19 **/
21 /* In-points to directory.c:
23 * - directory_post_to_dirservers(), called from
24 * router_upload_dir_desc_to_dirservers() in router.c
25 * upload_service_descriptor() in rendservice.c
26 * - directory_get_from_dirserver(), called from
27 * rend_client_refetch_renddesc() in rendclient.c
28 * run_scheduled_events() in main.c
29 * do_hup() in main.c
30 * - connection_dir_process_inbuf(), called from
31 * connection_process_inbuf() in connection.c
32 * - connection_dir_finished_flushing(), called from
33 * connection_finished_flushing() in connection.c
34 * - connection_dir_finished_connecting(), called from
35 * connection_finished_connecting() in connection.c
37 static void directory_send_command(dir_connection_t *conn,
38 int purpose, int direct, const char *resource,
39 const char *payload, size_t payload_len,
40 time_t if_modified_since);
41 static int directory_handle_command(dir_connection_t *conn);
42 static int body_is_plausible(const char *body, size_t body_len, int purpose);
43 static int purpose_needs_anonymity(uint8_t dir_purpose,
44 uint8_t router_purpose);
45 static char *http_get_header(const char *headers, const char *which);
46 static void http_set_address_origin(const char *headers, connection_t *conn);
47 static void connection_dir_download_networkstatus_failed(
48 dir_connection_t *conn, int status_code);
49 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
50 static void connection_dir_download_cert_failed(
51 dir_connection_t *conn, int status_code);
52 static void dir_networkstatus_download_failed(smartlist_t *failed,
53 int status_code);
54 static void dir_routerdesc_download_failed(smartlist_t *failed,
55 int status_code,
56 int router_purpose,
57 int was_extrainfo,
58 int was_descriptor_digests);
59 static void note_request(const char *key, size_t bytes);
61 /********* START VARIABLES **********/
63 /** How far in the future do we allow a directory server to tell us it is
64 * before deciding that one of us has the wrong time? */
65 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
67 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
69 /** HTTP cache control: how long do we tell proxies they can cache each
70 * kind of document we serve? */
71 #define FULL_DIR_CACHE_LIFETIME (60*60)
72 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
73 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
74 #define ROUTERDESC_CACHE_LIFETIME (30*60)
75 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
76 #define ROBOTS_CACHE_LIFETIME (24*60*60)
78 /********* END VARIABLES ************/
80 /** Return true iff the directory purpose 'purpose' must use an
81 * anonymous connection to a directory. */
82 static int
83 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
85 if (get_options()->AllDirActionsPrivate)
86 return 1;
87 if (router_purpose == ROUTER_PURPOSE_BRIDGE && has_completed_circuit)
88 return 1; /* if no circuits yet, we may need this info to bootstrap. */
89 if (dir_purpose == DIR_PURPOSE_FETCH_DIR ||
90 dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
91 dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
92 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
93 dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
94 dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
95 dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
96 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
97 dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
98 dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
99 dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
100 dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
101 return 0;
102 return 1;
105 /** Return a newly allocated string describing <b>auth</b>. */
106 char *
107 authority_type_to_string(authority_type_t auth)
109 char *result;
110 smartlist_t *lst = smartlist_create();
111 if (auth & V1_AUTHORITY)
112 smartlist_add(lst, (void*)"V1");
113 if (auth & V2_AUTHORITY)
114 smartlist_add(lst, (void*)"V2");
115 if (auth & BRIDGE_AUTHORITY)
116 smartlist_add(lst, (void*)"Bridge");
117 if (auth & HIDSERV_AUTHORITY)
118 smartlist_add(lst, (void*)"Hidden service");
119 if (smartlist_len(lst)) {
120 result = smartlist_join_strings(lst, ", ", 0, NULL);
121 } else {
122 result = tor_strdup("[Not an authority]");
124 smartlist_free(lst);
125 return result;
128 /** Return a string describing a given directory connection purpose. */
129 static const char *
130 dir_conn_purpose_to_string(int purpose)
132 switch (purpose)
134 case DIR_PURPOSE_FETCH_DIR:
135 return "v1 directory fetch";
136 case DIR_PURPOSE_FETCH_RENDDESC:
137 return "hidden-service descriptor fetch";
138 case DIR_PURPOSE_UPLOAD_DIR:
139 return "server descriptor upload";
140 case DIR_PURPOSE_UPLOAD_RENDDESC:
141 return "hidden-service descriptor upload";
142 case DIR_PURPOSE_UPLOAD_VOTE:
143 return "server vote upload";
144 case DIR_PURPOSE_UPLOAD_SIGNATURES:
145 return "consensus signature upload";
146 case DIR_PURPOSE_FETCH_RUNNING_LIST:
147 return "running-routers fetch";
148 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
149 return "network-status fetch";
150 case DIR_PURPOSE_FETCH_SERVERDESC:
151 return "server descriptor fetch";
152 case DIR_PURPOSE_FETCH_EXTRAINFO:
153 return "extra-info fetch";
154 case DIR_PURPOSE_FETCH_CONSENSUS:
155 return "consensus network-status fetch";
156 case DIR_PURPOSE_FETCH_CERTIFICATE:
157 return "authority cert fetch";
158 case DIR_PURPOSE_FETCH_STATUS_VOTE:
159 return "status vote fetch";
160 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
161 return "consensus signature fetch";
162 case DIR_PURPOSE_FETCH_RENDDESC_V2:
163 return "hidden-service v2 descriptor fetch";
164 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
165 return "hidden-service v2 descriptor upload";
168 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
169 return "(unknown)";
172 /** Return true iff <b>identity_digest</b> is the digest of a router we
173 * believe to support extrainfo downloads. (If <b>is_authority</b> we do
174 * additional checking that's only valid for authorities.) */
176 router_supports_extrainfo(const char *identity_digest, int is_authority)
178 routerinfo_t *ri = router_get_by_digest(identity_digest);
180 if (ri) {
181 if (ri->caches_extra_info)
182 return 1;
183 if (is_authority && ri->platform &&
184 tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
185 return 1;
187 if (is_authority) {
188 routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
189 if (rs && rs->version_supports_extrainfo_upload)
190 return 1;
192 return 0;
195 /** Return true iff all trusted directory servers have accepted our
196 * server descriptor. */
198 directories_have_accepted_server_descriptor(void)
200 smartlist_t *servers = router_get_trusted_dir_servers();
201 or_options_t *options = get_options();
202 /* XXX020 If any authority of the needed type is down, this
203 * function will never return true. Perhaps we need to be
204 * tolerant of down servers? Or even better, should we change
205 * this so one successful upload is enough? -RD */
206 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
207 if ((d->type & options->_PublishServerDescriptor) &&
208 !d->has_accepted_serverdesc) {
209 return 0;
212 return 1;
215 /** Start a connection to every suitable directory authority, using
216 * connection purpose 'purpose' and uploading the payload 'payload'
217 * (length 'payload_len'). The purpose should be one of
218 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
220 * <b>type</b> specifies what sort of dir authorities (V1, V2,
221 * HIDSERV, BRIDGE) we should upload to.
223 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
224 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
225 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
226 * to all authorities, and the extra-info document to all authorities that
227 * support it.
229 void
230 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
231 authority_type_t type,
232 const char *payload,
233 size_t payload_len, size_t extrainfo_len)
235 int post_via_tor;
236 smartlist_t *dirservers = router_get_trusted_dir_servers();
237 int found = 0;
238 tor_assert(dirservers);
239 /* This tries dirservers which we believe to be down, but ultimately, that's
240 * harmless, and we may as well err on the side of getting things uploaded.
242 SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
244 routerstatus_t *rs = &(ds->fake_status);
245 size_t upload_len = payload_len;
247 if ((type & ds->type) == 0)
248 continue;
250 found = 1; /* at least one authority of this type was listed */
251 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
252 ds->has_accepted_serverdesc = 0;
254 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
255 upload_len += extrainfo_len;
256 log_info(LD_DIR, "Uploading an extrainfo (length %d)",
257 (int) extrainfo_len);
259 post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) ||
260 !fascist_firewall_allows_address_dir(ds->addr, ds->dir_port);
261 directory_initiate_command_routerstatus(rs, dir_purpose,
262 router_purpose,
263 post_via_tor,
264 NULL, payload, upload_len, 0);
266 if (!found) {
267 char *s = authority_type_to_string(type);
268 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
269 "of type '%s', but no authorities of that type listed!", s);
270 tor_free(s);
274 /** Start a connection to a random running directory server, using
275 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
276 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
277 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
278 * down, mark them up and try again.
280 void
281 directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
282 const char *resource, int retry_if_no_servers)
284 routerstatus_t *rs = NULL;
285 or_options_t *options = get_options();
286 int prefer_authority = directory_fetches_from_authorities(options);
287 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
288 authority_type_t type;
289 int flags = retry_if_no_servers ? PDS_RETRY_IF_NO_SERVERS : 0;
290 time_t if_modified_since = 0;
292 /* FFFF we could break this switch into its own function, and call
293 * it elsewhere in directory.c. -RD */
294 switch (dir_purpose) {
295 case DIR_PURPOSE_FETCH_EXTRAINFO:
296 type = EXTRAINFO_CACHE |
297 (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
298 V2_AUTHORITY);
299 break;
300 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
301 case DIR_PURPOSE_FETCH_SERVERDESC:
302 type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
303 V2_AUTHORITY);
304 break;
305 case DIR_PURPOSE_FETCH_DIR:
306 case DIR_PURPOSE_FETCH_RUNNING_LIST:
307 type = V1_AUTHORITY;
308 break;
309 case DIR_PURPOSE_FETCH_RENDDESC:
310 type = HIDSERV_AUTHORITY;
311 break;
312 case DIR_PURPOSE_FETCH_STATUS_VOTE:
313 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
314 type = V3_AUTHORITY;
315 break;
316 case DIR_PURPOSE_FETCH_CONSENSUS:
317 case DIR_PURPOSE_FETCH_CERTIFICATE:
318 type = V3_AUTHORITY;
319 break;
320 default:
321 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
322 return;
325 if (DIR_PURPOSE_FETCH_CONSENSUS) {
326 networkstatus_t *v = networkstatus_get_latest_consensus();
327 if (v)
328 if_modified_since = v->valid_after + 180;
331 if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
332 return;
334 if (!get_via_tor) {
335 if (options->UseBridges && type != BRIDGE_AUTHORITY) {
336 /* want to ask a running bridge for which we have a descriptor. */
337 /* XXX021 we assume that all of our bridges can answer any
338 * possible directory question. This won't be true forever. -RD */
339 routerinfo_t *ri = choose_random_entry(NULL);
340 if (ri) {
341 directory_initiate_command(ri->address, ri->addr,
342 ri->or_port, 0,
343 1, ri->cache_info.identity_digest,
344 dir_purpose,
345 router_purpose,
346 0, resource, NULL, 0, if_modified_since);
347 } else
348 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
349 "nodes are available yet.");
350 return;
351 } else {
352 if (prefer_authority || type == BRIDGE_AUTHORITY) {
353 /* only ask authdirservers, and don't ask myself */
354 rs = router_pick_trusteddirserver(type, flags);
356 if (!rs && type != BRIDGE_AUTHORITY) {
357 /* anybody with a non-zero dirport will do */
358 rs = router_pick_directory_server(type, flags);
359 if (!rs) {
360 log_info(LD_DIR, "No router found for %s; falling back to "
361 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
362 rs = router_pick_trusteddirserver(type, flags);
363 if (!rs)
364 get_via_tor = 1; /* last resort: try routing it via Tor */
368 } else { /* get_via_tor */
369 /* Never use fascistfirewall; we're going via Tor. */
370 if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
371 /* only ask hidserv authorities, any of them will do */
372 flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
373 rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, flags);
374 } else {
375 /* anybody with a non-zero dirport will do. Disregard firewalls. */
376 flags |= PDS_IGNORE_FASCISTFIREWALL;
377 rs = router_pick_directory_server(type, flags);
378 /* If we have any hope of building an indirect conn, we know some router
379 * descriptors. If (rs==NULL), we can't build circuits anyway, so
380 * there's no point in falling back to the authorities in this case. */
384 if (rs)
385 directory_initiate_command_routerstatus(rs, dir_purpose,
386 router_purpose,
387 get_via_tor,
388 resource, NULL, 0,
389 if_modified_since);
390 else {
391 log_notice(LD_DIR,
392 "While fetching directory info, "
393 "no running dirservers known. Will try again later. "
394 "(purpose %d)", dir_purpose);
395 if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
396 /* remember we tried them all and failed. */
397 directory_all_unreachable(time(NULL));
402 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
403 * directory authority other than ourself. Only for use by authorities when
404 * searching for missing information while voting. */
405 void
406 directory_get_from_all_authorities(uint8_t dir_purpose,
407 uint8_t router_purpose,
408 const char *resource)
410 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
411 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
413 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
414 trusted_dir_server_t *, ds,
416 routerstatus_t *rs;
417 if (router_digest_is_me(ds->digest))
418 continue;
419 if (!(ds->type & V3_AUTHORITY))
420 continue;
421 rs = &ds->fake_status;
422 directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
423 0, resource, NULL, 0, 0);
427 /** Launch a new connection to the directory server <b>status</b> to
428 * upload or download a server or rendezvous
429 * descriptor. <b>dir_purpose</b> determines what
430 * kind of directory connection we're launching, and must be one of
431 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC|RENDDESC_V2}. <b>router_purpose</b>
432 * specifies the descriptor purposes we have in mind (currently only
433 * used for FETCH_DIR).
435 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
436 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
438 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
439 * want to fetch.
441 void
442 directory_initiate_command_routerstatus(routerstatus_t *status,
443 uint8_t dir_purpose,
444 uint8_t router_purpose,
445 int anonymized_connection,
446 const char *resource,
447 const char *payload,
448 size_t payload_len,
449 time_t if_modified_since)
451 routerinfo_t *router;
452 char address_buf[INET_NTOA_BUF_LEN+1];
453 struct in_addr in;
454 const char *address;
455 if ((router = router_get_by_digest(status->identity_digest))) {
456 address = router->address;
457 } else {
458 in.s_addr = htonl(status->addr);
459 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
460 address = address_buf;
462 directory_initiate_command(address, status->addr,
463 status->or_port, status->dir_port,
464 status->version_supports_begindir,
465 status->identity_digest,
466 dir_purpose, router_purpose,
467 anonymized_connection, resource,
468 payload, payload_len, if_modified_since);
471 /** Return true iff <b>conn</b> is the client side of a directory connection
472 * we launched to ourself in order to determine the reachability of our
473 * dir_port. */
474 static int
475 directory_conn_is_self_reachability_test(dir_connection_t *conn)
477 if (conn->requested_resource &&
478 !strcmpstart(conn->requested_resource,"authority")) {
479 routerinfo_t *me = router_get_my_routerinfo();
480 if (me &&
481 router_digest_is_me(conn->identity_digest) &&
482 me->addr == conn->_base.addr &&
483 me->dir_port == conn->_base.port)
484 return 1;
486 return 0;
489 /** Called when we are unable to complete the client's request to a directory
490 * server due to a network error: Mark the router as down and try again if
491 * possible.
493 void
494 connection_dir_request_failed(dir_connection_t *conn)
496 if (directory_conn_is_self_reachability_test(conn)) {
497 routerinfo_t *me = router_get_my_routerinfo();
498 if (me)
499 control_event_server_status(LOG_WARN,
500 "REACHABILITY_FAILED DIRADDRESS=%s:%d",
501 me->address, me->dir_port);
502 return; /* this was a test fetch. don't retry. */
504 if (entry_list_can_grow(get_options()))
505 router_set_status(conn->identity_digest, 0); /* don't try him again */
506 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR ||
507 conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
508 log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
509 conn->_base.address, conn->_base.port);
510 directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose,
511 NULL, 0 /* don't retry_if_no_servers */);
512 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
513 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
514 conn->_base.address);
515 connection_dir_download_networkstatus_failed(conn, -1);
516 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
517 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
518 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
519 conn->_base.address);
520 connection_dir_download_routerdesc_failed(conn);
521 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
522 networkstatus_consensus_download_failed(0);
523 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
524 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
525 conn->_base.address);
526 connection_dir_download_cert_failed(conn, 0);
527 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
528 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
529 conn->_base.address);
530 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
531 log_info(LD_DIR, "Giving up downloading votes from '%s'",
532 conn->_base.address);
536 /** Called when an attempt to download one or more network status
537 * documents on connection <b>conn</b> failed. Decide whether to
538 * retry the fetch now, later, or never.
540 static void
541 connection_dir_download_networkstatus_failed(dir_connection_t *conn,
542 int status_code)
544 if (!conn->requested_resource) {
545 /* We never reached directory_send_command, which means that we never
546 * opened a network connection. Either we're out of sockets, or the
547 * network is down. Either way, retrying would be pointless. */
548 return;
550 if (!strcmpstart(conn->requested_resource, "all")) {
551 /* We're a non-authoritative directory cache; try again. Ignore status
552 * code, since we don't want to keep trying forever in a tight loop
553 * if all the authorities are shutting us out. */
554 smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
555 SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
556 download_status_failed(&ds->v2_ns_dl_status, 0));
557 directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose,
558 "all.z", 0 /* don't retry_if_no_servers */);
559 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
560 /* We were trying to download by fingerprint; mark them all as having
561 * failed, and possibly retry them later.*/
562 smartlist_t *failed = smartlist_create();
563 dir_split_resource_into_fingerprints(conn->requested_resource+3,
564 failed, NULL, 0, 0);
565 if (smartlist_len(failed)) {
566 dir_networkstatus_download_failed(failed, status_code);
567 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
569 smartlist_free(failed);
573 /** Called when an attempt to download one or more router descriptors
574 * or extra-info documents on connection <b>conn</b> failed.
576 static void
577 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
579 /* No need to increment the failure count for routerdescs, since
580 * it's not their fault. */
582 /* No need to relaunch descriptor downloads here: we already do it
583 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
584 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
585 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
587 (void) conn;
590 /** Called when an attempt to fetch a certificate fails. */
591 static void
592 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
594 smartlist_t *failed;
595 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
597 if (!conn->requested_resource)
598 return;
599 failed = smartlist_create();
600 dir_split_resource_into_fingerprints(conn->requested_resource+3,
601 failed, NULL, 1, 0);
602 SMARTLIST_FOREACH(failed, char *, cp,
604 authority_cert_dl_failed(cp, status);
605 tor_free(cp);
607 smartlist_free(failed);
609 update_certificate_downloads(time(NULL));
612 /** Helper for directory_initiate_command_routerstatus: send the
613 * command to a server whose address is <b>address</b>, whose IP is
614 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
615 * <b>supports_begindir</b>, and whose identity key digest is
616 * <b>digest</b>. */
617 void
618 directory_initiate_command(const char *address, uint32_t addr,
619 uint16_t or_port, uint16_t dir_port,
620 int supports_begindir, const char *digest,
621 uint8_t dir_purpose, uint8_t router_purpose,
622 int anonymized_connection, const char *resource,
623 const char *payload, size_t payload_len,
624 time_t if_modified_since)
626 dir_connection_t *conn;
627 or_options_t *options = get_options();
628 int use_begindir = supports_begindir && or_port &&
629 (options->TunnelDirConns ||
630 router_purpose == ROUTER_PURPOSE_BRIDGE) &&
631 (anonymized_connection ||
632 fascist_firewall_allows_address_or(addr, or_port));
634 tor_assert(address);
635 tor_assert(addr);
636 tor_assert(or_port || dir_port);
637 tor_assert(digest);
639 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
640 anonymized_connection, use_begindir);
642 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
644 conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
646 /* set up conn so it's got all the data we need to remember */
647 conn->_base.addr = addr;
648 conn->_base.port = use_begindir ? or_port : dir_port;
649 conn->_base.address = tor_strdup(address);
650 memcpy(conn->identity_digest, digest, DIGEST_LEN);
652 conn->_base.purpose = dir_purpose;
653 conn->router_purpose = router_purpose;
655 /* give it an initial state */
656 conn->_base.state = DIR_CONN_STATE_CONNECTING;
658 /* decide whether we can learn our IP address from this conn */
659 conn->dirconn_direct = !anonymized_connection;
661 if (!anonymized_connection && !use_begindir) {
662 /* then we want to connect to dirport directly */
664 if (options->HttpProxy) {
665 addr = options->HttpProxyAddr;
666 dir_port = options->HttpProxyPort;
669 switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
670 dir_port)) {
671 case -1:
672 connection_dir_request_failed(conn); /* retry if we want */
673 /* XXX we only pass 'conn' above, not 'resource', 'payload',
674 * etc. So in many situations it can't retry! -RD */
675 connection_free(TO_CONN(conn));
676 return;
677 case 1:
678 /* start flushing conn */
679 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
680 /* fall through */
681 case 0:
682 /* queue the command on the outbuf */
683 directory_send_command(conn, dir_purpose, 1, resource,
684 payload, payload_len, if_modified_since);
685 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
686 /* writable indicates finish, readable indicates broken link,
687 error indicates broken link in windowsland. */
689 } else { /* we want to connect via a tor connection */
690 edge_connection_t *linked_conn;
691 /* make an AP connection
692 * populate it and add it at the right state
693 * hook up both sides
695 linked_conn =
696 connection_ap_make_link(conn->_base.address, conn->_base.port,
697 digest, use_begindir, conn->dirconn_direct);
698 if (!linked_conn) {
699 log_warn(LD_NET,"Making tunnel to dirserver failed.");
700 connection_mark_for_close(TO_CONN(conn));
701 return;
703 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
705 if (connection_add(TO_CONN(conn)) < 0) {
706 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
707 connection_mark_for_close(TO_CONN(conn));
708 return;
710 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
711 /* queue the command on the outbuf */
712 directory_send_command(conn, dir_purpose, 0, resource,
713 payload, payload_len, if_modified_since);
714 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
715 connection_start_reading(TO_CONN(linked_conn));
719 /** Return true iff anything we say on <b>conn</b> is being encrypted before
720 * we send it to the client/server. */
722 connection_dir_is_encrypted(dir_connection_t *conn)
724 /* Right now it's sufficient to see if conn is or has been linked, since
725 * the only thing it could be linked to is an edge connection on a
726 * circuit, and the only way it could have been unlinked is at the edge
727 * connection getting closed.
729 return TO_CONN(conn)->linked;
732 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
733 * are as in directory_initiate_command.
735 static void
736 directory_send_command(dir_connection_t *conn,
737 int purpose, int direct, const char *resource,
738 const char *payload, size_t payload_len,
739 time_t if_modified_since)
741 char proxystring[256];
742 char proxyauthstring[256];
743 char hoststring[128];
744 char imsstring[RFC1123_TIME_LEN+32];
745 char *url;
746 char request[8192];
747 const char *httpcommand = NULL;
748 size_t len;
750 tor_assert(conn);
751 tor_assert(conn->_base.type == CONN_TYPE_DIR);
753 tor_free(conn->requested_resource);
754 if (resource)
755 conn->requested_resource = tor_strdup(resource);
757 /* come up with a string for which Host: we want */
758 if (conn->_base.port == 80) {
759 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
760 } else {
761 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
762 conn->_base.address, conn->_base.port);
765 /* Format if-modified-since */
766 if (!if_modified_since) {
767 imsstring[0] = '\0';
768 } else {
769 char b[RFC1123_TIME_LEN+1];
770 format_rfc1123_time(b, if_modified_since);
771 tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
774 /* come up with some proxy lines, if we're using one. */
775 if (direct && get_options()->HttpProxy) {
776 char *base64_authenticator=NULL;
777 const char *authenticator = get_options()->HttpProxyAuthenticator;
779 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
780 if (authenticator) {
781 base64_authenticator = alloc_http_authenticator(authenticator);
782 if (!base64_authenticator)
783 log_warn(LD_BUG, "Encoding http authenticator failed");
785 if (base64_authenticator) {
786 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
787 "\r\nProxy-Authorization: Basic %s",
788 base64_authenticator);
789 tor_free(base64_authenticator);
790 } else {
791 proxyauthstring[0] = 0;
793 } else {
794 proxystring[0] = 0;
795 proxyauthstring[0] = 0;
798 switch (purpose) {
799 case DIR_PURPOSE_FETCH_DIR:
800 tor_assert(!resource);
801 tor_assert(!payload);
802 httpcommand = "GET";
803 url = tor_strdup("/tor/dir.z");
804 break;
805 case DIR_PURPOSE_FETCH_RUNNING_LIST:
806 tor_assert(!resource);
807 tor_assert(!payload);
808 httpcommand = "GET";
809 url = tor_strdup("/tor/running-routers");
810 break;
811 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
812 httpcommand = "GET";
813 len = strlen(resource)+32;
814 url = tor_malloc(len);
815 tor_snprintf(url, len, "/tor/status/%s", resource);
816 break;
817 case DIR_PURPOSE_FETCH_CONSENSUS:
818 tor_assert(!resource);
819 tor_assert(!payload);
820 httpcommand = "GET";
821 url = tor_strdup("/tor/status-vote/current/consensus.z");
822 break;
823 case DIR_PURPOSE_FETCH_CERTIFICATE:
824 tor_assert(resource);
825 tor_assert(!payload);
826 httpcommand = "GET";
827 len = strlen(resource)+32;
828 url = tor_malloc(len);
829 tor_snprintf(url, len, "/tor/keys/%s", resource);
830 break;
831 case DIR_PURPOSE_FETCH_STATUS_VOTE:
832 tor_assert(resource);
833 tor_assert(!payload);
834 httpcommand = "GET";
835 len = strlen(resource)+32;
836 url = tor_malloc(len);
837 tor_snprintf(url, len, "/tor/status-vote/next/%s.z", resource);
838 break;
839 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
840 tor_assert(!resource);
841 tor_assert(!payload);
842 httpcommand = "GET";
843 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
844 break;
845 case DIR_PURPOSE_FETCH_SERVERDESC:
846 httpcommand = "GET";
847 len = strlen(resource)+32;
848 url = tor_malloc(len);
849 tor_snprintf(url, len, "/tor/server/%s", resource);
850 break;
851 case DIR_PURPOSE_FETCH_EXTRAINFO:
852 httpcommand = "GET";
853 len = strlen(resource)+32;
854 url = tor_malloc(len);
855 tor_snprintf(url, len, "/tor/extra/%s", resource);
856 break;
857 case DIR_PURPOSE_UPLOAD_DIR:
858 tor_assert(!resource);
859 tor_assert(payload);
860 httpcommand = "POST";
861 url = tor_strdup("/tor/");
862 break;
863 case DIR_PURPOSE_UPLOAD_VOTE:
864 tor_assert(!resource);
865 tor_assert(payload);
866 httpcommand = "POST";
867 url = tor_strdup("/tor/post/vote");
868 break;
869 case DIR_PURPOSE_UPLOAD_SIGNATURES:
870 tor_assert(!resource);
871 tor_assert(payload);
872 httpcommand = "POST";
873 url = tor_strdup("/tor/post/consensus-signature");
874 break;
875 case DIR_PURPOSE_FETCH_RENDDESC:
876 tor_assert(resource);
877 tor_assert(!payload);
879 /* this must be true or we wouldn't be doing the lookup */
880 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN_BASE32);
881 /* This breaks the function abstraction. */
882 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
884 httpcommand = "GET";
885 /* Request the most recent versioned descriptor. */
886 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
887 // but that never got testing, and it wasn't a good design.)
888 len = strlen(resource)+32;
889 url = tor_malloc(len);
890 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
891 break;
892 case DIR_PURPOSE_FETCH_RENDDESC_V2:
893 tor_assert(resource);
894 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
895 /* Remember the query to refer to it when a response arrives. */
896 strlcpy(conn->rend_query, payload, sizeof(conn->rend_query));
897 payload = NULL;
898 httpcommand = "GET";
899 len = strlen(resource) + 32;
900 url = tor_malloc(len);
901 tor_snprintf(url, len, "/tor/rendezvous2/%s", resource);
902 break;
903 case DIR_PURPOSE_UPLOAD_RENDDESC:
904 tor_assert(!resource);
905 tor_assert(payload);
906 httpcommand = "POST";
907 url = tor_strdup("/tor/rendezvous/publish");
908 break;
909 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
910 tor_assert(!resource);
911 tor_assert(payload);
912 httpcommand = "POST";
913 url = tor_strdup("/tor/rendezvous2/publish");
914 break;
915 default:
916 tor_assert(0);
917 return;
920 if (strlen(proxystring) + strlen(url) >= 4096) {
921 log_warn(LD_BUG,
922 "Squid does not like URLs longer than 4095 bytes, and this "
923 "one is %d bytes long: %s%s",
924 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
927 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
928 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
929 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
930 tor_free(url);
932 if (!strcmp(httpcommand, "GET") && !payload) {
933 tor_snprintf(request, sizeof(request),
934 " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
935 hoststring,
936 imsstring,
937 proxyauthstring);
938 } else {
939 tor_snprintf(request, sizeof(request),
940 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
941 payload ? (unsigned long)payload_len : 0,
942 hoststring,
943 imsstring,
944 proxyauthstring);
946 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
948 if (payload) {
949 /* then send the payload afterwards too */
950 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
954 /** Parse an HTTP request string <b>headers</b> of the form
955 * \verbatim
956 * "\%s [http[s]://]\%s HTTP/1..."
957 * \endverbatim
958 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
959 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
960 * so it does. Return 0.
961 * Otherwise, return -1.
963 static int
964 parse_http_url(const char *headers, char **url)
966 char *s, *start, *tmp;
968 s = (char *)eat_whitespace_no_nl(headers);
969 if (!*s) return -1;
970 s = (char *)find_whitespace(s); /* get past GET/POST */
971 if (!*s) return -1;
972 s = (char *)eat_whitespace_no_nl(s);
973 if (!*s) return -1;
974 start = s; /* this is it, assuming it's valid */
975 s = (char *)find_whitespace(start);
976 if (!*s) return -1;
978 /* tolerate the http[s] proxy style of putting the hostname in the url */
979 if (s-start >= 4 && !strcmpstart(start,"http")) {
980 tmp = start + 4;
981 if (*tmp == 's')
982 tmp++;
983 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
984 tmp = strchr(tmp+3, '/');
985 if (tmp && tmp < s) {
986 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
987 start = tmp;
992 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
993 *url = tor_malloc(s - start + 5);
994 strlcpy(*url,"/tor", s-start+5);
995 strlcat((*url)+4, start, s-start+1);
996 } else {
997 *url = tor_strndup(start, s-start);
999 return 0;
1002 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1003 * <b>which</b>. The key should be given with a terminating colon and space;
1004 * this function copies everything after, up to but not including the
1005 * following \\r\\n. */
1006 static char *
1007 http_get_header(const char *headers, const char *which)
1009 const char *cp = headers;
1010 while (cp) {
1011 if (!strcasecmpstart(cp, which)) {
1012 char *eos;
1013 cp += strlen(which);
1014 if ((eos = strchr(cp,'\r')))
1015 return tor_strndup(cp, eos-cp);
1016 else
1017 return tor_strdup(cp);
1019 cp = strchr(cp, '\n');
1020 if (cp)
1021 ++cp;
1023 return NULL;
1026 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1027 * <b>conn</b>-\>address to describe our best guess of the address that
1028 * originated this HTTP request. */
1029 static void
1030 http_set_address_origin(const char *headers, connection_t *conn)
1032 char *fwd;
1034 fwd = http_get_header(headers, "Forwarded-For: ");
1035 if (!fwd)
1036 fwd = http_get_header(headers, "X-Forwarded-For: ");
1037 if (fwd) {
1038 struct in_addr in;
1039 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
1040 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
1041 escaped(fwd));
1042 tor_free(fwd);
1043 return;
1045 tor_free(conn->address);
1046 conn->address = tor_strdup(fwd);
1047 tor_free(fwd);
1051 /** Parse an HTTP response string <b>headers</b> of the form
1052 * \verbatim
1053 * "HTTP/1.\%d \%d\%s\r\n...".
1054 * \endverbatim
1056 * If it's well-formed, assign the status code to *<b>code</b> and
1057 * return 0. Otherwise, return -1.
1059 * On success: If <b>date</b> is provided, set *date to the Date
1060 * header in the http headers, or 0 if no such header is found. If
1061 * <b>compression</b> is provided, set *<b>compression</b> to the
1062 * compression method given in the Content-Encoding header, or 0 if no
1063 * such header is found, or -1 if the value of the header is not
1064 * recognized. If <b>reason</b> is provided, strdup the reason string
1065 * into it.
1068 parse_http_response(const char *headers, int *code, time_t *date,
1069 compress_method_t *compression, char **reason)
1071 int n1, n2;
1072 char datestr[RFC1123_TIME_LEN+1];
1073 smartlist_t *parsed_headers;
1074 tor_assert(headers);
1075 tor_assert(code);
1077 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1079 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
1080 (n1 != 0 && n1 != 1) ||
1081 (n2 < 100 || n2 >= 600)) {
1082 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1083 return -1;
1085 *code = n2;
1087 parsed_headers = smartlist_create();
1088 smartlist_split_string(parsed_headers, headers, "\n",
1089 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1090 if (reason) {
1091 smartlist_t *status_line_elements = smartlist_create();
1092 tor_assert(smartlist_len(parsed_headers));
1093 smartlist_split_string(status_line_elements,
1094 smartlist_get(parsed_headers, 0),
1095 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1096 tor_assert(smartlist_len(status_line_elements) <= 3);
1097 if (smartlist_len(status_line_elements) == 3) {
1098 *reason = smartlist_get(status_line_elements, 2);
1099 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1101 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1102 smartlist_free(status_line_elements);
1104 if (date) {
1105 *date = 0;
1106 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1107 if (!strcmpstart(s, "Date: ")) {
1108 strlcpy(datestr, s+6, sizeof(datestr));
1109 /* This will do nothing on failure, so we don't need to check
1110 the result. We shouldn't warn, since there are many other valid
1111 date formats besides the one we use. */
1112 parse_rfc1123_time(datestr, date);
1113 break;
1116 if (compression) {
1117 const char *enc = NULL;
1118 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1119 if (!strcmpstart(s, "Content-Encoding: ")) {
1120 enc = s+18; break;
1122 if (!enc || !strcmp(enc, "identity")) {
1123 *compression = NO_METHOD;
1124 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1125 *compression = ZLIB_METHOD;
1126 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1127 *compression = GZIP_METHOD;
1128 } else {
1129 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1130 escaped(enc));
1131 *compression = UNKNOWN_METHOD;
1134 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1135 smartlist_free(parsed_headers);
1137 return 0;
1140 /** Return true iff <b>body</b> doesn't start with a plausible router or
1141 * running-list or directory opening. This is a sign of possible compression.
1143 static int
1144 body_is_plausible(const char *body, size_t len, int purpose)
1146 int i;
1147 if (len == 0)
1148 return 1; /* empty bodies don't need decompression */
1149 if (len < 32)
1150 return 0;
1151 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
1152 if (!strcmpstart(body,"router") ||
1153 !strcmpstart(body,"signed-directory") ||
1154 !strcmpstart(body,"network-status") ||
1155 !strcmpstart(body,"running-routers"))
1156 return 1;
1157 for (i=0;i<32;++i) {
1158 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1159 return 0;
1161 return 1;
1162 } else {
1163 return 1;
1167 /** Called when we've just fetched a bunch of router descriptors in
1168 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1169 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1170 * is true, or identity digests otherwise. Parse the descriptors, validate
1171 * them, and annotate them as having purpose <b>purpose</b> and as having been
1172 * downloaded from <b>source</b>. */
1173 static void
1174 load_downloaded_routers(const char *body, smartlist_t *which,
1175 int descriptor_digests,
1176 int router_purpose,
1177 const char *source)
1179 char buf[256];
1180 char time_buf[ISO_TIME_LEN+1];
1181 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1182 format_iso_time(time_buf, time(NULL));
1183 tor_assert(source);
1185 if (tor_snprintf(buf, sizeof(buf),
1186 "@downloaded-at %s\n"
1187 "@source %s\n"
1188 "%s%s%s", time_buf, escaped(source),
1189 !general ? "@purpose " : "",
1190 !general ? router_purpose_to_string(router_purpose) : "",
1191 !general ? "\n" : "")<0)
1192 return;
1194 router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1195 descriptor_digests, buf);
1198 /** We are a client, and we've finished reading the server's
1199 * response. Parse it and act appropriately.
1201 * If we're still happy with using this directory server in the future, return
1202 * 0. Otherwise return -1; and the caller should consider trying the request
1203 * again.
1205 * The caller will take care of marking the connection for close.
1207 static int
1208 connection_dir_client_reached_eof(dir_connection_t *conn)
1210 char *body;
1211 char *headers;
1212 char *reason = NULL;
1213 size_t body_len=0, orig_len=0;
1214 int status_code;
1215 time_t date_header=0;
1216 int delta;
1217 compress_method_t compression;
1218 int plausible;
1219 int skewed=0;
1220 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1221 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
1222 int was_compressed=0;
1223 time_t now = time(NULL);
1225 switch (fetch_from_buf_http(conn->_base.inbuf,
1226 &headers, MAX_HEADERS_SIZE,
1227 &body, &body_len, MAX_DIR_DL_SIZE,
1228 allow_partial)) {
1229 case -1: /* overflow */
1230 log_warn(LD_PROTOCOL,
1231 "'fetch' response too large (server '%s:%d'). Closing.",
1232 conn->_base.address, conn->_base.port);
1233 return -1;
1234 case 0:
1235 log_info(LD_HTTP,
1236 "'fetch' response not all here, but we're at eof. Closing.");
1237 return -1;
1238 /* case 1, fall through */
1240 orig_len = body_len;
1242 if (parse_http_response(headers, &status_code, &date_header,
1243 &compression, &reason) < 0) {
1244 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1245 conn->_base.address, conn->_base.port);
1246 tor_free(body); tor_free(headers);
1247 return -1;
1249 if (!reason) reason = tor_strdup("[no reason given]");
1251 log_debug(LD_DIR,
1252 "Received response from directory server '%s:%d': %d %s",
1253 conn->_base.address, conn->_base.port, status_code,
1254 escaped(reason));
1256 /* now check if it's got any hints for us about our IP address. */
1257 if (conn->dirconn_direct) {
1258 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1259 if (guess) {
1260 router_new_address_suggestion(guess, conn);
1261 tor_free(guess);
1265 if (date_header > 0) {
1266 /* The date header was written very soon after we sent our request,
1267 * so compute the skew as the difference between sending the request
1268 * and the date header. (We used to check now-date_header, but that's
1269 * inaccurate if we spend a lot of time downloading.)
1271 delta = conn->_base.timestamp_lastwritten - date_header;
1272 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1273 char dbuf[64];
1274 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1275 format_time_interval(dbuf, sizeof(dbuf), delta);
1276 log_fn(trusted ? LOG_WARN : LOG_INFO,
1277 LD_HTTP,
1278 "Received directory with skewed time (server '%s:%d'): "
1279 "It seems that our clock is %s by %s, or that theirs is %s. "
1280 "Tor requires an accurate clock to work: please check your time "
1281 "and date settings.",
1282 conn->_base.address, conn->_base.port,
1283 delta>0 ? "ahead" : "behind", dbuf,
1284 delta>0 ? "behind" : "ahead");
1285 skewed = 1; /* don't check the recommended-versions line */
1286 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1287 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
1288 delta, conn->_base.address, conn->_base.port);
1289 } else {
1290 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1291 "we are %d seconds skewed. (That's okay.)", delta);
1294 (void) skewed; /* skewed isn't used yet. */
1296 if (status_code == 503 && body_len < 16) {
1297 routerstatus_t *rs;
1298 trusted_dir_server_t *ds;
1299 log_info(LD_DIR,"Received http status code %d (%s) from server "
1300 "'%s:%d'. I'll try again soon.",
1301 status_code, escaped(reason), conn->_base.address,
1302 conn->_base.port);
1303 if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
1304 rs->last_dir_503_at = now;
1305 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1306 ds->fake_status.last_dir_503_at = now;
1308 tor_free(body); tor_free(headers); tor_free(reason);
1309 return -1;
1310 } else if (status_code == 503) {
1311 /* XXXX022 Remove this once every server with bug 539 is obsolete. */
1312 log_info(LD_DIR, "Server at '%s:%d' sent us a 503 response, but included "
1313 "a body anyway. We'll pretend it gave us a 200.",
1314 conn->_base.address, conn->_base.port);
1315 status_code = 200;
1318 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1319 if (compression != NO_METHOD || !plausible) {
1320 char *new_body = NULL;
1321 size_t new_len = 0;
1322 compress_method_t guessed = detect_compression_method(body, body_len);
1323 if (compression == UNKNOWN_METHOD || guessed != compression) {
1324 /* Tell the user if we don't believe what we're told about compression.*/
1325 const char *description1, *description2;
1326 if (compression == ZLIB_METHOD)
1327 description1 = "as deflated";
1328 else if (compression == GZIP_METHOD)
1329 description1 = "as gzipped";
1330 else if (compression == NO_METHOD)
1331 description1 = "as uncompressed";
1332 else
1333 description1 = "with an unknown Content-Encoding";
1334 if (guessed == ZLIB_METHOD)
1335 description2 = "deflated";
1336 else if (guessed == GZIP_METHOD)
1337 description2 = "gzipped";
1338 else if (!plausible)
1339 description2 = "confusing binary junk";
1340 else
1341 description2 = "uncompressed";
1343 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1344 "but it seems to be %s.%s",
1345 conn->_base.address, conn->_base.port, description1,
1346 description2,
1347 (compression>0 && guessed>0)?" Trying both.":"");
1349 /* Try declared compression first if we can. */
1350 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1351 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1352 !allow_partial, LOG_PROTOCOL_WARN);
1353 /* Okay, if that didn't work, and we think that it was compressed
1354 * differently, try that. */
1355 if (!new_body &&
1356 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1357 compression != guessed)
1358 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1359 !allow_partial, LOG_PROTOCOL_WARN);
1360 /* If we're pretty sure that we have a compressed directory, and
1361 * we didn't manage to uncompress it, then warn and bail. */
1362 if (!plausible && !new_body) {
1363 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1364 "Unable to decompress HTTP body (server '%s:%d').",
1365 conn->_base.address, conn->_base.port);
1366 tor_free(body); tor_free(headers); tor_free(reason);
1367 return -1;
1369 if (new_body) {
1370 tor_free(body);
1371 body = new_body;
1372 body_len = new_len;
1373 was_compressed = 1;
1377 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
1378 /* fetch/process the directory to cache it. */
1379 log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
1380 (int)body_len, conn->_base.address, conn->_base.port);
1381 if (status_code != 200) {
1382 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1383 "'%s:%d' while fetching directory. I'll try again soon.",
1384 status_code, escaped(reason), conn->_base.address,
1385 conn->_base.port);
1386 tor_free(body); tor_free(headers); tor_free(reason);
1387 return -1;
1389 if (router_parse_directory(body) < 0) {
1390 log_notice(LD_DIR,"I failed to parse the directory I fetched from "
1391 "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
1393 note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
1396 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
1397 /* just update our list of running routers, if this list is new info */
1398 log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
1399 if (status_code != 200) {
1400 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1401 "'%s:%d' while fetching running-routers. I'll try again soon.",
1402 status_code, escaped(reason), conn->_base.address,
1403 conn->_base.port);
1404 tor_free(body); tor_free(headers); tor_free(reason);
1405 return -1;
1407 if (router_parse_runningrouters(body)<0) {
1408 log_warn(LD_DIR,
1409 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1410 conn->_base.address, conn->_base.port);
1411 tor_free(body); tor_free(headers); tor_free(reason);
1412 return -1;
1414 note_request(was_compressed?"dl/running-routers.z":
1415 "dl/running-routers", orig_len);
1418 if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
1419 smartlist_t *which = NULL;
1420 networkstatus_source_t source;
1421 char *cp;
1422 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1423 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1424 if (status_code != 200) {
1425 log_warn(LD_DIR,
1426 "Received http status code %d (%s) from server "
1427 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1428 status_code, escaped(reason), conn->_base.address,
1429 conn->_base.port, conn->requested_resource);
1430 tor_free(body); tor_free(headers); tor_free(reason);
1431 connection_dir_download_networkstatus_failed(conn, status_code);
1432 return -1;
1434 note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
1435 if (conn->requested_resource &&
1436 !strcmpstart(conn->requested_resource,"fp/")) {
1437 source = NS_FROM_DIR_BY_FP;
1438 which = smartlist_create();
1439 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1440 which, NULL, 0, 0);
1441 } else if (conn->requested_resource &&
1442 !strcmpstart(conn->requested_resource, "all")) {
1443 source = NS_FROM_DIR_ALL;
1444 which = smartlist_create();
1445 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1446 trusted_dir_server_t *, ds,
1448 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1449 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1450 smartlist_add(which, hex);
1452 } else {
1453 /* XXXX Can we even end up here? -- weasel*/
1454 source = NS_FROM_DIR_BY_FP;
1455 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1456 "for it by fp, nor did we ask for all.");
1458 cp = body;
1459 while (*cp) {
1460 char *next = strstr(cp, "\nnetwork-status-version");
1461 if (next)
1462 next[1] = '\0';
1463 /* learn from it, and then remove it from 'which' */
1464 if (router_set_networkstatus_v2(cp, now, source, which)<0)
1465 break;
1466 if (next) {
1467 next[1] = 'n';
1468 cp = next+1;
1469 } else
1470 break;
1472 /* launches router downloads as needed */
1473 routers_update_all_from_networkstatus(now, 2);
1474 directory_info_has_arrived(now, 0);
1475 if (which) {
1476 if (smartlist_len(which)) {
1477 dir_networkstatus_download_failed(which, status_code);
1479 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1480 smartlist_free(which);
1484 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1485 int r;
1486 if (status_code != 200) {
1487 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1488 log(severity, LD_DIR,
1489 "Received http status code %d (%s) from server "
1490 "'%s:%d' while fetching consensus directory.",
1491 status_code, escaped(reason), conn->_base.address,
1492 conn->_base.port);
1493 tor_free(body); tor_free(headers); tor_free(reason);
1494 networkstatus_consensus_download_failed(status_code);
1495 return -1;
1497 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1498 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1499 if ((r=networkstatus_set_current_consensus(body, 0))<0) {
1500 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1501 "Unable to load consensus directory downloaded from "
1502 "server '%s:%d'", conn->_base.address, conn->_base.port);
1503 tor_free(body); tor_free(headers); tor_free(reason);
1504 networkstatus_consensus_download_failed(0);
1505 return -1;
1507 /* launches router downloads as needed */
1508 routers_update_all_from_networkstatus(now, 3);
1509 directory_info_has_arrived(now, 0);
1510 log_info(LD_DIR, "Successfully loaded consensus.");
1513 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1514 if (status_code != 200) {
1515 log_warn(LD_DIR,
1516 "Received http status code %d (%s) from server "
1517 "'%s:%d' while fetching \"/tor/keys/%s\".",
1518 status_code, escaped(reason), conn->_base.address,
1519 conn->_base.port, conn->requested_resource);
1520 connection_dir_download_cert_failed(conn, status_code);
1521 tor_free(body); tor_free(headers); tor_free(reason);
1522 return -1;
1524 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1525 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1526 if (trusted_dirs_load_certs_from_string(body, 0)<0) {
1527 log_warn(LD_DIR, "Unable to parse fetched certificates");
1528 connection_dir_download_cert_failed(conn, status_code);
1529 } else {
1530 directory_info_has_arrived(now, 0);
1531 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1534 if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1535 const char *msg;
1536 int st;
1537 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1538 (int) body_len, conn->_base.address, conn->_base.port);
1539 if (status_code != 200) {
1540 log_warn(LD_DIR,
1541 "Received http status code %d (%s) from server "
1542 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1543 status_code, escaped(reason), conn->_base.address,
1544 conn->_base.port, conn->requested_resource);
1545 tor_free(body); tor_free(headers); tor_free(reason);
1546 return -1;
1548 dirvote_add_vote(body, &msg, &st);
1549 if (st > 299) {
1550 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1551 } else {
1552 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1555 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1556 const char *msg = NULL;
1557 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1558 (int) body_len, conn->_base.address, conn->_base.port);
1559 if (status_code != 200) {
1560 log_warn(LD_DIR,
1561 "Received http status code %d (%s) from server "
1562 "'%s:%d' while fetching \"/tor/status-vote/consensus-signatures.z\".",
1563 status_code, escaped(reason), conn->_base.address,
1564 conn->_base.port);
1565 tor_free(body); tor_free(headers); tor_free(reason);
1566 return -1;
1568 if (dirvote_add_signatures(body, conn->_base.address, &msg)<0) {
1569 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1570 conn->_base.address, conn->_base.port, msg?msg:"???");
1574 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1575 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1576 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1577 smartlist_t *which = NULL;
1578 int n_asked_for = 0;
1579 int descriptor_digests = conn->requested_resource &&
1580 !strcmpstart(conn->requested_resource,"d/");
1581 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1582 was_ei ? "extra server info" : "server info",
1583 (int)body_len, conn->_base.address, conn->_base.port);
1584 if (was_ei)
1585 note_request(was_compressed?"dl/extra.z":"dl/extra", orig_len);
1586 else
1587 note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
1588 if (conn->requested_resource &&
1589 (!strcmpstart(conn->requested_resource,"d/") ||
1590 !strcmpstart(conn->requested_resource,"fp/"))) {
1591 which = smartlist_create();
1592 dir_split_resource_into_fingerprints(conn->requested_resource +
1593 (descriptor_digests ? 2 : 3),
1594 which, NULL, 0, 0);
1595 n_asked_for = smartlist_len(which);
1597 if (status_code != 200) {
1598 int dir_okay = status_code == 404 ||
1599 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1600 /* 404 means that it didn't have them; no big deal.
1601 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1602 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1603 "Received http status code %d (%s) from server '%s:%d' "
1604 "while fetching \"/tor/server/%s\". I'll try again soon.",
1605 status_code, escaped(reason), conn->_base.address,
1606 conn->_base.port, conn->requested_resource);
1607 if (!which) {
1608 connection_dir_download_routerdesc_failed(conn);
1609 } else {
1610 dir_routerdesc_download_failed(which, status_code,
1611 conn->router_purpose,
1612 was_ei, descriptor_digests);
1613 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1614 smartlist_free(which);
1616 tor_free(body); tor_free(headers); tor_free(reason);
1617 return dir_okay ? 0 : -1;
1619 /* Learn the routers, assuming we requested by fingerprint or "all"
1620 * or "authority".
1622 * We use "authority" to fetch our own descriptor for
1623 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1624 * the output of "authority" requests unless we are using bridges,
1625 * since otherwise they'll be the response from reachability tests,
1626 * and we don't really want to add that to our routerlist. */
1627 if (which || (conn->requested_resource &&
1628 (!strcmpstart(conn->requested_resource, "all") ||
1629 (!strcmpstart(conn->requested_resource, "authority") &&
1630 get_options()->UseBridges)))) {
1631 /* as we learn from them, we remove them from 'which' */
1632 if (was_ei) {
1633 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1634 descriptor_digests);
1635 } else {
1636 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1637 // descriptor_digests, conn->router_purpose);
1638 load_downloaded_routers(body, which, descriptor_digests,
1639 conn->router_purpose,
1640 conn->_base.address);
1641 directory_info_has_arrived(now, 0);
1644 if (which) { /* mark remaining ones as failed */
1645 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1646 n_asked_for-smartlist_len(which), n_asked_for,
1647 was_ei ? "extra-info documents" : "router descriptors",
1648 conn->_base.address, (int)conn->_base.port);
1649 if (smartlist_len(which)) {
1650 dir_routerdesc_download_failed(which, status_code,
1651 conn->router_purpose,
1652 was_ei, descriptor_digests);
1654 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1655 smartlist_free(which);
1657 if (directory_conn_is_self_reachability_test(conn))
1658 router_dirport_found_reachable();
1661 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1662 switch (status_code) {
1663 case 200: {
1664 trusted_dir_server_t *ds =
1665 router_get_trusteddirserver_by_digest(conn->identity_digest);
1666 char *rejected_hdr = http_get_header(headers,
1667 "X-Descriptor-Not-New: ");
1668 int rejected = 0;
1669 if (rejected_hdr) {
1670 if (!strcmp(rejected_hdr, "Yes")) {
1671 /* XXXX020 use this information; be sure to upload next one
1672 * sooner. */
1673 rejected = 1;
1675 tor_free(rejected_hdr);
1677 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1678 "descriptor: finished.");
1679 control_event_server_status(
1680 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1681 conn->_base.address, conn->_base.port);
1683 ds->has_accepted_serverdesc = 1;
1684 if (directories_have_accepted_server_descriptor())
1685 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1687 break;
1688 case 400:
1689 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1690 "dirserver '%s:%d'. Please correct.",
1691 escaped(reason), conn->_base.address, conn->_base.port);
1692 control_event_server_status(LOG_WARN,
1693 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1694 conn->_base.address, conn->_base.port, escaped(reason));
1695 break;
1696 default:
1697 log_warn(LD_GENERAL,
1698 "http status %d (%s) reason unexpected while uploading "
1699 "descriptor to server '%s:%d').",
1700 status_code, escaped(reason), conn->_base.address,
1701 conn->_base.port);
1702 break;
1704 /* return 0 in all cases, since we don't want to mark any
1705 * dirservers down just because they don't like us. */
1708 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
1709 switch (status_code) {
1710 case 200: {
1711 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
1712 conn->_base.address, conn->_base.port);
1714 break;
1715 case 400:
1716 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1717 "vote to dirserver '%s:%d'. Please correct.",
1718 escaped(reason), conn->_base.address, conn->_base.port);
1719 break;
1720 default:
1721 log_warn(LD_GENERAL,
1722 "http status %d (%s) reason unexpected while uploading "
1723 "vote to server '%s:%d').",
1724 status_code, escaped(reason), conn->_base.address,
1725 conn->_base.port);
1726 break;
1728 /* return 0 in all cases, since we don't want to mark any
1729 * dirservers down just because they don't like us. */
1732 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
1733 switch (status_code) {
1734 case 200: {
1735 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
1736 conn->_base.address, conn->_base.port);
1738 break;
1739 case 400:
1740 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1741 "signatures to dirserver '%s:%d'. Please correct.",
1742 escaped(reason), conn->_base.address, conn->_base.port);
1743 break;
1744 default:
1745 log_warn(LD_GENERAL,
1746 "http status %d (%s) reason unexpected while uploading "
1747 "signatures to server '%s:%d').",
1748 status_code, escaped(reason), conn->_base.address,
1749 conn->_base.port);
1750 break;
1752 /* return 0 in all cases, since we don't want to mark any
1753 * dirservers down just because they don't like us. */
1756 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1757 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1758 "(%s))",
1759 (int)body_len, status_code, escaped(reason));
1760 switch (status_code) {
1761 case 200:
1762 if (rend_cache_store(body, body_len, 0) < 0) {
1763 log_warn(LD_REND,"Failed to fetch rendezvous descriptor.");
1764 /* Any pending rendezvous attempts will notice when
1765 * connection_about_to_close_connection()
1766 * cleans this dir conn up. */
1767 /* We could retry. But since v0 descriptors are going out of
1768 * style, it isn't worth the hassle. We'll do better in v2. */
1769 } else {
1770 /* success. notify pending connections about this. */
1771 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1772 rend_client_desc_here(conn->rend_query);
1774 break;
1775 case 404:
1776 /* Not there. Pending connections will be notified when
1777 * connection_about_to_close_connection() cleans this conn up. */
1778 break;
1779 case 400:
1780 log_warn(LD_REND,
1781 "http status 400 (%s). Dirserver didn't like our "
1782 "rendezvous query?", escaped(reason));
1783 break;
1784 default:
1785 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1786 "fetching hidden service descriptor (server '%s:%d').",
1787 status_code, escaped(reason), conn->_base.address,
1788 conn->_base.port);
1789 break;
1793 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
1794 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1795 "(%s))",
1796 (int)body_len, status_code, escaped(reason));
1797 switch (status_code) {
1798 case 200:
1799 switch (rend_cache_store_v2_desc_as_client(body, NULL)) {
1800 case -2:
1801 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
1802 "Retrying at another directory.");
1803 /* We'll retry when connection_about_to_close_connection()
1804 * cleans this dir conn up. */
1805 break;
1806 case -1:
1807 /* We already have a v0 descriptor here. Ignoring this one
1808 * and _not_ performing another request. */
1809 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1810 "descriptor, but we already have a v0 descriptor.");
1811 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1812 break;
1813 default:
1814 /* success. notify pending connections about this. */
1815 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1816 "descriptor.");
1817 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1818 rend_client_desc_here(conn->rend_query);
1819 break;
1821 break;
1822 case 404:
1823 /* Not there. We'll retry when
1824 * connection_about_to_close_connection() cleans this conn up. */
1825 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
1826 "Retrying at another directory.");
1827 break;
1828 case 400:
1829 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1830 "http status 400 (%s). Dirserver didn't like our "
1831 "v2 rendezvous query? Retrying at another directory.",
1832 escaped(reason));
1833 break;
1834 default:
1835 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1836 "http status %d (%s) response unexpected while "
1837 "fetching v2 hidden service descriptor (server '%s:%d'). "
1838 "Retrying at another directory.",
1839 status_code, escaped(reason), conn->_base.address,
1840 conn->_base.port);
1841 break;
1845 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
1846 conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
1847 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
1848 "(%s))",
1849 status_code, escaped(reason));
1850 switch (status_code) {
1851 case 200:
1852 log_info(LD_REND,
1853 "Uploading rendezvous descriptor: finished with status "
1854 "200 (%s)", escaped(reason));
1855 break;
1856 case 400:
1857 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1858 "'%s:%d'. Malformed rendezvous descriptor?",
1859 escaped(reason), conn->_base.address, conn->_base.port);
1860 break;
1861 case 503:
1862 log_info(LD_REND,"http status 503 (%s) response from dirserver "
1863 "'%s:%d'. Node is (currently) not acting as v2 hidden "
1864 "service directory.",
1865 escaped(reason), conn->_base.address, conn->_base.port);
1866 break;
1867 default:
1868 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1869 "'%s:%d').",
1870 status_code, escaped(reason), conn->_base.address,
1871 conn->_base.port);
1872 break;
1875 tor_free(body); tor_free(headers); tor_free(reason);
1876 return 0;
1879 /** Called when a directory connection reaches EOF. */
1881 connection_dir_reached_eof(dir_connection_t *conn)
1883 int retval;
1884 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
1885 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
1886 conn->_base.state);
1887 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
1888 connection_mark_for_close(TO_CONN(conn));
1889 return -1;
1892 retval = connection_dir_client_reached_eof(conn);
1893 if (retval == 0) /* success */
1894 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
1895 connection_mark_for_close(TO_CONN(conn));
1896 return retval;
1899 /** If any directory object is arriving, and it's over 10MB large, we're
1900 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1901 * ask for more than 96 router descriptors at a time.)
1903 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1905 /** Read handler for directory connections. (That's connections <em>to</em>
1906 * directory servers and connections <em>at</em> directory servers.)
1909 connection_dir_process_inbuf(dir_connection_t *conn)
1911 tor_assert(conn);
1912 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1914 /* Directory clients write, then read data until they receive EOF;
1915 * directory servers read data until they get an HTTP command, then
1916 * write their response (when it's finished flushing, they mark for
1917 * close).
1920 /* If we're on the dirserver side, look for a command. */
1921 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1922 if (directory_handle_command(conn) < 0) {
1923 connection_mark_for_close(TO_CONN(conn));
1924 return -1;
1926 return 0;
1929 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
1930 log_warn(LD_HTTP, "Too much data received from directory connection: "
1931 "denial of service attempt, or you need to upgrade?");
1932 connection_mark_for_close(TO_CONN(conn));
1933 return -1;
1936 if (!conn->_base.inbuf_reached_eof)
1937 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1938 return 0;
1941 /** Create an http response for the client <b>conn</b> out of
1942 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1944 static void
1945 write_http_status_line(dir_connection_t *conn, int status,
1946 const char *reason_phrase)
1948 char buf[256];
1949 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1950 status, reason_phrase ? reason_phrase : "OK") < 0) {
1951 log_warn(LD_BUG,"status line too long.");
1952 return;
1954 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
1957 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1958 * with <b>type</b> as the Content-Type.
1960 * If <b>length</b> is nonnegative, it is the Content-Length.
1961 * If <b>encoding</b> is provided, it is the Content-Encoding.
1962 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1963 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1964 static void
1965 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
1966 const char *type, const char *encoding,
1967 const char *extra_headers,
1968 int cache_lifetime)
1970 char date[RFC1123_TIME_LEN+1];
1971 char tmp[1024];
1972 char *cp;
1973 time_t now = time(NULL);
1975 tor_assert(conn);
1977 format_rfc1123_time(date, now);
1978 cp = tmp;
1979 tor_snprintf(cp, sizeof(tmp),
1980 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
1981 date);
1982 cp += strlen(tmp);
1983 if (type) {
1984 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
1985 cp += strlen(cp);
1987 if (!is_local_IP(conn->_base.addr)) {
1988 /* Don't report the source address for a nearby/private connection.
1989 * Otherwise we tend to mis-report in cases where incoming ports are
1990 * being forwarded to a Tor server running behind the firewall. */
1991 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1992 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
1993 cp += strlen(cp);
1995 if (encoding) {
1996 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1997 "Content-Encoding: %s\r\n", encoding);
1998 cp += strlen(cp);
2000 if (length >= 0) {
2001 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2002 "Content-Length: %ld\r\n", (long)length);
2003 cp += strlen(cp);
2005 if (cache_lifetime > 0) {
2006 char expbuf[RFC1123_TIME_LEN+1];
2007 format_rfc1123_time(expbuf, now + cache_lifetime);
2008 /* We could say 'Cache-control: max-age=%d' here if we start doing
2009 * http/1.1 */
2010 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2011 "Expires: %s\r\n", expbuf);
2012 cp += strlen(cp);
2013 } else if (cache_lifetime == 0) {
2014 /* We could say 'Cache-control: no-cache' here if we start doing
2015 * http/1.1 */
2016 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2017 cp += strlen(cp);
2019 if (extra_headers)
2020 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2021 if (sizeof(tmp)-(cp-tmp) > 3)
2022 memcpy(cp, "\r\n", 3);
2023 else
2024 tor_assert(0);
2025 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2028 /** As write_http_response_header_impl, but sets encoding and content-typed
2029 * based on whether the response will be <b>compressed</b> or not. */
2030 static void
2031 write_http_response_header(dir_connection_t *conn, ssize_t length,
2032 int compressed, int cache_lifetime)
2034 write_http_response_header_impl(conn, length,
2035 compressed?"application/octet-stream":"text/plain",
2036 compressed?"deflate":"identity",
2037 NULL,
2038 cache_lifetime);
2041 /** Helper function: return 1 if there are any dir conns of purpose
2042 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
2043 * Else return 0.
2045 static int
2046 already_fetching_directory(int purpose)
2048 smartlist_t *conns = get_connection_array();
2049 SMARTLIST_FOREACH(conns, connection_t *, conn,
2051 if (conn->type == CONN_TYPE_DIR &&
2052 conn->purpose == purpose &&
2053 !conn->marked_for_close &&
2054 !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
2055 return 1;
2057 return 0;
2060 #ifdef INSTRUMENT_DOWNLOADS
2061 /** Map used to keep track of how much data we've up/downloaded in what kind
2062 * of request. Maps from request type to pointer to uint64_t. */
2063 static strmap_t *request_bytes_map = NULL;
2065 /** Called when we just transmitted or received <b>bytes</b> worth of data
2066 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2067 * <b>bytes</b> to the total associated with key. */
2068 static void
2069 note_request(const char *key, size_t bytes)
2071 uint64_t *n;
2072 if (!request_bytes_map)
2073 request_bytes_map = strmap_new();
2075 n = strmap_get(request_bytes_map, key);
2076 if (!n) {
2077 n = tor_malloc_zero(sizeof(uint64_t));
2078 strmap_set(request_bytes_map, key, n);
2080 *n += bytes;
2083 /** Return a newly allocated string holding a summary of bytes used per
2084 * request type. */
2085 char *
2086 directory_dump_request_log(void)
2088 smartlist_t *lines;
2089 char tmp[256];
2090 char *result;
2091 strmap_iter_t *iter;
2093 if (!request_bytes_map)
2094 request_bytes_map = strmap_new();
2096 lines = smartlist_create();
2098 for (iter = strmap_iter_init(request_bytes_map);
2099 !strmap_iter_done(iter);
2100 iter = strmap_iter_next(request_bytes_map, iter)) {
2101 const char *key;
2102 void *val;
2103 uint64_t *n;
2104 strmap_iter_get(iter, &key, &val);
2105 n = val;
2106 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT"\n",
2107 key, U64_PRINTF_ARG(*n));
2108 smartlist_add(lines, tor_strdup(tmp));
2110 smartlist_sort_strings(lines);
2111 result = smartlist_join_strings(lines, "", 0, NULL);
2112 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2113 smartlist_free(lines);
2114 return result;
2116 #else
2117 static void
2118 note_request(const char *key, size_t bytes)
2120 (void)key;
2121 (void)bytes;
2124 char *
2125 directory_dump_request_log(void)
2127 return tor_strdup("Not supported.");
2129 #endif
2131 /** Helper function: called when a dirserver gets a complete HTTP GET
2132 * request. Look for a request for a directory or for a rendezvous
2133 * service descriptor. On finding one, write a response into
2134 * conn-\>outbuf. If the request is unrecognized, send a 400.
2135 * Always return 0. */
2136 static int
2137 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2138 const char *body, size_t body_len)
2140 size_t dlen;
2141 char *url, *url_mem, *header;
2142 or_options_t *options = get_options();
2143 time_t if_modified_since = 0;
2144 int compressed;
2145 size_t url_len;
2147 /* We ignore the body of a GET request. */
2148 (void)body;
2149 (void)body_len;
2151 log_debug(LD_DIRSERV,"Received GET command.");
2153 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2155 if (parse_http_url(headers, &url) < 0) {
2156 write_http_status_line(conn, 400, "Bad request");
2157 return 0;
2159 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2160 struct tm tm;
2161 if (parse_http_time(header, &tm) == 0) {
2162 if_modified_since = tor_timegm(&tm);
2164 /* The correct behavior on a malformed If-Modified-Since header is to
2165 * act as if no If-Modified-Since header had been given. */
2166 tor_free(header);
2168 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2170 url_mem = url;
2171 url_len = strlen(url);
2172 compressed = url_len > 2 && !strcmp(url+url_len-2, ".z");
2173 if (compressed) {
2174 url[url_len-2] = '\0';
2175 url_len -= 2;
2178 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* dir fetch */
2179 cached_dir_t *d = dirserv_get_directory();
2181 if (!d) {
2182 log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
2183 "don't have a good one yet. Sending 503 Dir not available.");
2184 write_http_status_line(conn, 503, "Directory unavailable");
2185 /* try to get a new one now */
2186 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR) &&
2187 !should_delay_dir_fetches(options))
2188 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR,
2189 ROUTER_PURPOSE_GENERAL, NULL, 1);
2190 goto done;
2192 if (d->published < if_modified_since) {
2193 write_http_status_line(conn, 304, "Not modified");
2194 goto done;
2197 dlen = compressed ? d->dir_z_len : d->dir_len;
2199 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2200 log_info(LD_DIRSERV,
2201 "Client asked for the mirrored directory, but we've been "
2202 "writing too many bytes lately. Sending 503 Dir busy.");
2203 write_http_status_line(conn, 503, "Directory busy, try again later");
2204 goto done;
2207 note_request(url, dlen);
2209 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
2210 compressed?"compressed ":"");
2211 write_http_response_header(conn, dlen, compressed,
2212 FULL_DIR_CACHE_LIFETIME);
2213 conn->cached_dir = d;
2214 conn->cached_dir_offset = 0;
2215 if (!compressed)
2216 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2217 ++d->refcnt;
2219 /* Prime the connection with some data. */
2220 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
2221 connection_dirserv_flushed_some(conn);
2222 goto done;
2225 if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
2226 cached_dir_t *d = dirserv_get_runningrouters();
2227 if (!d) {
2228 write_http_status_line(conn, 503, "Directory unavailable");
2229 /* try to get a new one now */
2230 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST) &&
2231 !should_delay_dir_fetches(options))
2232 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST,
2233 ROUTER_PURPOSE_GENERAL, NULL, 1);
2234 goto done;
2236 if (d->published < if_modified_since) {
2237 write_http_status_line(conn, 304, "Not modified");
2238 goto done;
2240 dlen = compressed ? d->dir_z_len : d->dir_len;
2242 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2243 log_info(LD_DIRSERV,
2244 "Client asked for running-routers, but we've been "
2245 "writing too many bytes lately. Sending 503 Dir busy.");
2246 write_http_status_line(conn, 503, "Directory busy, try again later");
2247 goto done;
2249 note_request(url, dlen);
2250 write_http_response_header(conn, dlen, compressed,
2251 RUNNINGROUTERS_CACHE_LIFETIME);
2252 connection_write_to_buf(compressed ? d->dir_z : d->dir, dlen,
2253 TO_CONN(conn));
2254 goto done;
2257 if (!strcmpstart(url,"/tor/status/")
2258 || !strcmp(url, "/tor/status-vote/current/consensus")) {
2259 /* v2 or v3 network status fetch. */
2260 smartlist_t *dir_fps = smartlist_create();
2261 int is_v3 = !strcmpstart(url, "/tor/status-vote");
2262 const char *request_type = NULL;
2263 const char *key = url + strlen("/tor/status/");
2264 int lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2265 if (!is_v3) {
2266 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
2267 if (!strcmpstart(key, "fp/"))
2268 request_type = compressed?"/tor/status/fp.z":"/tor/status/fp";
2269 else if (!strcmpstart(key, "authority"))
2270 request_type = compressed?"/tor/status/authority.z":
2271 "/tor/status/authority";
2272 else if (!strcmpstart(key, "all"))
2273 request_type = compressed?"/tor/status/all.z":"/tor/status/all";
2274 else
2275 request_type = "/tor/status/?";
2276 } else {
2277 networkstatus_t *v = networkstatus_get_latest_consensus();
2278 time_t now = time(NULL);
2279 smartlist_add(dir_fps, tor_memdup("\0\0\0\0\0\0\0\0\0\0"
2280 "\0\0\0\0\0\0\0\0\0\0", 20));
2281 request_type = compressed?"v3.z":"v3";
2282 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2285 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2286 write_http_status_line(conn, 503, "Network status object unavailable");
2287 smartlist_free(dir_fps);
2288 goto done;
2291 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2292 write_http_status_line(conn, 404, "Not found");
2293 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2294 smartlist_free(dir_fps);
2295 goto done;
2296 } else if (!smartlist_len(dir_fps)) {
2297 write_http_status_line(conn, 304, "Not modified");
2298 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2299 smartlist_free(dir_fps);
2300 goto done;
2303 dlen = dirserv_estimate_data_size(dir_fps, 0, compressed);
2304 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2305 log_info(LD_DIRSERV,
2306 "Client asked for network status lists, but we've been "
2307 "writing too many bytes lately. Sending 503 Dir busy.");
2308 write_http_status_line(conn, 503, "Directory busy, try again later");
2309 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2310 smartlist_free(dir_fps);
2311 goto done;
2314 // note_request(request_type,dlen);
2315 (void) request_type;
2316 write_http_response_header(conn, -1, compressed,
2317 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2318 conn->fingerprint_stack = dir_fps;
2319 if (! compressed)
2320 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2322 /* Prime the connection with some data. */
2323 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2324 connection_dirserv_flushed_some(conn);
2325 goto done;
2328 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2329 !strcmpstart(url,"/tor/status-vote/next/")) {
2330 /* XXXX If-modified-since is only implemented for the current
2331 * consensus: that's probably fine, since it's the only vote document
2332 * people fetch much.*/
2333 int current;
2334 ssize_t body_len = 0;
2335 ssize_t estimated_len = 0;
2336 smartlist_t *items = smartlist_create();
2337 smartlist_t *dir_items = smartlist_create();
2338 int lifetime = 60; /* XXXX020 should actually use vote intervals. */
2339 url += strlen("/tor/status-vote/");
2340 current = !strcmpstart(url, "current/");
2341 url = strchr(url, '/');
2342 tor_assert(url);
2343 ++url;
2344 if (!strcmp(url, "consensus")) {
2345 const char *item;
2346 tor_assert(!current); /* we handle current consensus specially above,
2347 * since it wants to be spooled. */
2348 if ((item = dirvote_get_pending_consensus()))
2349 smartlist_add(items, (char*)item);
2350 } else if (!current && !strcmp(url, "consensus-signatures")) {
2351 /* XXXX the spec says that we should implement
2352 * current/consensus-signatures too. It doesn't seem to be needed,
2353 * though. */
2354 const char *item;
2355 if ((item=dirvote_get_pending_detached_signatures()))
2356 smartlist_add(items, (char*)item);
2357 } else if (!strcmp(url, "authority")) {
2358 const cached_dir_t *d;
2359 int flags = DGV_BY_ID |
2360 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2361 if ((d=dirvote_get_vote(NULL, flags)))
2362 smartlist_add(dir_items, (cached_dir_t*)d);
2363 } else {
2364 const cached_dir_t *d;
2365 smartlist_t *fps = smartlist_create();
2366 int flags;
2367 if (!strcmpstart(url, "d/")) {
2368 url += 2;
2369 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2370 } else {
2371 flags = DGV_BY_ID |
2372 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2374 dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1);
2375 SMARTLIST_FOREACH(fps, char *, fp, {
2376 if ((d = dirvote_get_vote(fp, flags)))
2377 smartlist_add(dir_items, (cached_dir_t*)d);
2378 tor_free(fp);
2380 smartlist_free(fps);
2382 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2383 write_http_status_line(conn, 404, "Not found");
2384 goto vote_done;
2386 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2387 body_len += compressed ? d->dir_z_len : d->dir_len);
2388 estimated_len += body_len;
2389 SMARTLIST_FOREACH(items, const char *, item, {
2390 size_t ln = strlen(item);
2391 if (compressed) {
2392 estimated_len += ln/2;
2393 } else {
2394 body_len += ln; estimated_len += ln;
2398 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 1)) {
2399 write_http_status_line(conn, 503, "Directory busy, try again later.");
2400 goto vote_done;
2402 write_http_response_header(conn, body_len ? body_len : -1, compressed,
2403 lifetime);
2405 if (smartlist_len(items)) {
2406 if (compressed) {
2407 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2408 SMARTLIST_FOREACH(items, const char *, c,
2409 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2410 connection_write_to_buf_zlib("", 0, conn, 1);
2411 } else {
2412 SMARTLIST_FOREACH(items, const char *, c,
2413 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2415 } else {
2416 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2417 connection_write_to_buf(compressed ? d->dir_z : d->dir,
2418 compressed ? d->dir_z_len : d->dir_len,
2419 TO_CONN(conn)));
2421 vote_done:
2422 smartlist_free(items);
2423 smartlist_free(dir_items);
2424 goto done;
2427 if (!strcmpstart(url,"/tor/server/") ||
2428 !strcmpstart(url,"/tor/extra/")) {
2429 int res;
2430 const char *msg;
2431 const char *request_type = NULL;
2432 int cache_lifetime = 0;
2433 int is_extra = !strcmpstart(url,"/tor/extra/");
2434 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2435 conn->fingerprint_stack = smartlist_create();
2436 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2437 &msg,
2438 !connection_dir_is_encrypted(conn));
2440 if (!strcmpstart(url, "fp/")) {
2441 request_type = compressed?"/tor/server/fp.z":"/tor/server/fp";
2442 if (smartlist_len(conn->fingerprint_stack) == 1)
2443 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2444 } else if (!strcmpstart(url, "authority")) {
2445 request_type = compressed?"/tor/server/authority.z":
2446 "/tor/server/authority";
2447 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2448 } else if (!strcmpstart(url, "all")) {
2449 request_type = compressed?"/tor/server/all.z":"/tor/server/all";
2450 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2451 } else if (!strcmpstart(url, "d/")) {
2452 request_type = compressed?"/tor/server/d.z":"/tor/server/d";
2453 if (smartlist_len(conn->fingerprint_stack) == 1)
2454 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2455 } else {
2456 request_type = "/tor/server/?";
2458 (void) request_type; /* usable for note_request. */
2459 if (!strcmpstart(url, "d/"))
2460 conn->dir_spool_src =
2461 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2462 else
2463 conn->dir_spool_src =
2464 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2466 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2467 conn->dir_spool_src)) {
2468 res = -1;
2469 msg = "Not found";
2472 if (res < 0)
2473 write_http_status_line(conn, 404, msg);
2474 else {
2475 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2476 1, compressed);
2477 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2478 log_info(LD_DIRSERV,
2479 "Client asked for server descriptors, but we've been "
2480 "writing too many bytes lately. Sending 503 Dir busy.");
2481 write_http_status_line(conn, 503, "Directory busy, try again later");
2482 conn->dir_spool_src = DIR_SPOOL_NONE;
2483 goto done;
2485 write_http_response_header(conn, -1, compressed, cache_lifetime);
2486 if (compressed)
2487 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2488 /* Prime the connection with some data. */
2489 connection_dirserv_flushed_some(conn);
2491 goto done;
2494 if (!strcmpstart(url,"/tor/keys/")) {
2495 smartlist_t *certs = smartlist_create();
2496 ssize_t len = -1;
2497 if (!strcmp(url, "/tor/keys/all")) {
2498 authority_cert_get_all(certs);
2499 } else if (!strcmp(url, "/tor/keys/authority")) {
2500 authority_cert_t *cert = get_my_v3_authority_cert();
2501 if (cert)
2502 smartlist_add(certs, cert);
2503 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
2504 smartlist_t *fps = smartlist_create();
2505 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
2506 fps, NULL, 1, 1);
2507 SMARTLIST_FOREACH(fps, char *, d, {
2508 authority_cert_t *c = authority_cert_get_newest_by_id(d);
2509 if (c) smartlist_add(certs, c);
2510 tor_free(d);
2512 smartlist_free(fps);
2513 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
2514 smartlist_t *fps = smartlist_create();
2515 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
2516 fps, NULL, 1, 1);
2517 SMARTLIST_FOREACH(fps, char *, d, {
2518 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
2519 if (c) smartlist_add(certs, c);
2520 tor_free(d);
2522 smartlist_free(fps);
2523 } else {
2524 write_http_status_line(conn, 400, "Bad request");
2525 goto keys_done;
2527 if (!smartlist_len(certs)) {
2528 write_http_status_line(conn, 404, "Not found");
2529 goto keys_done;
2531 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2532 if (c->cache_info.published_on < if_modified_since)
2533 SMARTLIST_DEL_CURRENT(certs, c));
2534 if (!smartlist_len(certs)) {
2535 write_http_status_line(conn, 304, "Not modified");
2536 goto keys_done;
2538 len = 0;
2539 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2540 len += c->cache_info.signed_descriptor_len);
2542 if (global_write_bucket_low(TO_CONN(conn), compressed?len/2:len, 1)) {
2543 write_http_status_line(conn, 503, "Directory busy, try again later.");
2544 goto keys_done;
2547 write_http_response_header(conn, compressed?-1:len, compressed, 60*60);
2548 if (compressed) {
2549 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2550 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2551 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
2552 c->cache_info.signed_descriptor_len,
2553 conn, 0));
2554 connection_write_to_buf_zlib("", 0, conn, 1);
2555 } else {
2556 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2557 connection_write_to_buf(c->cache_info.signed_descriptor_body,
2558 c->cache_info.signed_descriptor_len,
2559 TO_CONN(conn)));
2561 keys_done:
2562 smartlist_free(certs);
2563 goto done;
2566 if (options->HidServDirectoryV2 &&
2567 !strcmpstart(url,"/tor/rendezvous2/")) {
2568 /* Handle v2 rendezvous descriptor fetch request. */
2569 const char *descp;
2570 const char *query = url + strlen("/tor/rendezvous2/");
2571 if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) {
2572 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
2573 query);
2574 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
2575 case 1: /* valid */
2576 write_http_response_header(conn, strlen(descp), 0, 0);
2577 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
2578 break;
2579 case 0: /* well-formed but not present */
2580 write_http_status_line(conn, 404, "Not found");
2581 break;
2582 case -1: /* not well-formed */
2583 write_http_status_line(conn, 400, "Bad request");
2584 break;
2586 } else { /* not well-formed */
2587 write_http_status_line(conn, 400, "Bad request");
2589 goto done;
2592 if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) {
2593 /* rendezvous descriptor fetch */
2594 const char *descp;
2595 size_t desc_len;
2596 const char *query = url+strlen("/tor/rendezvous/");
2598 log_info(LD_REND, "Handling rendezvous descriptor get");
2599 switch (rend_cache_lookup_desc(query, 0, &descp, &desc_len)) {
2600 case 1: /* valid */
2601 write_http_response_header_impl(conn, desc_len,
2602 "application/octet-stream",
2603 NULL, NULL, 0);
2604 note_request("/tor/rendezvous?/", desc_len);
2605 /* need to send descp separately, because it may include nuls */
2606 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
2607 /* report successful fetch to statistic */
2608 if (options->HSAuthorityRecordStats) {
2609 hs_usage_note_fetch_total(query, time(NULL));
2610 hs_usage_note_fetch_successful(query, time(NULL));
2612 break;
2613 case 0: /* well-formed but not present */
2614 write_http_status_line(conn, 404, "Not found");
2615 /* report (unsuccessful) fetch to statistic */
2616 if (options->HSAuthorityRecordStats) {
2617 hs_usage_note_fetch_total(query, time(NULL));
2619 break;
2620 case -1: /* not well-formed */
2621 write_http_status_line(conn, 400, "Bad request");
2622 break;
2624 goto done;
2627 if (options->BridgeAuthoritativeDir &&
2628 options->BridgePassword &&
2629 connection_dir_is_encrypted(conn) &&
2630 !strcmp(url,"/tor/networkstatus-bridges")) {
2631 char *status;
2632 char decoded[64];
2633 char *secret;
2634 int r;
2636 header = http_get_header(headers, "Authorization: Basic ");
2638 if (!header) {
2639 write_http_status_line(conn, 404, "Not found");
2640 goto done;
2643 /* now make sure the password is right */
2644 r = base64_decode(decoded, sizeof(decoded), header, strlen(header));
2645 secret = alloc_http_authenticator(options->BridgePassword);
2646 if (r < 0 || (unsigned)r != strlen(secret) || memcmp(decoded, secret, r)) {
2647 /* failed to decode, or didn't match. Refuse. */
2648 write_http_status_line(conn, 404, "Not found");
2649 tor_free(header);
2650 goto done;
2652 tor_free(secret);
2654 /* all happy now. send an answer. */
2655 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
2656 dlen = strlen(status);
2657 write_http_response_header(conn, dlen, 0, 0);
2658 connection_write_to_buf(status, dlen, TO_CONN(conn));
2659 tor_free(status);
2660 goto done;
2663 if (!strcmpstart(url,"/tor/bytes.txt")) {
2664 char *bytes = directory_dump_request_log();
2665 size_t len = strlen(bytes);
2666 write_http_response_header(conn, len, 0, 0);
2667 connection_write_to_buf(bytes, len, TO_CONN(conn));
2668 tor_free(bytes);
2669 goto done;
2672 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
2673 rewritten to /tor/robots.txt */
2674 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
2675 size_t len = strlen(robots);
2676 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
2677 connection_write_to_buf(robots, len, TO_CONN(conn));
2678 goto done;
2681 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
2682 #define ADD_MALLINFO_LINE(x) do { \
2683 tor_snprintf(tmp, sizeof(tmp), "%s %d\n", #x, mi.x); \
2684 smartlist_add(lines, tor_strdup(tmp)); \
2685 }while(0);
2687 if (!strcmp(url,"/tor/mallinfo.txt") &&
2688 (conn->_base.addr == 0x7f000001ul)) {
2689 char *result;
2690 size_t len;
2691 struct mallinfo mi;
2692 smartlist_t *lines;
2693 char tmp[256];
2695 memset(&mi, 0, sizeof(mi));
2696 mi = mallinfo();
2697 lines = smartlist_create();
2699 ADD_MALLINFO_LINE(arena)
2700 ADD_MALLINFO_LINE(ordblks)
2701 ADD_MALLINFO_LINE(smblks)
2702 ADD_MALLINFO_LINE(hblks)
2703 ADD_MALLINFO_LINE(hblkhd)
2704 ADD_MALLINFO_LINE(usmblks)
2705 ADD_MALLINFO_LINE(fsmblks)
2706 ADD_MALLINFO_LINE(uordblks)
2707 ADD_MALLINFO_LINE(fordblks)
2708 ADD_MALLINFO_LINE(keepcost)
2710 result = smartlist_join_strings(lines, "", 0, NULL);
2711 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2712 smartlist_free(lines);
2714 len = strlen(result);
2715 write_http_response_header(conn, len, 0, 0);
2716 connection_write_to_buf(result, len, TO_CONN(conn));
2717 tor_free(result);
2718 goto done;
2720 #endif
2722 /* we didn't recognize the url */
2723 write_http_status_line(conn, 404, "Not found");
2725 done:
2726 tor_free(url_mem);
2727 return 0;
2730 /** Helper function: called when a dirserver gets a complete HTTP POST
2731 * request. Look for an uploaded server descriptor or rendezvous
2732 * service descriptor. On finding one, process it and write a
2733 * response into conn-\>outbuf. If the request is unrecognized, send a
2734 * 400. Always return 0. */
2735 static int
2736 directory_handle_command_post(dir_connection_t *conn, const char *headers,
2737 const char *body, size_t body_len)
2739 char *url = NULL;
2740 or_options_t *options = get_options();
2742 log_debug(LD_DIRSERV,"Received POST command.");
2744 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2746 if (parse_http_url(headers, &url) < 0) {
2747 write_http_status_line(conn, 400, "Bad request");
2748 return 0;
2750 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2752 /* Handle v2 rendezvous service publish request. */
2753 if (options->HidServDirectoryV2 &&
2754 !strcmpstart(url,"/tor/rendezvous2/publish")) {
2755 switch (rend_cache_store_v2_desc_as_dir(body)) {
2756 case -2:
2757 log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
2758 "since we're not currently a hidden service directory.",
2759 (int)body_len, conn->_base.address);
2760 write_http_status_line(conn, 503, "Currently not acting as v2 "
2761 "hidden service directory");
2762 break;
2763 case -1:
2764 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
2765 (int)body_len, conn->_base.address);
2766 write_http_status_line(conn, 400, "Invalid service descriptor "
2767 "rejected");
2768 break;
2769 default:
2770 write_http_status_line(conn, 200, "Service descriptor stored");
2771 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
2773 goto done;
2776 if (!authdir_mode(options)) {
2777 /* we just provide cached directories; we don't want to
2778 * receive anything. */
2779 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
2780 "accept posted server descriptors");
2781 return 0;
2784 if (authdir_mode_handles_descs(options, -1) &&
2785 !strcmp(url,"/tor/")) { /* server descriptor post */
2786 const char *msg = NULL;
2787 uint8_t purpose = authdir_mode_bridge(options) ?
2788 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
2789 int r = dirserv_add_multiple_descriptors(body, purpose,
2790 conn->_base.address, &msg);
2791 tor_assert(msg);
2792 if (r > 0)
2793 dirserv_get_directory(); /* rebuild and write to disk */
2794 switch (r) {
2795 case -1:
2796 log_notice(LD_DIRSERV,
2797 "Rejected router descriptor or extra-info from %s "
2798 "(\"%s\").",
2799 conn->_base.address, msg);
2800 /* fall through */
2801 case 1:
2802 /* malformed descriptor, or something wrong */
2803 write_http_status_line(conn, 400, msg);
2804 break;
2805 case 0: /* accepted but discarded */
2806 write_http_response_header_impl(conn, -1, NULL, NULL,
2807 "X-Descriptor-Not-New: Yes\r\n", -1);
2808 break;
2809 case 2: /* accepted */
2810 write_http_status_line(conn, 200, msg);
2811 break;
2813 goto done;
2816 if (options->HSAuthoritativeDir &&
2817 !strcmpstart(url,"/tor/rendezvous/publish")) {
2818 /* rendezvous descriptor post */
2819 log_info(LD_REND, "Handling rendezvous descriptor post.");
2820 if (rend_cache_store(body, body_len, 1) < 0) {
2821 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
2822 "Rejected rend descriptor (length %d) from %s.",
2823 (int)body_len, conn->_base.address);
2824 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
2825 } else {
2826 write_http_status_line(conn, 200, "Service descriptor stored");
2828 goto done;
2831 if (authdir_mode_v3(options) &&
2832 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
2833 const char *msg = "OK";
2834 int status;
2835 if (dirvote_add_vote(body, &msg, &status)) {
2836 write_http_status_line(conn, status, "Vote stored");
2837 } else {
2838 tor_assert(msg);
2839 write_http_status_line(conn, status, msg);
2841 goto done;
2844 if (authdir_mode_v3(options) &&
2845 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
2846 const char *msg = NULL;
2847 if (dirvote_add_signatures(body, conn->_base.address, &msg)>=0) {
2848 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
2849 } else {
2850 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
2851 conn->_base.address, msg?msg:"???");
2852 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
2854 goto done;
2857 /* we didn't recognize the url */
2858 write_http_status_line(conn, 404, "Not found");
2860 done:
2861 tor_free(url);
2862 return 0;
2865 /** Called when a dirserver receives data on a directory connection;
2866 * looks for an HTTP request. If the request is complete, remove it
2867 * from the inbuf, try to process it; otherwise, leave it on the
2868 * buffer. Return a 0 on success, or -1 on error.
2870 static int
2871 directory_handle_command(dir_connection_t *conn)
2873 char *headers=NULL, *body=NULL;
2874 size_t body_len=0;
2875 int r;
2877 tor_assert(conn);
2878 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2880 switch (fetch_from_buf_http(conn->_base.inbuf,
2881 &headers, MAX_HEADERS_SIZE,
2882 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
2883 case -1: /* overflow */
2884 log_warn(LD_DIRSERV,
2885 "Invalid input from address '%s'. Closing.",
2886 conn->_base.address);
2887 return -1;
2888 case 0:
2889 log_debug(LD_DIRSERV,"command not all here yet.");
2890 return 0;
2891 /* case 1, fall through */
2894 http_set_address_origin(headers, TO_CONN(conn));
2895 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
2897 if (!strncasecmp(headers,"GET",3))
2898 r = directory_handle_command_get(conn, headers, body, body_len);
2899 else if (!strncasecmp(headers,"POST",4))
2900 r = directory_handle_command_post(conn, headers, body, body_len);
2901 else {
2902 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
2903 "Got headers %s with unknown command. Closing.",
2904 escaped(headers));
2905 r = -1;
2908 tor_free(headers); tor_free(body);
2909 return r;
2912 /** Write handler for directory connections; called when all data has
2913 * been flushed. Close the connection or wait for a response as
2914 * appropriate.
2917 connection_dir_finished_flushing(dir_connection_t *conn)
2919 tor_assert(conn);
2920 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2922 switch (conn->_base.state) {
2923 case DIR_CONN_STATE_CLIENT_SENDING:
2924 log_debug(LD_DIR,"client finished sending command.");
2925 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
2926 connection_stop_writing(TO_CONN(conn));
2927 return 0;
2928 case DIR_CONN_STATE_SERVER_WRITING:
2929 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
2930 connection_mark_for_close(TO_CONN(conn));
2931 return 0;
2932 default:
2933 log_warn(LD_BUG,"called in unexpected state %d.",
2934 conn->_base.state);
2935 tor_fragile_assert();
2936 return -1;
2938 return 0;
2941 /** Connected handler for directory connections: begin sending data to the
2942 * server */
2944 connection_dir_finished_connecting(dir_connection_t *conn)
2946 tor_assert(conn);
2947 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2948 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
2950 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
2951 conn->_base.address,conn->_base.port);
2953 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
2954 return 0;
2957 /** Called when one or more networkstatus fetches have failed (with uppercase
2958 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
2959 * failed once, unless they failed with status code 503. */
2960 static void
2961 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
2963 if (status_code == 503)
2964 return;
2965 SMARTLIST_FOREACH(failed, const char *, fp,
2967 char digest[DIGEST_LEN];
2968 trusted_dir_server_t *dir;
2969 if (base16_decode(digest, DIGEST_LEN, fp, strlen(fp))<0) {
2970 log_warn(LD_BUG, "Called with bad fingerprint in list: %s",
2971 escaped(fp));
2972 continue;
2974 dir = router_get_trusteddirserver_by_digest(digest);
2976 if (dir)
2977 download_status_failed(&dir->v2_ns_dl_status, status_code);
2981 static const int server_dl_schedule[] = {
2982 0, 0, 0, 60, 60, 60*2, 60*5, 60*15, INT_MAX
2984 static const int client_dl_schedule[] = {
2985 0, 0, 60, 60*5, 60*10, INT_MAX
2987 static const int server_consensus_dl_schedule[] = {
2988 0, 0, 60, 60*5, 60*10, 60*30, 60*30, 60*30, 60*30, 60*30, 60*60, 60*60*2
2990 static const int client_consensus_dl_schedule[] = {
2991 0, 0, 60, 60*5, 60*10, 60*30, 60*60, 60*60, 60*60, 60*60*3, 60*60*6, 60*60*12
2994 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
2995 * <b>status_code</b>. Increment the failure count (if the code indicates a
2996 * real failure) and set <b>dls<b>->next_attempt_at to an appropriate time in
2997 * the future. */
2998 time_t
2999 download_status_increment_failure(download_status_t *dls, int status_code,
3000 const char *item, int server, time_t now)
3002 const int *schedule;
3003 int schedule_len;
3004 int increment;
3005 tor_assert(dls);
3006 if (status_code != 503 || server)
3007 ++dls->n_download_failures;
3009 switch (dls->schedule) {
3010 case DL_SCHED_GENERIC:
3011 if (server) {
3012 schedule = server_dl_schedule;
3013 schedule_len = sizeof(server_dl_schedule)/sizeof(int);
3014 } else {
3015 schedule = client_dl_schedule;
3016 schedule_len = sizeof(client_dl_schedule)/sizeof(int);
3018 break;
3019 case DL_SCHED_CONSENSUS:
3020 if (server) {
3021 schedule = server_consensus_dl_schedule;
3022 schedule_len = sizeof(server_consensus_dl_schedule)/sizeof(int);
3023 } else {
3024 schedule = client_consensus_dl_schedule;
3025 schedule_len = sizeof(client_consensus_dl_schedule)/sizeof(int);
3027 break;
3028 default:
3029 tor_assert(0);
3032 if (dls->n_download_failures < schedule_len)
3033 increment = schedule[dls->n_download_failures];
3034 else
3035 increment = schedule[schedule_len-1];
3037 if (increment < INT_MAX)
3038 dls->next_attempt_at = now+increment;
3039 else
3040 dls->next_attempt_at = TIME_MAX;
3042 if (item) {
3043 if (dls->next_attempt_at == 0)
3044 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
3045 item, (int)dls->n_download_failures);
3046 else if (dls->next_attempt_at < TIME_MAX)
3047 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
3048 item, (int)dls->n_download_failures,
3049 (int)(dls->next_attempt_at-now));
3050 else
3051 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
3052 item, (int)dls->n_download_failures);
3054 return dls->next_attempt_at;
3057 /** Reset <b>dls</b> so that it will be considered downloadable
3058 * immediately. */
3059 void
3060 download_status_reset(download_status_t *dls)
3062 dls->n_download_failures = 0;
3063 dls->next_attempt_at = 0;
3066 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
3067 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
3068 * either as descriptor digests or as identity digests based on
3069 * <b>was_descriptor_digests</b>).
3071 static void
3072 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
3073 int router_purpose,
3074 int was_extrainfo, int was_descriptor_digests)
3076 char digest[DIGEST_LEN];
3077 time_t now = time(NULL);
3078 int server = directory_fetches_from_authorities(get_options());
3079 if (!was_descriptor_digests) {
3080 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
3081 tor_assert(!was_extrainfo); /* not supported yet */
3082 SMARTLIST_FOREACH(failed, const char *, cp,
3084 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
3085 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
3086 escaped(cp));
3087 continue;
3089 retry_bridge_descriptor_fetch_directly(digest);
3092 return; /* FFFF should implement for other-than-router-purpose someday */
3094 SMARTLIST_FOREACH(failed, const char *, cp,
3096 download_status_t *dls = NULL;
3097 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) {
3098 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
3099 continue;
3101 if (was_extrainfo) {
3102 signed_descriptor_t *sd =
3103 router_get_by_extrainfo_digest(digest);
3104 if (sd)
3105 dls = &sd->ei_dl_status;
3106 } else {
3107 dls = router_get_dl_status_by_descriptor_digest(digest);
3109 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
3110 continue;
3111 download_status_increment_failure(dls, status_code, cp, server, now);
3114 /* No need to relaunch descriptor downloads here: we already do it
3115 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3118 /** Given a directory <b>resource</b> request, containing zero
3119 * or more strings separated by plus signs, followed optionally by ".z", store
3120 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3121 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
3122 * decode_hex is true, then delete all elements that aren't hex digests, and
3123 * decode the rest. If sort_uniq is true, then sort the list and remove
3124 * all duplicates.
3127 dir_split_resource_into_fingerprints(const char *resource,
3128 smartlist_t *fp_out, int *compressed_out,
3129 int decode_hex, int sort_uniq)
3131 smartlist_t *fp_tmp = smartlist_create();
3132 tor_assert(fp_out);
3133 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
3134 if (compressed_out)
3135 *compressed_out = 0;
3136 if (smartlist_len(fp_tmp)) {
3137 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3138 size_t last_len = strlen(last);
3139 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3140 last[last_len-2] = '\0';
3141 if (compressed_out)
3142 *compressed_out = 1;
3145 if (decode_hex) {
3146 int i;
3147 char *cp, *d = NULL;
3148 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3149 cp = smartlist_get(fp_tmp, i);
3150 if (strlen(cp) != HEX_DIGEST_LEN) {
3151 log_info(LD_DIR,
3152 "Skipping digest %s with non-standard length.", escaped(cp));
3153 smartlist_del_keeporder(fp_tmp, i--);
3154 goto again;
3156 d = tor_malloc_zero(DIGEST_LEN);
3157 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
3158 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3159 smartlist_del_keeporder(fp_tmp, i--);
3160 goto again;
3162 smartlist_set(fp_tmp, i, d);
3163 d = NULL;
3164 again:
3165 tor_free(cp);
3166 tor_free(d);
3169 if (sort_uniq) {
3170 smartlist_t *fp_tmp2 = smartlist_create();
3171 int i;
3172 if (decode_hex)
3173 smartlist_sort_digests(fp_tmp);
3174 else
3175 smartlist_sort_strings(fp_tmp);
3176 if (smartlist_len(fp_tmp))
3177 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
3178 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
3179 char *cp = smartlist_get(fp_tmp, i);
3180 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
3182 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
3183 || (!decode_hex && strcasecmp(cp, last)))
3184 smartlist_add(fp_tmp2, cp);
3185 else
3186 tor_free(cp);
3188 smartlist_free(fp_tmp);
3189 fp_tmp = fp_tmp2;
3191 smartlist_add_all(fp_out, fp_tmp);
3192 smartlist_free(fp_tmp);
3193 return 0;