answer one of nick's XXX020rc's usefully
[tor.git] / src / or / directory.c
blob900e9a2e7aaadf1fb14893e9bb891b58737988f5
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 /* XXX020rc 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;
692 /* If it's an anonymized connection, remember the fact that we
693 * wanted it for later: maybe we'll want it again soon. */
694 if (anonymized_connection && use_begindir)
695 rep_hist_note_used_internal(time(NULL), 0, 1);
696 else if (anonymized_connection && !use_begindir)
697 rep_hist_note_used_port(time(NULL), conn->_base.port);
699 /* make an AP connection
700 * populate it and add it at the right state
701 * hook up both sides
703 linked_conn =
704 connection_ap_make_link(conn->_base.address, conn->_base.port,
705 digest, use_begindir, conn->dirconn_direct);
706 if (!linked_conn) {
707 log_warn(LD_NET,"Making tunnel to dirserver failed.");
708 connection_mark_for_close(TO_CONN(conn));
709 return;
711 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
713 if (connection_add(TO_CONN(conn)) < 0) {
714 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
715 connection_mark_for_close(TO_CONN(conn));
716 return;
718 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
719 /* queue the command on the outbuf */
720 directory_send_command(conn, dir_purpose, 0, resource,
721 payload, payload_len, if_modified_since);
722 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
723 connection_start_reading(TO_CONN(linked_conn));
727 /** Return true iff anything we say on <b>conn</b> is being encrypted before
728 * we send it to the client/server. */
730 connection_dir_is_encrypted(dir_connection_t *conn)
732 /* Right now it's sufficient to see if conn is or has been linked, since
733 * the only thing it could be linked to is an edge connection on a
734 * circuit, and the only way it could have been unlinked is at the edge
735 * connection getting closed.
737 return TO_CONN(conn)->linked;
740 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
741 * are as in directory_initiate_command.
743 static void
744 directory_send_command(dir_connection_t *conn,
745 int purpose, int direct, const char *resource,
746 const char *payload, size_t payload_len,
747 time_t if_modified_since)
749 char proxystring[256];
750 char proxyauthstring[256];
751 char hoststring[128];
752 char imsstring[RFC1123_TIME_LEN+32];
753 char *url;
754 char request[8192];
755 const char *httpcommand = NULL;
756 size_t len;
758 tor_assert(conn);
759 tor_assert(conn->_base.type == CONN_TYPE_DIR);
761 tor_free(conn->requested_resource);
762 if (resource)
763 conn->requested_resource = tor_strdup(resource);
765 /* come up with a string for which Host: we want */
766 if (conn->_base.port == 80) {
767 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
768 } else {
769 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
770 conn->_base.address, conn->_base.port);
773 /* Format if-modified-since */
774 if (!if_modified_since) {
775 imsstring[0] = '\0';
776 } else {
777 char b[RFC1123_TIME_LEN+1];
778 format_rfc1123_time(b, if_modified_since);
779 tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
782 /* come up with some proxy lines, if we're using one. */
783 if (direct && get_options()->HttpProxy) {
784 char *base64_authenticator=NULL;
785 const char *authenticator = get_options()->HttpProxyAuthenticator;
787 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
788 if (authenticator) {
789 base64_authenticator = alloc_http_authenticator(authenticator);
790 if (!base64_authenticator)
791 log_warn(LD_BUG, "Encoding http authenticator failed");
793 if (base64_authenticator) {
794 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
795 "\r\nProxy-Authorization: Basic %s",
796 base64_authenticator);
797 tor_free(base64_authenticator);
798 } else {
799 proxyauthstring[0] = 0;
801 } else {
802 proxystring[0] = 0;
803 proxyauthstring[0] = 0;
806 switch (purpose) {
807 case DIR_PURPOSE_FETCH_DIR:
808 tor_assert(!resource);
809 tor_assert(!payload);
810 httpcommand = "GET";
811 url = tor_strdup("/tor/dir.z");
812 break;
813 case DIR_PURPOSE_FETCH_RUNNING_LIST:
814 tor_assert(!resource);
815 tor_assert(!payload);
816 httpcommand = "GET";
817 url = tor_strdup("/tor/running-routers");
818 break;
819 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
820 httpcommand = "GET";
821 len = strlen(resource)+32;
822 url = tor_malloc(len);
823 tor_snprintf(url, len, "/tor/status/%s", resource);
824 break;
825 case DIR_PURPOSE_FETCH_CONSENSUS:
826 tor_assert(!resource);
827 tor_assert(!payload);
828 httpcommand = "GET";
829 url = tor_strdup("/tor/status-vote/current/consensus.z");
830 break;
831 case DIR_PURPOSE_FETCH_CERTIFICATE:
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/keys/%s", resource);
838 break;
839 case DIR_PURPOSE_FETCH_STATUS_VOTE:
840 tor_assert(resource);
841 tor_assert(!payload);
842 httpcommand = "GET";
843 len = strlen(resource)+32;
844 url = tor_malloc(len);
845 tor_snprintf(url, len, "/tor/status-vote/next/%s.z", resource);
846 break;
847 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
848 tor_assert(!resource);
849 tor_assert(!payload);
850 httpcommand = "GET";
851 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
852 break;
853 case DIR_PURPOSE_FETCH_SERVERDESC:
854 httpcommand = "GET";
855 len = strlen(resource)+32;
856 url = tor_malloc(len);
857 tor_snprintf(url, len, "/tor/server/%s", resource);
858 break;
859 case DIR_PURPOSE_FETCH_EXTRAINFO:
860 httpcommand = "GET";
861 len = strlen(resource)+32;
862 url = tor_malloc(len);
863 tor_snprintf(url, len, "/tor/extra/%s", resource);
864 break;
865 case DIR_PURPOSE_UPLOAD_DIR:
866 tor_assert(!resource);
867 tor_assert(payload);
868 httpcommand = "POST";
869 url = tor_strdup("/tor/");
870 break;
871 case DIR_PURPOSE_UPLOAD_VOTE:
872 tor_assert(!resource);
873 tor_assert(payload);
874 httpcommand = "POST";
875 url = tor_strdup("/tor/post/vote");
876 break;
877 case DIR_PURPOSE_UPLOAD_SIGNATURES:
878 tor_assert(!resource);
879 tor_assert(payload);
880 httpcommand = "POST";
881 url = tor_strdup("/tor/post/consensus-signature");
882 break;
883 case DIR_PURPOSE_FETCH_RENDDESC:
884 tor_assert(resource);
885 tor_assert(!payload);
887 /* this must be true or we wouldn't be doing the lookup */
888 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN_BASE32);
889 /* This breaks the function abstraction. */
890 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
891 conn->rend_version = 0;
893 httpcommand = "GET";
894 /* Request the most recent versioned descriptor. */
895 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
896 // but that never got testing, and it wasn't a good design.)
897 len = strlen(resource)+32;
898 url = tor_malloc(len);
899 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
900 break;
901 case DIR_PURPOSE_FETCH_RENDDESC_V2:
902 tor_assert(resource);
903 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
904 /* Remember the query to refer to it when a response arrives. */
905 strlcpy(conn->rend_query, payload, sizeof(conn->rend_query));
906 conn->rend_version = 2;
907 payload = NULL;
908 httpcommand = "GET";
909 len = strlen(resource) + 32;
910 url = tor_malloc(len);
911 tor_snprintf(url, len, "/tor/rendezvous2/%s", resource);
912 break;
913 case DIR_PURPOSE_UPLOAD_RENDDESC:
914 tor_assert(!resource);
915 tor_assert(payload);
916 httpcommand = "POST";
917 url = tor_strdup("/tor/rendezvous/publish");
918 break;
919 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
920 tor_assert(!resource);
921 tor_assert(payload);
922 httpcommand = "POST";
923 url = tor_strdup("/tor/rendezvous2/publish");
924 break;
925 default:
926 tor_assert(0);
927 return;
930 if (strlen(proxystring) + strlen(url) >= 4096) {
931 log_warn(LD_BUG,
932 "Squid does not like URLs longer than 4095 bytes, and this "
933 "one is %d bytes long: %s%s",
934 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
937 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
938 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
939 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
940 tor_free(url);
942 if (!strcmp(httpcommand, "GET") && !payload) {
943 tor_snprintf(request, sizeof(request),
944 " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
945 hoststring,
946 imsstring,
947 proxyauthstring);
948 } else {
949 tor_snprintf(request, sizeof(request),
950 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
951 payload ? (unsigned long)payload_len : 0,
952 hoststring,
953 imsstring,
954 proxyauthstring);
956 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
958 if (payload) {
959 /* then send the payload afterwards too */
960 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
964 /** Parse an HTTP request string <b>headers</b> of the form
965 * \verbatim
966 * "\%s [http[s]://]\%s HTTP/1..."
967 * \endverbatim
968 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
969 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
970 * so it does. Return 0.
971 * Otherwise, return -1.
973 static int
974 parse_http_url(const char *headers, char **url)
976 char *s, *start, *tmp;
978 s = (char *)eat_whitespace_no_nl(headers);
979 if (!*s) return -1;
980 s = (char *)find_whitespace(s); /* get past GET/POST */
981 if (!*s) return -1;
982 s = (char *)eat_whitespace_no_nl(s);
983 if (!*s) return -1;
984 start = s; /* this is it, assuming it's valid */
985 s = (char *)find_whitespace(start);
986 if (!*s) return -1;
988 /* tolerate the http[s] proxy style of putting the hostname in the url */
989 if (s-start >= 4 && !strcmpstart(start,"http")) {
990 tmp = start + 4;
991 if (*tmp == 's')
992 tmp++;
993 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
994 tmp = strchr(tmp+3, '/');
995 if (tmp && tmp < s) {
996 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
997 start = tmp;
1002 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
1003 *url = tor_malloc(s - start + 5);
1004 strlcpy(*url,"/tor", s-start+5);
1005 strlcat((*url)+4, start, s-start+1);
1006 } else {
1007 *url = tor_strndup(start, s-start);
1009 return 0;
1012 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1013 * <b>which</b>. The key should be given with a terminating colon and space;
1014 * this function copies everything after, up to but not including the
1015 * following \\r\\n. */
1016 static char *
1017 http_get_header(const char *headers, const char *which)
1019 const char *cp = headers;
1020 while (cp) {
1021 if (!strcasecmpstart(cp, which)) {
1022 char *eos;
1023 cp += strlen(which);
1024 if ((eos = strchr(cp,'\r')))
1025 return tor_strndup(cp, eos-cp);
1026 else
1027 return tor_strdup(cp);
1029 cp = strchr(cp, '\n');
1030 if (cp)
1031 ++cp;
1033 return NULL;
1036 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1037 * <b>conn</b>-\>address to describe our best guess of the address that
1038 * originated this HTTP request. */
1039 static void
1040 http_set_address_origin(const char *headers, connection_t *conn)
1042 char *fwd;
1044 fwd = http_get_header(headers, "Forwarded-For: ");
1045 if (!fwd)
1046 fwd = http_get_header(headers, "X-Forwarded-For: ");
1047 if (fwd) {
1048 struct in_addr in;
1049 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
1050 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
1051 escaped(fwd));
1052 tor_free(fwd);
1053 return;
1055 tor_free(conn->address);
1056 conn->address = tor_strdup(fwd);
1057 tor_free(fwd);
1061 /** Parse an HTTP response string <b>headers</b> of the form
1062 * \verbatim
1063 * "HTTP/1.\%d \%d\%s\r\n...".
1064 * \endverbatim
1066 * If it's well-formed, assign the status code to *<b>code</b> and
1067 * return 0. Otherwise, return -1.
1069 * On success: If <b>date</b> is provided, set *date to the Date
1070 * header in the http headers, or 0 if no such header is found. If
1071 * <b>compression</b> is provided, set *<b>compression</b> to the
1072 * compression method given in the Content-Encoding header, or 0 if no
1073 * such header is found, or -1 if the value of the header is not
1074 * recognized. If <b>reason</b> is provided, strdup the reason string
1075 * into it.
1078 parse_http_response(const char *headers, int *code, time_t *date,
1079 compress_method_t *compression, char **reason)
1081 int n1, n2;
1082 char datestr[RFC1123_TIME_LEN+1];
1083 smartlist_t *parsed_headers;
1084 tor_assert(headers);
1085 tor_assert(code);
1087 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1089 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
1090 (n1 != 0 && n1 != 1) ||
1091 (n2 < 100 || n2 >= 600)) {
1092 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1093 return -1;
1095 *code = n2;
1097 parsed_headers = smartlist_create();
1098 smartlist_split_string(parsed_headers, headers, "\n",
1099 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1100 if (reason) {
1101 smartlist_t *status_line_elements = smartlist_create();
1102 tor_assert(smartlist_len(parsed_headers));
1103 smartlist_split_string(status_line_elements,
1104 smartlist_get(parsed_headers, 0),
1105 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1106 tor_assert(smartlist_len(status_line_elements) <= 3);
1107 if (smartlist_len(status_line_elements) == 3) {
1108 *reason = smartlist_get(status_line_elements, 2);
1109 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1111 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1112 smartlist_free(status_line_elements);
1114 if (date) {
1115 *date = 0;
1116 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1117 if (!strcmpstart(s, "Date: ")) {
1118 strlcpy(datestr, s+6, sizeof(datestr));
1119 /* This will do nothing on failure, so we don't need to check
1120 the result. We shouldn't warn, since there are many other valid
1121 date formats besides the one we use. */
1122 parse_rfc1123_time(datestr, date);
1123 break;
1126 if (compression) {
1127 const char *enc = NULL;
1128 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1129 if (!strcmpstart(s, "Content-Encoding: ")) {
1130 enc = s+18; break;
1132 if (!enc || !strcmp(enc, "identity")) {
1133 *compression = NO_METHOD;
1134 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1135 *compression = ZLIB_METHOD;
1136 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1137 *compression = GZIP_METHOD;
1138 } else {
1139 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1140 escaped(enc));
1141 *compression = UNKNOWN_METHOD;
1144 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1145 smartlist_free(parsed_headers);
1147 return 0;
1150 /** Return true iff <b>body</b> doesn't start with a plausible router or
1151 * running-list or directory opening. This is a sign of possible compression.
1153 static int
1154 body_is_plausible(const char *body, size_t len, int purpose)
1156 int i;
1157 if (len == 0)
1158 return 1; /* empty bodies don't need decompression */
1159 if (len < 32)
1160 return 0;
1161 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
1162 if (!strcmpstart(body,"router") ||
1163 !strcmpstart(body,"signed-directory") ||
1164 !strcmpstart(body,"network-status") ||
1165 !strcmpstart(body,"running-routers"))
1166 return 1;
1167 for (i=0;i<32;++i) {
1168 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1169 return 0;
1171 return 1;
1172 } else {
1173 return 1;
1177 /** Called when we've just fetched a bunch of router descriptors in
1178 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1179 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1180 * is true, or identity digests otherwise. Parse the descriptors, validate
1181 * them, and annotate them as having purpose <b>purpose</b> and as having been
1182 * downloaded from <b>source</b>. */
1183 static void
1184 load_downloaded_routers(const char *body, smartlist_t *which,
1185 int descriptor_digests,
1186 int router_purpose,
1187 const char *source)
1189 char buf[256];
1190 char time_buf[ISO_TIME_LEN+1];
1191 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1192 format_iso_time(time_buf, time(NULL));
1193 tor_assert(source);
1195 if (tor_snprintf(buf, sizeof(buf),
1196 "@downloaded-at %s\n"
1197 "@source %s\n"
1198 "%s%s%s", time_buf, escaped(source),
1199 !general ? "@purpose " : "",
1200 !general ? router_purpose_to_string(router_purpose) : "",
1201 !general ? "\n" : "")<0)
1202 return;
1204 router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1205 descriptor_digests, buf);
1208 /** We are a client, and we've finished reading the server's
1209 * response. Parse it and act appropriately.
1211 * If we're still happy with using this directory server in the future, return
1212 * 0. Otherwise return -1; and the caller should consider trying the request
1213 * again.
1215 * The caller will take care of marking the connection for close.
1217 static int
1218 connection_dir_client_reached_eof(dir_connection_t *conn)
1220 char *body;
1221 char *headers;
1222 char *reason = NULL;
1223 size_t body_len=0, orig_len=0;
1224 int status_code;
1225 time_t date_header=0;
1226 int delta;
1227 compress_method_t compression;
1228 int plausible;
1229 int skewed=0;
1230 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1231 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
1232 int was_compressed=0;
1233 time_t now = time(NULL);
1235 switch (fetch_from_buf_http(conn->_base.inbuf,
1236 &headers, MAX_HEADERS_SIZE,
1237 &body, &body_len, MAX_DIR_DL_SIZE,
1238 allow_partial)) {
1239 case -1: /* overflow */
1240 log_warn(LD_PROTOCOL,
1241 "'fetch' response too large (server '%s:%d'). Closing.",
1242 conn->_base.address, conn->_base.port);
1243 return -1;
1244 case 0:
1245 log_info(LD_HTTP,
1246 "'fetch' response not all here, but we're at eof. Closing.");
1247 return -1;
1248 /* case 1, fall through */
1250 orig_len = body_len;
1252 if (parse_http_response(headers, &status_code, &date_header,
1253 &compression, &reason) < 0) {
1254 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1255 conn->_base.address, conn->_base.port);
1256 tor_free(body); tor_free(headers);
1257 return -1;
1259 if (!reason) reason = tor_strdup("[no reason given]");
1261 log_debug(LD_DIR,
1262 "Received response from directory server '%s:%d': %d %s",
1263 conn->_base.address, conn->_base.port, status_code,
1264 escaped(reason));
1266 /* now check if it's got any hints for us about our IP address. */
1267 if (conn->dirconn_direct) {
1268 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1269 if (guess) {
1270 router_new_address_suggestion(guess, conn);
1271 tor_free(guess);
1275 if (date_header > 0) {
1276 /* The date header was written very soon after we sent our request,
1277 * so compute the skew as the difference between sending the request
1278 * and the date header. (We used to check now-date_header, but that's
1279 * inaccurate if we spend a lot of time downloading.)
1281 delta = conn->_base.timestamp_lastwritten - date_header;
1282 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1283 char dbuf[64];
1284 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1285 format_time_interval(dbuf, sizeof(dbuf), delta);
1286 log_fn(trusted ? LOG_WARN : LOG_INFO,
1287 LD_HTTP,
1288 "Received directory with skewed time (server '%s:%d'): "
1289 "It seems that our clock is %s by %s, or that theirs is %s. "
1290 "Tor requires an accurate clock to work: please check your time "
1291 "and date settings.",
1292 conn->_base.address, conn->_base.port,
1293 delta>0 ? "ahead" : "behind", dbuf,
1294 delta>0 ? "behind" : "ahead");
1295 skewed = 1; /* don't check the recommended-versions line */
1296 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1297 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
1298 delta, conn->_base.address, conn->_base.port);
1299 } else {
1300 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1301 "we are %d seconds skewed. (That's okay.)", delta);
1304 (void) skewed; /* skewed isn't used yet. */
1306 if (status_code == 503 && body_len < 16) {
1307 routerstatus_t *rs;
1308 trusted_dir_server_t *ds;
1309 log_info(LD_DIR,"Received http status code %d (%s) from server "
1310 "'%s:%d'. I'll try again soon.",
1311 status_code, escaped(reason), conn->_base.address,
1312 conn->_base.port);
1313 if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
1314 rs->last_dir_503_at = now;
1315 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1316 ds->fake_status.last_dir_503_at = now;
1318 tor_free(body); tor_free(headers); tor_free(reason);
1319 return -1;
1320 } else if (status_code == 503) {
1321 /* XXXX022 Remove this once every server with bug 539 is obsolete. */
1322 log_info(LD_DIR, "Server at '%s:%d' sent us a 503 response, but included "
1323 "a body anyway. We'll pretend it gave us a 200.",
1324 conn->_base.address, conn->_base.port);
1325 status_code = 200;
1328 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1329 if (compression != NO_METHOD || !plausible) {
1330 char *new_body = NULL;
1331 size_t new_len = 0;
1332 compress_method_t guessed = detect_compression_method(body, body_len);
1333 if (compression == UNKNOWN_METHOD || guessed != compression) {
1334 /* Tell the user if we don't believe what we're told about compression.*/
1335 const char *description1, *description2;
1336 if (compression == ZLIB_METHOD)
1337 description1 = "as deflated";
1338 else if (compression == GZIP_METHOD)
1339 description1 = "as gzipped";
1340 else if (compression == NO_METHOD)
1341 description1 = "as uncompressed";
1342 else
1343 description1 = "with an unknown Content-Encoding";
1344 if (guessed == ZLIB_METHOD)
1345 description2 = "deflated";
1346 else if (guessed == GZIP_METHOD)
1347 description2 = "gzipped";
1348 else if (!plausible)
1349 description2 = "confusing binary junk";
1350 else
1351 description2 = "uncompressed";
1353 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1354 "but it seems to be %s.%s",
1355 conn->_base.address, conn->_base.port, description1,
1356 description2,
1357 (compression>0 && guessed>0)?" Trying both.":"");
1359 /* Try declared compression first if we can. */
1360 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1361 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1362 !allow_partial, LOG_PROTOCOL_WARN);
1363 /* Okay, if that didn't work, and we think that it was compressed
1364 * differently, try that. */
1365 if (!new_body &&
1366 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1367 compression != guessed)
1368 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1369 !allow_partial, LOG_PROTOCOL_WARN);
1370 /* If we're pretty sure that we have a compressed directory, and
1371 * we didn't manage to uncompress it, then warn and bail. */
1372 if (!plausible && !new_body) {
1373 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1374 "Unable to decompress HTTP body (server '%s:%d').",
1375 conn->_base.address, conn->_base.port);
1376 tor_free(body); tor_free(headers); tor_free(reason);
1377 return -1;
1379 if (new_body) {
1380 tor_free(body);
1381 body = new_body;
1382 body_len = new_len;
1383 was_compressed = 1;
1387 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
1388 /* fetch/process the directory to cache it. */
1389 log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
1390 (int)body_len, conn->_base.address, conn->_base.port);
1391 if (status_code != 200) {
1392 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1393 "'%s:%d' while fetching directory. I'll try again soon.",
1394 status_code, escaped(reason), conn->_base.address,
1395 conn->_base.port);
1396 tor_free(body); tor_free(headers); tor_free(reason);
1397 return -1;
1399 if (router_parse_directory(body) < 0) {
1400 log_notice(LD_DIR,"I failed to parse the directory I fetched from "
1401 "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
1403 note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
1406 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
1407 /* just update our list of running routers, if this list is new info */
1408 log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
1409 if (status_code != 200) {
1410 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1411 "'%s:%d' while fetching running-routers. I'll try again soon.",
1412 status_code, escaped(reason), conn->_base.address,
1413 conn->_base.port);
1414 tor_free(body); tor_free(headers); tor_free(reason);
1415 return -1;
1417 if (router_parse_runningrouters(body)<0) {
1418 log_warn(LD_DIR,
1419 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1420 conn->_base.address, conn->_base.port);
1421 tor_free(body); tor_free(headers); tor_free(reason);
1422 return -1;
1424 note_request(was_compressed?"dl/running-routers.z":
1425 "dl/running-routers", orig_len);
1428 if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
1429 smartlist_t *which = NULL;
1430 networkstatus_source_t source;
1431 char *cp;
1432 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1433 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1434 if (status_code != 200) {
1435 log_warn(LD_DIR,
1436 "Received http status code %d (%s) from server "
1437 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1438 status_code, escaped(reason), conn->_base.address,
1439 conn->_base.port, conn->requested_resource);
1440 tor_free(body); tor_free(headers); tor_free(reason);
1441 connection_dir_download_networkstatus_failed(conn, status_code);
1442 return -1;
1444 note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
1445 if (conn->requested_resource &&
1446 !strcmpstart(conn->requested_resource,"fp/")) {
1447 source = NS_FROM_DIR_BY_FP;
1448 which = smartlist_create();
1449 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1450 which, NULL, 0, 0);
1451 } else if (conn->requested_resource &&
1452 !strcmpstart(conn->requested_resource, "all")) {
1453 source = NS_FROM_DIR_ALL;
1454 which = smartlist_create();
1455 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1456 trusted_dir_server_t *, ds,
1458 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1459 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1460 smartlist_add(which, hex);
1462 } else {
1463 /* XXXX Can we even end up here? -- weasel*/
1464 source = NS_FROM_DIR_BY_FP;
1465 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1466 "for it by fp, nor did we ask for all.");
1468 cp = body;
1469 while (*cp) {
1470 char *next = strstr(cp, "\nnetwork-status-version");
1471 if (next)
1472 next[1] = '\0';
1473 /* learn from it, and then remove it from 'which' */
1474 if (router_set_networkstatus_v2(cp, now, source, which)<0)
1475 break;
1476 if (next) {
1477 next[1] = 'n';
1478 cp = next+1;
1479 } else
1480 break;
1482 /* launches router downloads as needed */
1483 routers_update_all_from_networkstatus(now, 2);
1484 directory_info_has_arrived(now, 0);
1485 if (which) {
1486 if (smartlist_len(which)) {
1487 dir_networkstatus_download_failed(which, status_code);
1489 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1490 smartlist_free(which);
1494 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1495 int r;
1496 if (status_code != 200) {
1497 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1498 log(severity, LD_DIR,
1499 "Received http status code %d (%s) from server "
1500 "'%s:%d' while fetching consensus directory.",
1501 status_code, escaped(reason), conn->_base.address,
1502 conn->_base.port);
1503 tor_free(body); tor_free(headers); tor_free(reason);
1504 networkstatus_consensus_download_failed(status_code);
1505 return -1;
1507 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1508 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1509 if ((r=networkstatus_set_current_consensus(body, 0))<0) {
1510 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1511 "Unable to load consensus directory downloaded from "
1512 "server '%s:%d'", conn->_base.address, conn->_base.port);
1513 tor_free(body); tor_free(headers); tor_free(reason);
1514 networkstatus_consensus_download_failed(0);
1515 return -1;
1517 /* launches router downloads as needed */
1518 routers_update_all_from_networkstatus(now, 3);
1519 directory_info_has_arrived(now, 0);
1520 log_info(LD_DIR, "Successfully loaded consensus.");
1523 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1524 if (status_code != 200) {
1525 log_warn(LD_DIR,
1526 "Received http status code %d (%s) from server "
1527 "'%s:%d' while fetching \"/tor/keys/%s\".",
1528 status_code, escaped(reason), conn->_base.address,
1529 conn->_base.port, conn->requested_resource);
1530 connection_dir_download_cert_failed(conn, status_code);
1531 tor_free(body); tor_free(headers); tor_free(reason);
1532 return -1;
1534 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1535 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1536 if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) {
1537 log_warn(LD_DIR, "Unable to parse fetched certificates");
1538 connection_dir_download_cert_failed(conn, status_code);
1539 } else {
1540 directory_info_has_arrived(now, 0);
1541 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1544 if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1545 const char *msg;
1546 int st;
1547 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1548 (int) body_len, conn->_base.address, conn->_base.port);
1549 if (status_code != 200) {
1550 log_warn(LD_DIR,
1551 "Received http status code %d (%s) from server "
1552 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1553 status_code, escaped(reason), conn->_base.address,
1554 conn->_base.port, conn->requested_resource);
1555 tor_free(body); tor_free(headers); tor_free(reason);
1556 return -1;
1558 dirvote_add_vote(body, &msg, &st);
1559 if (st > 299) {
1560 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1561 } else {
1562 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1565 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1566 const char *msg = NULL;
1567 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1568 (int) body_len, conn->_base.address, conn->_base.port);
1569 if (status_code != 200) {
1570 log_warn(LD_DIR,
1571 "Received http status code %d (%s) from server "
1572 "'%s:%d' while fetching \"/tor/status-vote/consensus-signatures.z\".",
1573 status_code, escaped(reason), conn->_base.address,
1574 conn->_base.port);
1575 tor_free(body); tor_free(headers); tor_free(reason);
1576 return -1;
1578 if (dirvote_add_signatures(body, conn->_base.address, &msg)<0) {
1579 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1580 conn->_base.address, conn->_base.port, msg?msg:"???");
1584 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1585 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1586 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1587 smartlist_t *which = NULL;
1588 int n_asked_for = 0;
1589 int descriptor_digests = conn->requested_resource &&
1590 !strcmpstart(conn->requested_resource,"d/");
1591 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1592 was_ei ? "extra server info" : "server info",
1593 (int)body_len, conn->_base.address, conn->_base.port);
1594 if (was_ei)
1595 note_request(was_compressed?"dl/extra.z":"dl/extra", orig_len);
1596 else
1597 note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
1598 if (conn->requested_resource &&
1599 (!strcmpstart(conn->requested_resource,"d/") ||
1600 !strcmpstart(conn->requested_resource,"fp/"))) {
1601 which = smartlist_create();
1602 dir_split_resource_into_fingerprints(conn->requested_resource +
1603 (descriptor_digests ? 2 : 3),
1604 which, NULL, 0, 0);
1605 n_asked_for = smartlist_len(which);
1607 if (status_code != 200) {
1608 int dir_okay = status_code == 404 ||
1609 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1610 /* 404 means that it didn't have them; no big deal.
1611 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1612 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1613 "Received http status code %d (%s) from server '%s:%d' "
1614 "while fetching \"/tor/server/%s\". I'll try again soon.",
1615 status_code, escaped(reason), conn->_base.address,
1616 conn->_base.port, conn->requested_resource);
1617 if (!which) {
1618 connection_dir_download_routerdesc_failed(conn);
1619 } else {
1620 dir_routerdesc_download_failed(which, status_code,
1621 conn->router_purpose,
1622 was_ei, descriptor_digests);
1623 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1624 smartlist_free(which);
1626 tor_free(body); tor_free(headers); tor_free(reason);
1627 return dir_okay ? 0 : -1;
1629 /* Learn the routers, assuming we requested by fingerprint or "all"
1630 * or "authority".
1632 * We use "authority" to fetch our own descriptor for
1633 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1634 * the output of "authority" requests unless we are using bridges,
1635 * since otherwise they'll be the response from reachability tests,
1636 * and we don't really want to add that to our routerlist. */
1637 if (which || (conn->requested_resource &&
1638 (!strcmpstart(conn->requested_resource, "all") ||
1639 (!strcmpstart(conn->requested_resource, "authority") &&
1640 get_options()->UseBridges)))) {
1641 /* as we learn from them, we remove them from 'which' */
1642 if (was_ei) {
1643 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1644 descriptor_digests);
1645 } else {
1646 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1647 // descriptor_digests, conn->router_purpose);
1648 load_downloaded_routers(body, which, descriptor_digests,
1649 conn->router_purpose,
1650 conn->_base.address);
1651 directory_info_has_arrived(now, 0);
1654 if (which) { /* mark remaining ones as failed */
1655 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1656 n_asked_for-smartlist_len(which), n_asked_for,
1657 was_ei ? "extra-info documents" : "router descriptors",
1658 conn->_base.address, (int)conn->_base.port);
1659 if (smartlist_len(which)) {
1660 dir_routerdesc_download_failed(which, status_code,
1661 conn->router_purpose,
1662 was_ei, descriptor_digests);
1664 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1665 smartlist_free(which);
1667 if (directory_conn_is_self_reachability_test(conn))
1668 router_dirport_found_reachable();
1671 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1672 switch (status_code) {
1673 case 200: {
1674 trusted_dir_server_t *ds =
1675 router_get_trusteddirserver_by_digest(conn->identity_digest);
1676 char *rejected_hdr = http_get_header(headers,
1677 "X-Descriptor-Not-New: ");
1678 int rejected = 0;
1679 if (rejected_hdr) {
1680 if (!strcmp(rejected_hdr, "Yes")) {
1681 /* XXXX020rc use this information; be sure to upload next one
1682 * sooner. -NM Given that we don't know of any bugs here, and
1683 * it's more insuring against the future, could this wait
1684 * until 0.2.1? -RD */
1685 rejected = 1;
1687 tor_free(rejected_hdr);
1689 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1690 "descriptor: finished.");
1691 control_event_server_status(
1692 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1693 conn->_base.address, conn->_base.port);
1695 ds->has_accepted_serverdesc = 1;
1696 if (directories_have_accepted_server_descriptor())
1697 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1699 break;
1700 case 400:
1701 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1702 "dirserver '%s:%d'. Please correct.",
1703 escaped(reason), conn->_base.address, conn->_base.port);
1704 control_event_server_status(LOG_WARN,
1705 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1706 conn->_base.address, conn->_base.port, escaped(reason));
1707 break;
1708 default:
1709 log_warn(LD_GENERAL,
1710 "http status %d (%s) reason unexpected while uploading "
1711 "descriptor to server '%s:%d').",
1712 status_code, escaped(reason), conn->_base.address,
1713 conn->_base.port);
1714 break;
1716 /* return 0 in all cases, since we don't want to mark any
1717 * dirservers down just because they don't like us. */
1720 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
1721 switch (status_code) {
1722 case 200: {
1723 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
1724 conn->_base.address, conn->_base.port);
1726 break;
1727 case 400:
1728 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1729 "vote to dirserver '%s:%d'. Please correct.",
1730 escaped(reason), conn->_base.address, conn->_base.port);
1731 break;
1732 default:
1733 log_warn(LD_GENERAL,
1734 "http status %d (%s) reason unexpected while uploading "
1735 "vote to server '%s:%d').",
1736 status_code, escaped(reason), conn->_base.address,
1737 conn->_base.port);
1738 break;
1740 /* return 0 in all cases, since we don't want to mark any
1741 * dirservers down just because they don't like us. */
1744 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
1745 switch (status_code) {
1746 case 200: {
1747 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
1748 conn->_base.address, conn->_base.port);
1750 break;
1751 case 400:
1752 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1753 "signatures to dirserver '%s:%d'. Please correct.",
1754 escaped(reason), conn->_base.address, conn->_base.port);
1755 break;
1756 default:
1757 log_warn(LD_GENERAL,
1758 "http status %d (%s) reason unexpected while uploading "
1759 "signatures to server '%s:%d').",
1760 status_code, escaped(reason), conn->_base.address,
1761 conn->_base.port);
1762 break;
1764 /* return 0 in all cases, since we don't want to mark any
1765 * dirservers down just because they don't like us. */
1768 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1769 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1770 "(%s))",
1771 (int)body_len, status_code, escaped(reason));
1772 switch (status_code) {
1773 case 200:
1774 if (rend_cache_store(body, body_len, 0) < 0) {
1775 log_warn(LD_REND,"Failed to fetch rendezvous descriptor.");
1776 /* Any pending rendezvous attempts will notice when
1777 * connection_about_to_close_connection()
1778 * cleans this dir conn up. */
1779 /* We could retry. But since v0 descriptors are going out of
1780 * style, it isn't worth the hassle. We'll do better in v2. */
1781 } else {
1782 /* success. notify pending connections about this. */
1783 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1784 rend_client_desc_here(conn->rend_query);
1786 break;
1787 case 404:
1788 /* Not there. Pending connections will be notified when
1789 * connection_about_to_close_connection() cleans this conn up. */
1790 break;
1791 case 400:
1792 log_warn(LD_REND,
1793 "http status 400 (%s). Dirserver didn't like our "
1794 "rendezvous query?", escaped(reason));
1795 break;
1796 default:
1797 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1798 "fetching hidden service descriptor (server '%s:%d').",
1799 status_code, escaped(reason), conn->_base.address,
1800 conn->_base.port);
1801 break;
1805 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
1806 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1807 "(%s))",
1808 (int)body_len, status_code, escaped(reason));
1809 switch (status_code) {
1810 case 200:
1811 switch (rend_cache_store_v2_desc_as_client(body, NULL)) {
1812 case -2:
1813 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
1814 "Retrying at another directory.");
1815 /* We'll retry when connection_about_to_close_connection()
1816 * cleans this dir conn up. */
1817 break;
1818 case -1:
1819 /* We already have a v0 descriptor here. Ignoring this one
1820 * and _not_ performing another request. */
1821 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1822 "descriptor, but we already have a v0 descriptor.");
1823 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1824 break;
1825 default:
1826 /* success. notify pending connections about this. */
1827 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1828 "descriptor.");
1829 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1830 rend_client_desc_here(conn->rend_query);
1831 break;
1833 break;
1834 case 404:
1835 /* Not there. We'll retry when
1836 * connection_about_to_close_connection() cleans this conn up. */
1837 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
1838 "Retrying at another directory.");
1839 break;
1840 case 400:
1841 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1842 "http status 400 (%s). Dirserver didn't like our "
1843 "v2 rendezvous query? Retrying at another directory.",
1844 escaped(reason));
1845 break;
1846 default:
1847 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1848 "http status %d (%s) response unexpected while "
1849 "fetching v2 hidden service descriptor (server '%s:%d'). "
1850 "Retrying at another directory.",
1851 status_code, escaped(reason), conn->_base.address,
1852 conn->_base.port);
1853 break;
1857 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
1858 conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
1859 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
1860 "(%s))",
1861 status_code, escaped(reason));
1862 switch (status_code) {
1863 case 200:
1864 log_info(LD_REND,
1865 "Uploading rendezvous descriptor: finished with status "
1866 "200 (%s)", escaped(reason));
1867 break;
1868 case 400:
1869 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1870 "'%s:%d'. Malformed rendezvous descriptor?",
1871 escaped(reason), conn->_base.address, conn->_base.port);
1872 break;
1873 case 503:
1874 log_info(LD_REND,"http status 503 (%s) response from dirserver "
1875 "'%s:%d'. Node is (currently) not acting as v2 hidden "
1876 "service directory.",
1877 escaped(reason), conn->_base.address, conn->_base.port);
1878 break;
1879 default:
1880 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1881 "'%s:%d').",
1882 status_code, escaped(reason), conn->_base.address,
1883 conn->_base.port);
1884 break;
1887 tor_free(body); tor_free(headers); tor_free(reason);
1888 return 0;
1891 /** Called when a directory connection reaches EOF. */
1893 connection_dir_reached_eof(dir_connection_t *conn)
1895 int retval;
1896 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
1897 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
1898 conn->_base.state);
1899 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
1900 connection_mark_for_close(TO_CONN(conn));
1901 return -1;
1904 retval = connection_dir_client_reached_eof(conn);
1905 if (retval == 0) /* success */
1906 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
1907 connection_mark_for_close(TO_CONN(conn));
1908 return retval;
1911 /** If any directory object is arriving, and it's over 10MB large, we're
1912 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1913 * ask for more than 96 router descriptors at a time.)
1915 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1917 /** Read handler for directory connections. (That's connections <em>to</em>
1918 * directory servers and connections <em>at</em> directory servers.)
1921 connection_dir_process_inbuf(dir_connection_t *conn)
1923 tor_assert(conn);
1924 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1926 /* Directory clients write, then read data until they receive EOF;
1927 * directory servers read data until they get an HTTP command, then
1928 * write their response (when it's finished flushing, they mark for
1929 * close).
1932 /* If we're on the dirserver side, look for a command. */
1933 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1934 if (directory_handle_command(conn) < 0) {
1935 connection_mark_for_close(TO_CONN(conn));
1936 return -1;
1938 return 0;
1941 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
1942 log_warn(LD_HTTP, "Too much data received from directory connection: "
1943 "denial of service attempt, or you need to upgrade?");
1944 connection_mark_for_close(TO_CONN(conn));
1945 return -1;
1948 if (!conn->_base.inbuf_reached_eof)
1949 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1950 return 0;
1953 /** Create an http response for the client <b>conn</b> out of
1954 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1956 static void
1957 write_http_status_line(dir_connection_t *conn, int status,
1958 const char *reason_phrase)
1960 char buf[256];
1961 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1962 status, reason_phrase ? reason_phrase : "OK") < 0) {
1963 log_warn(LD_BUG,"status line too long.");
1964 return;
1966 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
1969 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1970 * with <b>type</b> as the Content-Type.
1972 * If <b>length</b> is nonnegative, it is the Content-Length.
1973 * If <b>encoding</b> is provided, it is the Content-Encoding.
1974 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1975 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1976 static void
1977 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
1978 const char *type, const char *encoding,
1979 const char *extra_headers,
1980 int cache_lifetime)
1982 char date[RFC1123_TIME_LEN+1];
1983 char tmp[1024];
1984 char *cp;
1985 time_t now = time(NULL);
1987 tor_assert(conn);
1989 format_rfc1123_time(date, now);
1990 cp = tmp;
1991 tor_snprintf(cp, sizeof(tmp),
1992 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
1993 date);
1994 cp += strlen(tmp);
1995 if (type) {
1996 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
1997 cp += strlen(cp);
1999 if (!is_local_IP(conn->_base.addr)) {
2000 /* Don't report the source address for a nearby/private connection.
2001 * Otherwise we tend to mis-report in cases where incoming ports are
2002 * being forwarded to a Tor server running behind the firewall. */
2003 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2004 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
2005 cp += strlen(cp);
2007 if (encoding) {
2008 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2009 "Content-Encoding: %s\r\n", encoding);
2010 cp += strlen(cp);
2012 if (length >= 0) {
2013 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2014 "Content-Length: %ld\r\n", (long)length);
2015 cp += strlen(cp);
2017 if (cache_lifetime > 0) {
2018 char expbuf[RFC1123_TIME_LEN+1];
2019 format_rfc1123_time(expbuf, now + cache_lifetime);
2020 /* We could say 'Cache-control: max-age=%d' here if we start doing
2021 * http/1.1 */
2022 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2023 "Expires: %s\r\n", expbuf);
2024 cp += strlen(cp);
2025 } else if (cache_lifetime == 0) {
2026 /* We could say 'Cache-control: no-cache' here if we start doing
2027 * http/1.1 */
2028 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2029 cp += strlen(cp);
2031 if (extra_headers)
2032 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2033 if (sizeof(tmp)-(cp-tmp) > 3)
2034 memcpy(cp, "\r\n", 3);
2035 else
2036 tor_assert(0);
2037 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2040 /** As write_http_response_header_impl, but sets encoding and content-typed
2041 * based on whether the response will be <b>compressed</b> or not. */
2042 static void
2043 write_http_response_header(dir_connection_t *conn, ssize_t length,
2044 int compressed, int cache_lifetime)
2046 write_http_response_header_impl(conn, length,
2047 compressed?"application/octet-stream":"text/plain",
2048 compressed?"deflate":"identity",
2049 NULL,
2050 cache_lifetime);
2053 /** Helper function: return 1 if there are any dir conns of purpose
2054 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
2055 * Else return 0.
2057 static int
2058 already_fetching_directory(int purpose)
2060 smartlist_t *conns = get_connection_array();
2061 SMARTLIST_FOREACH(conns, connection_t *, conn,
2063 if (conn->type == CONN_TYPE_DIR &&
2064 conn->purpose == purpose &&
2065 !conn->marked_for_close &&
2066 !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
2067 return 1;
2069 return 0;
2072 #ifdef INSTRUMENT_DOWNLOADS
2073 /** Map used to keep track of how much data we've up/downloaded in what kind
2074 * of request. Maps from request type to pointer to uint64_t. */
2075 static strmap_t *request_bytes_map = NULL;
2077 /** Called when we just transmitted or received <b>bytes</b> worth of data
2078 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2079 * <b>bytes</b> to the total associated with key. */
2080 static void
2081 note_request(const char *key, size_t bytes)
2083 uint64_t *n;
2084 if (!request_bytes_map)
2085 request_bytes_map = strmap_new();
2087 n = strmap_get(request_bytes_map, key);
2088 if (!n) {
2089 n = tor_malloc_zero(sizeof(uint64_t));
2090 strmap_set(request_bytes_map, key, n);
2092 *n += bytes;
2095 /** Return a newly allocated string holding a summary of bytes used per
2096 * request type. */
2097 char *
2098 directory_dump_request_log(void)
2100 smartlist_t *lines;
2101 char tmp[256];
2102 char *result;
2103 strmap_iter_t *iter;
2105 if (!request_bytes_map)
2106 request_bytes_map = strmap_new();
2108 lines = smartlist_create();
2110 for (iter = strmap_iter_init(request_bytes_map);
2111 !strmap_iter_done(iter);
2112 iter = strmap_iter_next(request_bytes_map, iter)) {
2113 const char *key;
2114 void *val;
2115 uint64_t *n;
2116 strmap_iter_get(iter, &key, &val);
2117 n = val;
2118 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT"\n",
2119 key, U64_PRINTF_ARG(*n));
2120 smartlist_add(lines, tor_strdup(tmp));
2122 smartlist_sort_strings(lines);
2123 result = smartlist_join_strings(lines, "", 0, NULL);
2124 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2125 smartlist_free(lines);
2126 return result;
2128 #else
2129 static void
2130 note_request(const char *key, size_t bytes)
2132 (void)key;
2133 (void)bytes;
2136 char *
2137 directory_dump_request_log(void)
2139 return tor_strdup("Not supported.");
2141 #endif
2143 /** Helper function: called when a dirserver gets a complete HTTP GET
2144 * request. Look for a request for a directory or for a rendezvous
2145 * service descriptor. On finding one, write a response into
2146 * conn-\>outbuf. If the request is unrecognized, send a 400.
2147 * Always return 0. */
2148 static int
2149 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2150 const char *body, size_t body_len)
2152 size_t dlen;
2153 char *url, *url_mem, *header;
2154 or_options_t *options = get_options();
2155 time_t if_modified_since = 0;
2156 int compressed;
2157 size_t url_len;
2159 /* We ignore the body of a GET request. */
2160 (void)body;
2161 (void)body_len;
2163 log_debug(LD_DIRSERV,"Received GET command.");
2165 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2167 if (parse_http_url(headers, &url) < 0) {
2168 write_http_status_line(conn, 400, "Bad request");
2169 return 0;
2171 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2172 struct tm tm;
2173 if (parse_http_time(header, &tm) == 0) {
2174 if_modified_since = tor_timegm(&tm);
2176 /* The correct behavior on a malformed If-Modified-Since header is to
2177 * act as if no If-Modified-Since header had been given. */
2178 tor_free(header);
2180 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2182 url_mem = url;
2183 url_len = strlen(url);
2184 compressed = url_len > 2 && !strcmp(url+url_len-2, ".z");
2185 if (compressed) {
2186 url[url_len-2] = '\0';
2187 url_len -= 2;
2190 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* dir fetch */
2191 cached_dir_t *d = dirserv_get_directory();
2193 if (!d) {
2194 log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
2195 "don't have a good one yet. Sending 503 Dir not available.");
2196 write_http_status_line(conn, 503, "Directory unavailable");
2197 /* try to get a new one now */
2198 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR) &&
2199 !should_delay_dir_fetches(options))
2200 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR,
2201 ROUTER_PURPOSE_GENERAL, NULL, 1);
2202 goto done;
2204 if (d->published < if_modified_since) {
2205 write_http_status_line(conn, 304, "Not modified");
2206 goto done;
2209 dlen = compressed ? d->dir_z_len : d->dir_len;
2211 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2212 log_info(LD_DIRSERV,
2213 "Client asked for the mirrored directory, but we've been "
2214 "writing too many bytes lately. Sending 503 Dir busy.");
2215 write_http_status_line(conn, 503, "Directory busy, try again later");
2216 goto done;
2219 note_request(url, dlen);
2221 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
2222 compressed?"compressed ":"");
2223 write_http_response_header(conn, dlen, compressed,
2224 FULL_DIR_CACHE_LIFETIME);
2225 conn->cached_dir = d;
2226 conn->cached_dir_offset = 0;
2227 if (!compressed)
2228 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2229 ++d->refcnt;
2231 /* Prime the connection with some data. */
2232 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
2233 connection_dirserv_flushed_some(conn);
2234 goto done;
2237 if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
2238 cached_dir_t *d = dirserv_get_runningrouters();
2239 if (!d) {
2240 write_http_status_line(conn, 503, "Directory unavailable");
2241 /* try to get a new one now */
2242 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST) &&
2243 !should_delay_dir_fetches(options))
2244 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST,
2245 ROUTER_PURPOSE_GENERAL, NULL, 1);
2246 goto done;
2248 if (d->published < if_modified_since) {
2249 write_http_status_line(conn, 304, "Not modified");
2250 goto done;
2252 dlen = compressed ? d->dir_z_len : d->dir_len;
2254 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2255 log_info(LD_DIRSERV,
2256 "Client asked for running-routers, but we've been "
2257 "writing too many bytes lately. Sending 503 Dir busy.");
2258 write_http_status_line(conn, 503, "Directory busy, try again later");
2259 goto done;
2261 note_request(url, dlen);
2262 write_http_response_header(conn, dlen, compressed,
2263 RUNNINGROUTERS_CACHE_LIFETIME);
2264 connection_write_to_buf(compressed ? d->dir_z : d->dir, dlen,
2265 TO_CONN(conn));
2266 goto done;
2269 if (!strcmpstart(url,"/tor/status/")
2270 || !strcmp(url, "/tor/status-vote/current/consensus")) {
2271 /* v2 or v3 network status fetch. */
2272 smartlist_t *dir_fps = smartlist_create();
2273 int is_v3 = !strcmpstart(url, "/tor/status-vote");
2274 const char *request_type = NULL;
2275 const char *key = url + strlen("/tor/status/");
2276 int lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2277 if (!is_v3) {
2278 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
2279 if (!strcmpstart(key, "fp/"))
2280 request_type = compressed?"/tor/status/fp.z":"/tor/status/fp";
2281 else if (!strcmpstart(key, "authority"))
2282 request_type = compressed?"/tor/status/authority.z":
2283 "/tor/status/authority";
2284 else if (!strcmpstart(key, "all"))
2285 request_type = compressed?"/tor/status/all.z":"/tor/status/all";
2286 else
2287 request_type = "/tor/status/?";
2288 } else {
2289 networkstatus_t *v = networkstatus_get_latest_consensus();
2290 time_t now = time(NULL);
2291 smartlist_add(dir_fps, tor_memdup("\0\0\0\0\0\0\0\0\0\0"
2292 "\0\0\0\0\0\0\0\0\0\0", 20));
2293 request_type = compressed?"v3.z":"v3";
2294 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2297 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2298 write_http_status_line(conn, 503, "Network status object unavailable");
2299 smartlist_free(dir_fps);
2300 goto done;
2303 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2304 write_http_status_line(conn, 404, "Not found");
2305 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2306 smartlist_free(dir_fps);
2307 goto done;
2308 } else if (!smartlist_len(dir_fps)) {
2309 write_http_status_line(conn, 304, "Not modified");
2310 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2311 smartlist_free(dir_fps);
2312 goto done;
2315 dlen = dirserv_estimate_data_size(dir_fps, 0, compressed);
2316 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2317 log_info(LD_DIRSERV,
2318 "Client asked for network status lists, but we've been "
2319 "writing too many bytes lately. Sending 503 Dir busy.");
2320 write_http_status_line(conn, 503, "Directory busy, try again later");
2321 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2322 smartlist_free(dir_fps);
2323 goto done;
2326 // note_request(request_type,dlen);
2327 (void) request_type;
2328 write_http_response_header(conn, -1, compressed,
2329 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2330 conn->fingerprint_stack = dir_fps;
2331 if (! compressed)
2332 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2334 /* Prime the connection with some data. */
2335 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2336 connection_dirserv_flushed_some(conn);
2337 goto done;
2340 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2341 !strcmpstart(url,"/tor/status-vote/next/")) {
2342 /* XXXX If-modified-since is only implemented for the current
2343 * consensus: that's probably fine, since it's the only vote document
2344 * people fetch much.*/
2345 int current;
2346 ssize_t body_len = 0;
2347 ssize_t estimated_len = 0;
2348 smartlist_t *items = smartlist_create();
2349 smartlist_t *dir_items = smartlist_create();
2350 int lifetime = 60; /* XXXX021 should actually use vote intervals. */
2351 url += strlen("/tor/status-vote/");
2352 current = !strcmpstart(url, "current/");
2353 url = strchr(url, '/');
2354 tor_assert(url);
2355 ++url;
2356 if (!strcmp(url, "consensus")) {
2357 const char *item;
2358 tor_assert(!current); /* we handle current consensus specially above,
2359 * since it wants to be spooled. */
2360 if ((item = dirvote_get_pending_consensus()))
2361 smartlist_add(items, (char*)item);
2362 } else if (!current && !strcmp(url, "consensus-signatures")) {
2363 /* XXXX the spec says that we should implement
2364 * current/consensus-signatures too. It doesn't seem to be needed,
2365 * though. */
2366 const char *item;
2367 if ((item=dirvote_get_pending_detached_signatures()))
2368 smartlist_add(items, (char*)item);
2369 } else if (!strcmp(url, "authority")) {
2370 const cached_dir_t *d;
2371 int flags = DGV_BY_ID |
2372 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2373 if ((d=dirvote_get_vote(NULL, flags)))
2374 smartlist_add(dir_items, (cached_dir_t*)d);
2375 } else {
2376 const cached_dir_t *d;
2377 smartlist_t *fps = smartlist_create();
2378 int flags;
2379 if (!strcmpstart(url, "d/")) {
2380 url += 2;
2381 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2382 } else {
2383 flags = DGV_BY_ID |
2384 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2386 dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1);
2387 SMARTLIST_FOREACH(fps, char *, fp, {
2388 if ((d = dirvote_get_vote(fp, flags)))
2389 smartlist_add(dir_items, (cached_dir_t*)d);
2390 tor_free(fp);
2392 smartlist_free(fps);
2394 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2395 write_http_status_line(conn, 404, "Not found");
2396 goto vote_done;
2398 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2399 body_len += compressed ? d->dir_z_len : d->dir_len);
2400 estimated_len += body_len;
2401 SMARTLIST_FOREACH(items, const char *, item, {
2402 size_t ln = strlen(item);
2403 if (compressed) {
2404 estimated_len += ln/2;
2405 } else {
2406 body_len += ln; estimated_len += ln;
2410 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 1)) {
2411 write_http_status_line(conn, 503, "Directory busy, try again later.");
2412 goto vote_done;
2414 write_http_response_header(conn, body_len ? body_len : -1, compressed,
2415 lifetime);
2417 if (smartlist_len(items)) {
2418 if (compressed) {
2419 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2420 SMARTLIST_FOREACH(items, const char *, c,
2421 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2422 connection_write_to_buf_zlib("", 0, conn, 1);
2423 } else {
2424 SMARTLIST_FOREACH(items, const char *, c,
2425 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2427 } else {
2428 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2429 connection_write_to_buf(compressed ? d->dir_z : d->dir,
2430 compressed ? d->dir_z_len : d->dir_len,
2431 TO_CONN(conn)));
2433 vote_done:
2434 smartlist_free(items);
2435 smartlist_free(dir_items);
2436 goto done;
2439 if (!strcmpstart(url,"/tor/server/") ||
2440 !strcmpstart(url,"/tor/extra/")) {
2441 int res;
2442 const char *msg;
2443 const char *request_type = NULL;
2444 int cache_lifetime = 0;
2445 int is_extra = !strcmpstart(url,"/tor/extra/");
2446 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2447 conn->fingerprint_stack = smartlist_create();
2448 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2449 &msg,
2450 !connection_dir_is_encrypted(conn));
2452 if (!strcmpstart(url, "fp/")) {
2453 request_type = compressed?"/tor/server/fp.z":"/tor/server/fp";
2454 if (smartlist_len(conn->fingerprint_stack) == 1)
2455 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2456 } else if (!strcmpstart(url, "authority")) {
2457 request_type = compressed?"/tor/server/authority.z":
2458 "/tor/server/authority";
2459 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2460 } else if (!strcmpstart(url, "all")) {
2461 request_type = compressed?"/tor/server/all.z":"/tor/server/all";
2462 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2463 } else if (!strcmpstart(url, "d/")) {
2464 request_type = compressed?"/tor/server/d.z":"/tor/server/d";
2465 if (smartlist_len(conn->fingerprint_stack) == 1)
2466 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2467 } else {
2468 request_type = "/tor/server/?";
2470 (void) request_type; /* usable for note_request. */
2471 if (!strcmpstart(url, "d/"))
2472 conn->dir_spool_src =
2473 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2474 else
2475 conn->dir_spool_src =
2476 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2478 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2479 conn->dir_spool_src)) {
2480 res = -1;
2481 msg = "Not found";
2484 if (res < 0)
2485 write_http_status_line(conn, 404, msg);
2486 else {
2487 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2488 1, compressed);
2489 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2490 log_info(LD_DIRSERV,
2491 "Client asked for server descriptors, but we've been "
2492 "writing too many bytes lately. Sending 503 Dir busy.");
2493 write_http_status_line(conn, 503, "Directory busy, try again later");
2494 conn->dir_spool_src = DIR_SPOOL_NONE;
2495 goto done;
2497 write_http_response_header(conn, -1, compressed, cache_lifetime);
2498 if (compressed)
2499 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2500 /* Prime the connection with some data. */
2501 connection_dirserv_flushed_some(conn);
2503 goto done;
2506 if (!strcmpstart(url,"/tor/keys/")) {
2507 smartlist_t *certs = smartlist_create();
2508 ssize_t len = -1;
2509 if (!strcmp(url, "/tor/keys/all")) {
2510 authority_cert_get_all(certs);
2511 } else if (!strcmp(url, "/tor/keys/authority")) {
2512 authority_cert_t *cert = get_my_v3_authority_cert();
2513 if (cert)
2514 smartlist_add(certs, cert);
2515 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
2516 smartlist_t *fps = smartlist_create();
2517 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
2518 fps, NULL, 1, 1);
2519 SMARTLIST_FOREACH(fps, char *, d, {
2520 authority_cert_t *c = authority_cert_get_newest_by_id(d);
2521 if (c) smartlist_add(certs, c);
2522 tor_free(d);
2524 smartlist_free(fps);
2525 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
2526 smartlist_t *fps = smartlist_create();
2527 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
2528 fps, NULL, 1, 1);
2529 SMARTLIST_FOREACH(fps, char *, d, {
2530 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
2531 if (c) smartlist_add(certs, c);
2532 tor_free(d);
2534 smartlist_free(fps);
2535 } else {
2536 write_http_status_line(conn, 400, "Bad request");
2537 goto keys_done;
2539 if (!smartlist_len(certs)) {
2540 write_http_status_line(conn, 404, "Not found");
2541 goto keys_done;
2543 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2544 if (c->cache_info.published_on < if_modified_since)
2545 SMARTLIST_DEL_CURRENT(certs, c));
2546 if (!smartlist_len(certs)) {
2547 write_http_status_line(conn, 304, "Not modified");
2548 goto keys_done;
2550 len = 0;
2551 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2552 len += c->cache_info.signed_descriptor_len);
2554 if (global_write_bucket_low(TO_CONN(conn), compressed?len/2:len, 1)) {
2555 write_http_status_line(conn, 503, "Directory busy, try again later.");
2556 goto keys_done;
2559 write_http_response_header(conn, compressed?-1:len, compressed, 60*60);
2560 if (compressed) {
2561 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2562 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2563 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
2564 c->cache_info.signed_descriptor_len,
2565 conn, 0));
2566 connection_write_to_buf_zlib("", 0, conn, 1);
2567 } else {
2568 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2569 connection_write_to_buf(c->cache_info.signed_descriptor_body,
2570 c->cache_info.signed_descriptor_len,
2571 TO_CONN(conn)));
2573 keys_done:
2574 smartlist_free(certs);
2575 goto done;
2578 if (options->HidServDirectoryV2 &&
2579 !strcmpstart(url,"/tor/rendezvous2/")) {
2580 /* Handle v2 rendezvous descriptor fetch request. */
2581 const char *descp;
2582 const char *query = url + strlen("/tor/rendezvous2/");
2583 if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) {
2584 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
2585 safe_str(query));
2586 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
2587 case 1: /* valid */
2588 write_http_response_header(conn, strlen(descp), 0, 0);
2589 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
2590 break;
2591 case 0: /* well-formed but not present */
2592 write_http_status_line(conn, 404, "Not found");
2593 break;
2594 case -1: /* not well-formed */
2595 write_http_status_line(conn, 400, "Bad request");
2596 break;
2598 } else { /* not well-formed */
2599 write_http_status_line(conn, 400, "Bad request");
2601 goto done;
2604 if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) {
2605 /* rendezvous descriptor fetch */
2606 const char *descp;
2607 size_t desc_len;
2608 const char *query = url+strlen("/tor/rendezvous/");
2610 log_info(LD_REND, "Handling rendezvous descriptor get");
2611 switch (rend_cache_lookup_desc(query, 0, &descp, &desc_len)) {
2612 case 1: /* valid */
2613 write_http_response_header_impl(conn, desc_len,
2614 "application/octet-stream",
2615 NULL, NULL, 0);
2616 note_request("/tor/rendezvous?/", desc_len);
2617 /* need to send descp separately, because it may include nuls */
2618 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
2619 /* report successful fetch to statistic */
2620 if (options->HSAuthorityRecordStats) {
2621 hs_usage_note_fetch_total(query, time(NULL));
2622 hs_usage_note_fetch_successful(query, time(NULL));
2624 break;
2625 case 0: /* well-formed but not present */
2626 write_http_status_line(conn, 404, "Not found");
2627 /* report (unsuccessful) fetch to statistic */
2628 if (options->HSAuthorityRecordStats) {
2629 hs_usage_note_fetch_total(query, time(NULL));
2631 break;
2632 case -1: /* not well-formed */
2633 write_http_status_line(conn, 400, "Bad request");
2634 break;
2636 goto done;
2639 if (options->BridgeAuthoritativeDir &&
2640 options->BridgePassword &&
2641 connection_dir_is_encrypted(conn) &&
2642 !strcmp(url,"/tor/networkstatus-bridges")) {
2643 char *status;
2644 char *secret = alloc_http_authenticator(options->BridgePassword);
2646 header = http_get_header(headers, "Authorization: Basic ");
2648 /* now make sure the password is there and right */
2649 if (!header || strcmp(header, secret)) {
2650 write_http_status_line(conn, 404, "Not found");
2651 tor_free(secret);
2652 tor_free(header);
2653 goto done;
2655 tor_free(secret);
2656 tor_free(header);
2658 /* all happy now. send an answer. */
2659 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
2660 dlen = strlen(status);
2661 write_http_response_header(conn, dlen, 0, 0);
2662 connection_write_to_buf(status, dlen, TO_CONN(conn));
2663 tor_free(status);
2664 goto done;
2667 if (!strcmpstart(url,"/tor/bytes.txt")) {
2668 char *bytes = directory_dump_request_log();
2669 size_t len = strlen(bytes);
2670 write_http_response_header(conn, len, 0, 0);
2671 connection_write_to_buf(bytes, len, TO_CONN(conn));
2672 tor_free(bytes);
2673 goto done;
2676 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
2677 rewritten to /tor/robots.txt */
2678 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
2679 size_t len = strlen(robots);
2680 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
2681 connection_write_to_buf(robots, len, TO_CONN(conn));
2682 goto done;
2685 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
2686 #define ADD_MALLINFO_LINE(x) do { \
2687 tor_snprintf(tmp, sizeof(tmp), "%s %d\n", #x, mi.x); \
2688 smartlist_add(lines, tor_strdup(tmp)); \
2689 }while(0);
2691 if (!strcmp(url,"/tor/mallinfo.txt") &&
2692 (conn->_base.addr == 0x7f000001ul)) {
2693 char *result;
2694 size_t len;
2695 struct mallinfo mi;
2696 smartlist_t *lines;
2697 char tmp[256];
2699 memset(&mi, 0, sizeof(mi));
2700 mi = mallinfo();
2701 lines = smartlist_create();
2703 ADD_MALLINFO_LINE(arena)
2704 ADD_MALLINFO_LINE(ordblks)
2705 ADD_MALLINFO_LINE(smblks)
2706 ADD_MALLINFO_LINE(hblks)
2707 ADD_MALLINFO_LINE(hblkhd)
2708 ADD_MALLINFO_LINE(usmblks)
2709 ADD_MALLINFO_LINE(fsmblks)
2710 ADD_MALLINFO_LINE(uordblks)
2711 ADD_MALLINFO_LINE(fordblks)
2712 ADD_MALLINFO_LINE(keepcost)
2714 result = smartlist_join_strings(lines, "", 0, NULL);
2715 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2716 smartlist_free(lines);
2718 len = strlen(result);
2719 write_http_response_header(conn, len, 0, 0);
2720 connection_write_to_buf(result, len, TO_CONN(conn));
2721 tor_free(result);
2722 goto done;
2724 #endif
2726 /* we didn't recognize the url */
2727 write_http_status_line(conn, 404, "Not found");
2729 done:
2730 tor_free(url_mem);
2731 return 0;
2734 /** Helper function: called when a dirserver gets a complete HTTP POST
2735 * request. Look for an uploaded server descriptor or rendezvous
2736 * service descriptor. On finding one, process it and write a
2737 * response into conn-\>outbuf. If the request is unrecognized, send a
2738 * 400. Always return 0. */
2739 static int
2740 directory_handle_command_post(dir_connection_t *conn, const char *headers,
2741 const char *body, size_t body_len)
2743 char *url = NULL;
2744 or_options_t *options = get_options();
2746 log_debug(LD_DIRSERV,"Received POST command.");
2748 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2750 if (parse_http_url(headers, &url) < 0) {
2751 write_http_status_line(conn, 400, "Bad request");
2752 return 0;
2754 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2756 /* Handle v2 rendezvous service publish request. */
2757 if (options->HidServDirectoryV2 &&
2758 !strcmpstart(url,"/tor/rendezvous2/publish")) {
2759 switch (rend_cache_store_v2_desc_as_dir(body)) {
2760 case -2:
2761 log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
2762 "since we're not currently a hidden service directory.",
2763 (int)body_len, conn->_base.address);
2764 write_http_status_line(conn, 503, "Currently not acting as v2 "
2765 "hidden service directory");
2766 break;
2767 case -1:
2768 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
2769 (int)body_len, conn->_base.address);
2770 write_http_status_line(conn, 400, "Invalid service descriptor "
2771 "rejected");
2772 break;
2773 default:
2774 write_http_status_line(conn, 200, "Service descriptor stored");
2775 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
2777 goto done;
2780 if (!authdir_mode(options)) {
2781 /* we just provide cached directories; we don't want to
2782 * receive anything. */
2783 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
2784 "accept posted server descriptors");
2785 return 0;
2788 if (authdir_mode_handles_descs(options, -1) &&
2789 !strcmp(url,"/tor/")) { /* server descriptor post */
2790 const char *msg = NULL;
2791 uint8_t purpose = authdir_mode_bridge(options) ?
2792 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
2793 int r = dirserv_add_multiple_descriptors(body, purpose,
2794 conn->_base.address, &msg);
2795 tor_assert(msg);
2796 if (r > 0)
2797 dirserv_get_directory(); /* rebuild and write to disk */
2798 switch (r) {
2799 case -1:
2800 log_notice(LD_DIRSERV,
2801 "Rejected router descriptor or extra-info from %s "
2802 "(\"%s\").",
2803 conn->_base.address, msg);
2804 /* fall through */
2805 case 1:
2806 /* malformed descriptor, or something wrong */
2807 write_http_status_line(conn, 400, msg);
2808 break;
2809 case 0: /* accepted but discarded */
2810 write_http_response_header_impl(conn, -1, NULL, NULL,
2811 "X-Descriptor-Not-New: Yes\r\n", -1);
2812 break;
2813 case 2: /* accepted */
2814 write_http_status_line(conn, 200, msg);
2815 break;
2817 goto done;
2820 if (options->HSAuthoritativeDir &&
2821 !strcmpstart(url,"/tor/rendezvous/publish")) {
2822 /* rendezvous descriptor post */
2823 log_info(LD_REND, "Handling rendezvous descriptor post.");
2824 if (rend_cache_store(body, body_len, 1) < 0) {
2825 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
2826 "Rejected rend descriptor (length %d) from %s.",
2827 (int)body_len, conn->_base.address);
2828 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
2829 } else {
2830 write_http_status_line(conn, 200, "Service descriptor stored");
2832 goto done;
2835 if (authdir_mode_v3(options) &&
2836 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
2837 const char *msg = "OK";
2838 int status;
2839 if (dirvote_add_vote(body, &msg, &status)) {
2840 write_http_status_line(conn, status, "Vote stored");
2841 } else {
2842 tor_assert(msg);
2843 write_http_status_line(conn, status, msg);
2845 goto done;
2848 if (authdir_mode_v3(options) &&
2849 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
2850 const char *msg = NULL;
2851 if (dirvote_add_signatures(body, conn->_base.address, &msg)>=0) {
2852 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
2853 } else {
2854 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
2855 conn->_base.address, msg?msg:"???");
2856 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
2858 goto done;
2861 /* we didn't recognize the url */
2862 write_http_status_line(conn, 404, "Not found");
2864 done:
2865 tor_free(url);
2866 return 0;
2869 /** Called when a dirserver receives data on a directory connection;
2870 * looks for an HTTP request. If the request is complete, remove it
2871 * from the inbuf, try to process it; otherwise, leave it on the
2872 * buffer. Return a 0 on success, or -1 on error.
2874 static int
2875 directory_handle_command(dir_connection_t *conn)
2877 char *headers=NULL, *body=NULL;
2878 size_t body_len=0;
2879 int r;
2881 tor_assert(conn);
2882 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2884 switch (fetch_from_buf_http(conn->_base.inbuf,
2885 &headers, MAX_HEADERS_SIZE,
2886 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
2887 case -1: /* overflow */
2888 log_warn(LD_DIRSERV,
2889 "Invalid input from address '%s'. Closing.",
2890 conn->_base.address);
2891 return -1;
2892 case 0:
2893 log_debug(LD_DIRSERV,"command not all here yet.");
2894 return 0;
2895 /* case 1, fall through */
2898 http_set_address_origin(headers, TO_CONN(conn));
2899 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
2901 if (!strncasecmp(headers,"GET",3))
2902 r = directory_handle_command_get(conn, headers, body, body_len);
2903 else if (!strncasecmp(headers,"POST",4))
2904 r = directory_handle_command_post(conn, headers, body, body_len);
2905 else {
2906 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
2907 "Got headers %s with unknown command. Closing.",
2908 escaped(headers));
2909 r = -1;
2912 tor_free(headers); tor_free(body);
2913 return r;
2916 /** Write handler for directory connections; called when all data has
2917 * been flushed. Close the connection or wait for a response as
2918 * appropriate.
2921 connection_dir_finished_flushing(dir_connection_t *conn)
2923 tor_assert(conn);
2924 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2926 switch (conn->_base.state) {
2927 case DIR_CONN_STATE_CLIENT_SENDING:
2928 log_debug(LD_DIR,"client finished sending command.");
2929 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
2930 connection_stop_writing(TO_CONN(conn));
2931 return 0;
2932 case DIR_CONN_STATE_SERVER_WRITING:
2933 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
2934 connection_mark_for_close(TO_CONN(conn));
2935 return 0;
2936 default:
2937 log_warn(LD_BUG,"called in unexpected state %d.",
2938 conn->_base.state);
2939 tor_fragile_assert();
2940 return -1;
2942 return 0;
2945 /** Connected handler for directory connections: begin sending data to the
2946 * server */
2948 connection_dir_finished_connecting(dir_connection_t *conn)
2950 tor_assert(conn);
2951 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2952 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
2954 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
2955 conn->_base.address,conn->_base.port);
2957 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
2958 return 0;
2961 /** Called when one or more networkstatus fetches have failed (with uppercase
2962 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
2963 * failed once, unless they failed with status code 503. */
2964 static void
2965 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
2967 if (status_code == 503)
2968 return;
2969 SMARTLIST_FOREACH(failed, const char *, fp,
2971 char digest[DIGEST_LEN];
2972 trusted_dir_server_t *dir;
2973 if (base16_decode(digest, DIGEST_LEN, fp, strlen(fp))<0) {
2974 log_warn(LD_BUG, "Called with bad fingerprint in list: %s",
2975 escaped(fp));
2976 continue;
2978 dir = router_get_trusteddirserver_by_digest(digest);
2980 if (dir)
2981 download_status_failed(&dir->v2_ns_dl_status, status_code);
2985 static const int server_dl_schedule[] = {
2986 0, 0, 0, 60, 60, 60*2, 60*5, 60*15, INT_MAX
2988 static const int client_dl_schedule[] = {
2989 0, 0, 60, 60*5, 60*10, INT_MAX
2991 static const int server_consensus_dl_schedule[] = {
2992 0, 0, 60, 60*5, 60*10, 60*30, 60*30, 60*30, 60*30, 60*30, 60*60, 60*60*2
2994 static const int client_consensus_dl_schedule[] = {
2995 0, 0, 60, 60*5, 60*10, 60*30, 60*60, 60*60, 60*60, 60*60*3, 60*60*6, 60*60*12
2998 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
2999 * <b>status_code</b>. Increment the failure count (if the code indicates a
3000 * real failure) and set <b>dls<b>->next_attempt_at to an appropriate time in
3001 * the future. */
3002 time_t
3003 download_status_increment_failure(download_status_t *dls, int status_code,
3004 const char *item, int server, time_t now)
3006 const int *schedule;
3007 int schedule_len;
3008 int increment;
3009 tor_assert(dls);
3010 if (status_code != 503 || server)
3011 ++dls->n_download_failures;
3013 switch (dls->schedule) {
3014 case DL_SCHED_GENERIC:
3015 if (server) {
3016 schedule = server_dl_schedule;
3017 schedule_len = sizeof(server_dl_schedule)/sizeof(int);
3018 } else {
3019 schedule = client_dl_schedule;
3020 schedule_len = sizeof(client_dl_schedule)/sizeof(int);
3022 break;
3023 case DL_SCHED_CONSENSUS:
3024 if (server) {
3025 schedule = server_consensus_dl_schedule;
3026 schedule_len = sizeof(server_consensus_dl_schedule)/sizeof(int);
3027 } else {
3028 schedule = client_consensus_dl_schedule;
3029 schedule_len = sizeof(client_consensus_dl_schedule)/sizeof(int);
3031 break;
3032 default:
3033 tor_assert(0);
3036 if (dls->n_download_failures < schedule_len)
3037 increment = schedule[dls->n_download_failures];
3038 else
3039 increment = schedule[schedule_len-1];
3041 if (increment < INT_MAX)
3042 dls->next_attempt_at = now+increment;
3043 else
3044 dls->next_attempt_at = TIME_MAX;
3046 if (item) {
3047 if (dls->next_attempt_at == 0)
3048 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
3049 item, (int)dls->n_download_failures);
3050 else if (dls->next_attempt_at < TIME_MAX)
3051 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
3052 item, (int)dls->n_download_failures,
3053 (int)(dls->next_attempt_at-now));
3054 else
3055 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
3056 item, (int)dls->n_download_failures);
3058 return dls->next_attempt_at;
3061 /** Reset <b>dls</b> so that it will be considered downloadable
3062 * immediately. */
3063 void
3064 download_status_reset(download_status_t *dls)
3066 dls->n_download_failures = 0;
3067 dls->next_attempt_at = 0;
3070 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
3071 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
3072 * either as descriptor digests or as identity digests based on
3073 * <b>was_descriptor_digests</b>).
3075 static void
3076 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
3077 int router_purpose,
3078 int was_extrainfo, int was_descriptor_digests)
3080 char digest[DIGEST_LEN];
3081 time_t now = time(NULL);
3082 int server = directory_fetches_from_authorities(get_options());
3083 if (!was_descriptor_digests) {
3084 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
3085 tor_assert(!was_extrainfo); /* not supported yet */
3086 SMARTLIST_FOREACH(failed, const char *, cp,
3088 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
3089 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
3090 escaped(cp));
3091 continue;
3093 retry_bridge_descriptor_fetch_directly(digest);
3096 return; /* FFFF should implement for other-than-router-purpose someday */
3098 SMARTLIST_FOREACH(failed, const char *, cp,
3100 download_status_t *dls = NULL;
3101 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) {
3102 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
3103 continue;
3105 if (was_extrainfo) {
3106 signed_descriptor_t *sd =
3107 router_get_by_extrainfo_digest(digest);
3108 if (sd)
3109 dls = &sd->ei_dl_status;
3110 } else {
3111 dls = router_get_dl_status_by_descriptor_digest(digest);
3113 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
3114 continue;
3115 download_status_increment_failure(dls, status_code, cp, server, now);
3118 /* No need to relaunch descriptor downloads here: we already do it
3119 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3122 /** Given a directory <b>resource</b> request, containing zero
3123 * or more strings separated by plus signs, followed optionally by ".z", store
3124 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3125 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
3126 * decode_hex is true, then delete all elements that aren't hex digests, and
3127 * decode the rest. If sort_uniq is true, then sort the list and remove
3128 * all duplicates.
3131 dir_split_resource_into_fingerprints(const char *resource,
3132 smartlist_t *fp_out, int *compressed_out,
3133 int decode_hex, int sort_uniq)
3135 smartlist_t *fp_tmp = smartlist_create();
3136 tor_assert(fp_out);
3137 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
3138 if (compressed_out)
3139 *compressed_out = 0;
3140 if (smartlist_len(fp_tmp)) {
3141 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3142 size_t last_len = strlen(last);
3143 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3144 last[last_len-2] = '\0';
3145 if (compressed_out)
3146 *compressed_out = 1;
3149 if (decode_hex) {
3150 int i;
3151 char *cp, *d = NULL;
3152 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3153 cp = smartlist_get(fp_tmp, i);
3154 if (strlen(cp) != HEX_DIGEST_LEN) {
3155 log_info(LD_DIR,
3156 "Skipping digest %s with non-standard length.", escaped(cp));
3157 smartlist_del_keeporder(fp_tmp, i--);
3158 goto again;
3160 d = tor_malloc_zero(DIGEST_LEN);
3161 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
3162 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3163 smartlist_del_keeporder(fp_tmp, i--);
3164 goto again;
3166 smartlist_set(fp_tmp, i, d);
3167 d = NULL;
3168 again:
3169 tor_free(cp);
3170 tor_free(d);
3173 if (sort_uniq) {
3174 smartlist_t *fp_tmp2 = smartlist_create();
3175 int i;
3176 if (decode_hex)
3177 smartlist_sort_digests(fp_tmp);
3178 else
3179 smartlist_sort_strings(fp_tmp);
3180 if (smartlist_len(fp_tmp))
3181 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
3182 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
3183 char *cp = smartlist_get(fp_tmp, i);
3184 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
3186 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
3187 || (!decode_hex && strcasecmp(cp, last)))
3188 smartlist_add(fp_tmp2, cp);
3189 else
3190 tor_free(cp);
3192 smartlist_free(fp_tmp);
3193 fp_tmp = fp_tmp2;
3195 smartlist_add_all(fp_out, fp_tmp);
3196 smartlist_free(fp_tmp);
3197 return 0;