continue r13250 cleanup: remove some duplicate code
[tor.git] / src / or / directory.c
blobde5b66eeb0f4d680ccbe2aee4797088edfec4321
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 /* $Id$ */
6 const char directory_c_id[] =
7 "$Id$";
9 #include "or.h"
10 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
11 #include <malloc.h>
12 #endif
14 /**
15 * \file directory.c
16 * \brief Code to send and fetch directories and router
17 * descriptors via HTTP. Directories use dirserv.c to generate the
18 * results; clients use routers.c to parse them.
19 **/
21 /* In-points to directory.c:
23 * - directory_post_to_dirservers(), called from
24 * router_upload_dir_desc_to_dirservers() in router.c
25 * upload_service_descriptor() in rendservice.c
26 * - directory_get_from_dirserver(), called from
27 * rend_client_refetch_renddesc() in rendclient.c
28 * run_scheduled_events() in main.c
29 * do_hup() in main.c
30 * - connection_dir_process_inbuf(), called from
31 * connection_process_inbuf() in connection.c
32 * - connection_dir_finished_flushing(), called from
33 * connection_finished_flushing() in connection.c
34 * - connection_dir_finished_connecting(), called from
35 * connection_finished_connecting() in connection.c
37 static void directory_send_command(dir_connection_t *conn,
38 int purpose, int direct, const char *resource,
39 const char *payload, size_t payload_len,
40 time_t if_modified_since);
41 static int directory_handle_command(dir_connection_t *conn);
42 static int body_is_plausible(const char *body, size_t body_len, int purpose);
43 static int purpose_needs_anonymity(uint8_t dir_purpose,
44 uint8_t router_purpose);
45 static char *http_get_header(const char *headers, const char *which);
46 static void http_set_address_origin(const char *headers, connection_t *conn);
47 static void connection_dir_download_networkstatus_failed(
48 dir_connection_t *conn, int status_code);
49 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
50 static void connection_dir_download_cert_failed(
51 dir_connection_t *conn, int status_code);
52 static void dir_networkstatus_download_failed(smartlist_t *failed,
53 int status_code);
54 static void dir_routerdesc_download_failed(smartlist_t *failed,
55 int status_code,
56 int router_purpose,
57 int was_extrainfo,
58 int was_descriptor_digests);
59 static void note_request(const char *key, size_t bytes);
61 /********* START VARIABLES **********/
63 /** How far in the future do we allow a directory server to tell us it is
64 * before deciding that one of us has the wrong time? */
65 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
67 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
69 /** HTTP cache control: how long do we tell proxies they can cache each
70 * kind of document we serve? */
71 #define FULL_DIR_CACHE_LIFETIME (60*60)
72 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
73 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
74 #define ROUTERDESC_CACHE_LIFETIME (30*60)
75 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
76 #define ROBOTS_CACHE_LIFETIME (24*60*60)
78 /********* END VARIABLES ************/
80 /** Return true iff the directory purpose 'purpose' must use an
81 * anonymous connection to a directory. */
82 static int
83 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
85 if (get_options()->AllDirActionsPrivate)
86 return 1;
87 if (router_purpose == ROUTER_PURPOSE_BRIDGE && has_completed_circuit)
88 return 1; /* if no circuits yet, we may need this info to bootstrap. */
89 if (dir_purpose == DIR_PURPOSE_FETCH_DIR ||
90 dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
91 dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
92 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
93 dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
94 dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
95 dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
96 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
97 dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
98 dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
99 dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
100 dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
101 return 0;
102 return 1;
105 /** Return a newly allocated string describing <b>auth</b>. */
106 char *
107 authority_type_to_string(authority_type_t auth)
109 char *result;
110 smartlist_t *lst = smartlist_create();
111 if (auth & V1_AUTHORITY)
112 smartlist_add(lst, (void*)"V1");
113 if (auth & V2_AUTHORITY)
114 smartlist_add(lst, (void*)"V2");
115 if (auth & BRIDGE_AUTHORITY)
116 smartlist_add(lst, (void*)"Bridge");
117 if (auth & HIDSERV_AUTHORITY)
118 smartlist_add(lst, (void*)"Hidden service");
119 if (smartlist_len(lst)) {
120 result = smartlist_join_strings(lst, ", ", 0, NULL);
121 } else {
122 result = tor_strdup("[Not an authority]");
124 smartlist_free(lst);
125 return result;
128 /** Return a string describing a given directory connection purpose. */
129 static const char *
130 dir_conn_purpose_to_string(int purpose)
132 switch (purpose)
134 case DIR_PURPOSE_FETCH_DIR:
135 return "v1 directory fetch";
136 case DIR_PURPOSE_FETCH_RENDDESC:
137 return "hidden-service descriptor fetch";
138 case DIR_PURPOSE_UPLOAD_DIR:
139 return "server descriptor upload";
140 case DIR_PURPOSE_UPLOAD_RENDDESC:
141 return "hidden-service descriptor upload";
142 case DIR_PURPOSE_UPLOAD_VOTE:
143 return "server vote upload";
144 case DIR_PURPOSE_UPLOAD_SIGNATURES:
145 return "consensus signature upload";
146 case DIR_PURPOSE_FETCH_RUNNING_LIST:
147 return "running-routers fetch";
148 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
149 return "network-status fetch";
150 case DIR_PURPOSE_FETCH_SERVERDESC:
151 return "server descriptor fetch";
152 case DIR_PURPOSE_FETCH_EXTRAINFO:
153 return "extra-info fetch";
154 case DIR_PURPOSE_FETCH_CONSENSUS:
155 return "consensus network-status fetch";
156 case DIR_PURPOSE_FETCH_CERTIFICATE:
157 return "authority cert fetch";
158 case DIR_PURPOSE_FETCH_STATUS_VOTE:
159 return "status vote fetch";
160 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
161 return "consensus signature fetch";
162 case DIR_PURPOSE_FETCH_RENDDESC_V2:
163 return "hidden-service v2 descriptor fetch";
164 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
165 return "hidden-service v2 descriptor upload";
168 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
169 return "(unknown)";
172 /** Return true iff <b>identity_digest</b> is the digest of a router we
173 * believe to support extrainfo downloads. (If <b>is_authority</b> we do
174 * additional checking that's only valid for authorities.) */
176 router_supports_extrainfo(const char *identity_digest, int is_authority)
178 routerinfo_t *ri = router_get_by_digest(identity_digest);
180 if (ri) {
181 if (ri->caches_extra_info)
182 return 1;
183 if (is_authority && ri->platform &&
184 tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
185 return 1;
187 if (is_authority) {
188 routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
189 if (rs && rs->version_supports_extrainfo_upload)
190 return 1;
192 return 0;
195 /** Return true iff all trusted directory servers have accepted our
196 * server descriptor. */
198 directories_have_accepted_server_descriptor(void)
200 smartlist_t *servers = router_get_trusted_dir_servers();
201 or_options_t *options = get_options();
202 /* XXX020 If any authority of the needed type is down, this
203 * function will never return true. Perhaps we need to be
204 * tolerant of down servers? Or even better, should we change
205 * this so one successful upload is enough? -RD */
206 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
207 if ((d->type & options->_PublishServerDescriptor) &&
208 !d->has_accepted_serverdesc) {
209 return 0;
212 return 1;
215 /** Start a connection to every suitable directory authority, using
216 * connection purpose 'purpose' and uploading the payload 'payload'
217 * (length 'payload_len'). The purpose should be one of
218 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
220 * <b>type</b> specifies what sort of dir authorities (V1, V2,
221 * HIDSERV, BRIDGE) we should upload to.
223 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
224 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
225 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
226 * to all authorities, and the extra-info document to all authorities that
227 * support it.
229 void
230 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
231 authority_type_t type,
232 const char *payload,
233 size_t payload_len, size_t extrainfo_len)
235 int post_via_tor;
236 smartlist_t *dirservers = router_get_trusted_dir_servers();
237 int found = 0;
238 tor_assert(dirservers);
239 /* This tries dirservers which we believe to be down, but ultimately, that's
240 * harmless, and we may as well err on the side of getting things uploaded.
242 SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
244 routerstatus_t *rs = &(ds->fake_status);
245 size_t upload_len = payload_len;
247 if ((type & ds->type) == 0)
248 continue;
250 found = 1; /* at least one authority of this type was listed */
251 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
252 ds->has_accepted_serverdesc = 0;
254 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
255 upload_len += extrainfo_len;
256 log_info(LD_DIR, "Uploading an extrainfo (length %d)",
257 (int) extrainfo_len);
259 post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) ||
260 !fascist_firewall_allows_address_dir(ds->addr, ds->dir_port);
261 directory_initiate_command_routerstatus(rs, dir_purpose,
262 router_purpose,
263 post_via_tor,
264 NULL, payload, upload_len, 0);
266 if (!found) {
267 char *s = authority_type_to_string(type);
268 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
269 "of type '%s', but no authorities of that type listed!", s);
270 tor_free(s);
274 /** Start a connection to a random running directory server, using
275 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
276 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
277 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
278 * down, mark them up and try again.
280 void
281 directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
282 const char *resource, int retry_if_no_servers)
284 routerstatus_t *rs = NULL;
285 or_options_t *options = get_options();
286 int prefer_authority = directory_fetches_from_authorities(options);
287 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
288 authority_type_t type;
289 int flags = retry_if_no_servers ? PDS_RETRY_IF_NO_SERVERS : 0;
290 time_t if_modified_since = 0;
292 /* FFFF we could break this switch into its own function, and call
293 * it elsewhere in directory.c. -RD */
294 switch (dir_purpose) {
295 case DIR_PURPOSE_FETCH_EXTRAINFO:
296 type = EXTRAINFO_CACHE |
297 (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
298 V2_AUTHORITY);
299 break;
300 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
301 case DIR_PURPOSE_FETCH_SERVERDESC:
302 type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
303 V2_AUTHORITY);
304 break;
305 case DIR_PURPOSE_FETCH_DIR:
306 case DIR_PURPOSE_FETCH_RUNNING_LIST:
307 type = V1_AUTHORITY;
308 break;
309 case DIR_PURPOSE_FETCH_RENDDESC:
310 type = HIDSERV_AUTHORITY;
311 break;
312 case DIR_PURPOSE_FETCH_STATUS_VOTE:
313 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
314 type = V3_AUTHORITY;
315 break;
316 case DIR_PURPOSE_FETCH_CONSENSUS:
317 case DIR_PURPOSE_FETCH_CERTIFICATE:
318 type = V3_AUTHORITY;
319 break;
320 default:
321 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
322 return;
325 if (DIR_PURPOSE_FETCH_CONSENSUS) {
326 networkstatus_vote_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 trusted_dir_server_t *dir = trusteddirserver_get_by_v3_auth_digest(cp);
605 if (dir)
606 download_status_failed(&dir->cert_dl_status, status);
607 tor_free(cp);
609 smartlist_free(failed);
611 update_certificate_downloads(time(NULL));
614 /** Helper for directory_initiate_command_routerstatus: send the
615 * command to a server whose address is <b>address</b>, whose IP is
616 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
617 * <b>supports_begindir</b>, and whose identity key digest is
618 * <b>digest</b>. */
619 void
620 directory_initiate_command(const char *address, uint32_t addr,
621 uint16_t or_port, uint16_t dir_port,
622 int supports_begindir, const char *digest,
623 uint8_t dir_purpose, uint8_t router_purpose,
624 int anonymized_connection, const char *resource,
625 const char *payload, size_t payload_len,
626 time_t if_modified_since)
628 dir_connection_t *conn;
629 or_options_t *options = get_options();
630 int use_begindir = supports_begindir && or_port &&
631 (options->TunnelDirConns ||
632 router_purpose == ROUTER_PURPOSE_BRIDGE) &&
633 (anonymized_connection ||
634 fascist_firewall_allows_address_or(addr, or_port));
636 tor_assert(address);
637 tor_assert(addr);
638 tor_assert(or_port || dir_port);
639 tor_assert(digest);
641 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
642 anonymized_connection, use_begindir);
644 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
646 conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
648 /* set up conn so it's got all the data we need to remember */
649 conn->_base.addr = addr;
650 conn->_base.port = use_begindir ? or_port : dir_port;
651 conn->_base.address = tor_strdup(address);
652 memcpy(conn->identity_digest, digest, DIGEST_LEN);
654 conn->_base.purpose = dir_purpose;
655 conn->router_purpose = router_purpose;
657 /* give it an initial state */
658 conn->_base.state = DIR_CONN_STATE_CONNECTING;
660 /* decide whether we can learn our IP address from this conn */
661 conn->dirconn_direct = !anonymized_connection;
663 if (!anonymized_connection && !use_begindir) {
664 /* then we want to connect to dirport directly */
666 if (options->HttpProxy) {
667 addr = options->HttpProxyAddr;
668 dir_port = options->HttpProxyPort;
671 switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
672 dir_port)) {
673 case -1:
674 connection_dir_request_failed(conn); /* retry if we want */
675 /* XXX we only pass 'conn' above, not 'resource', 'payload',
676 * etc. So in many situations it can't retry! -RD */
677 connection_free(TO_CONN(conn));
678 return;
679 case 1:
680 /* start flushing conn */
681 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
682 /* fall through */
683 case 0:
684 /* queue the command on the outbuf */
685 directory_send_command(conn, dir_purpose, 1, resource,
686 payload, payload_len, if_modified_since);
687 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
688 /* writable indicates finish, readable indicates broken link,
689 error indicates broken link in windowsland. */
691 } else { /* we want to connect via a tor connection */
692 edge_connection_t *linked_conn;
693 /* make an AP connection
694 * populate it and add it at the right state
695 * hook up both sides
697 linked_conn =
698 connection_ap_make_link(conn->_base.address, conn->_base.port,
699 digest, use_begindir, conn->dirconn_direct);
700 if (!linked_conn) {
701 log_warn(LD_NET,"Making tunnel to dirserver failed.");
702 connection_mark_for_close(TO_CONN(conn));
703 return;
705 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
707 if (connection_add(TO_CONN(conn)) < 0) {
708 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
709 connection_mark_for_close(TO_CONN(conn));
710 return;
712 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
713 /* queue the command on the outbuf */
714 directory_send_command(conn, dir_purpose, 0, resource,
715 payload, payload_len, if_modified_since);
716 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
717 connection_start_reading(TO_CONN(linked_conn));
721 /** Return true iff anything we say on <b>conn</b> is being encrypted before
722 * we send it to the client/server. */
724 connection_dir_is_encrypted(dir_connection_t *conn)
726 /* Right now it's sufficient to see if conn is or has been linked, since
727 * the only thing it could be linked to is an edge connection on a
728 * circuit, and the only way it could have been unlinked is at the edge
729 * connection getting closed.
731 return TO_CONN(conn)->linked;
734 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
735 * are as in directory_initiate_command.
737 static void
738 directory_send_command(dir_connection_t *conn,
739 int purpose, int direct, const char *resource,
740 const char *payload, size_t payload_len,
741 time_t if_modified_since)
743 char proxystring[256];
744 char proxyauthstring[256];
745 char hoststring[128];
746 char imsstring[RFC1123_TIME_LEN+32];
747 char *url;
748 char request[8192];
749 const char *httpcommand = NULL;
750 size_t len;
752 tor_assert(conn);
753 tor_assert(conn->_base.type == CONN_TYPE_DIR);
755 tor_free(conn->requested_resource);
756 if (resource)
757 conn->requested_resource = tor_strdup(resource);
759 /* come up with a string for which Host: we want */
760 if (conn->_base.port == 80) {
761 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
762 } else {
763 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
764 conn->_base.address, conn->_base.port);
767 /* Format if-modified-since */
768 if (!if_modified_since) {
769 imsstring[0] = '\0';
770 } else {
771 char b[RFC1123_TIME_LEN+1];
772 format_rfc1123_time(b, if_modified_since);
773 tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
776 /* come up with some proxy lines, if we're using one. */
777 if (direct && get_options()->HttpProxy) {
778 char *base64_authenticator=NULL;
779 const char *authenticator = get_options()->HttpProxyAuthenticator;
781 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
782 if (authenticator) {
783 base64_authenticator = alloc_http_authenticator(authenticator);
784 if (!base64_authenticator)
785 log_warn(LD_BUG, "Encoding http authenticator failed");
787 if (base64_authenticator) {
788 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
789 "\r\nProxy-Authorization: Basic %s",
790 base64_authenticator);
791 tor_free(base64_authenticator);
792 } else {
793 proxyauthstring[0] = 0;
795 } else {
796 proxystring[0] = 0;
797 proxyauthstring[0] = 0;
800 switch (purpose) {
801 case DIR_PURPOSE_FETCH_DIR:
802 tor_assert(!resource);
803 tor_assert(!payload);
804 httpcommand = "GET";
805 url = tor_strdup("/tor/dir.z");
806 break;
807 case DIR_PURPOSE_FETCH_RUNNING_LIST:
808 tor_assert(!resource);
809 tor_assert(!payload);
810 httpcommand = "GET";
811 url = tor_strdup("/tor/running-routers");
812 break;
813 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
814 httpcommand = "GET";
815 len = strlen(resource)+32;
816 url = tor_malloc(len);
817 tor_snprintf(url, len, "/tor/status/%s", resource);
818 break;
819 case DIR_PURPOSE_FETCH_CONSENSUS:
820 tor_assert(!resource);
821 tor_assert(!payload);
822 httpcommand = "GET";
823 url = tor_strdup("/tor/status-vote/current/consensus.z");
824 break;
825 case DIR_PURPOSE_FETCH_CERTIFICATE:
826 tor_assert(resource);
827 tor_assert(!payload);
828 httpcommand = "GET";
829 len = strlen(resource)+32;
830 url = tor_malloc(len);
831 tor_snprintf(url, len, "/tor/keys/%s", resource);
832 break;
833 case DIR_PURPOSE_FETCH_STATUS_VOTE:
834 tor_assert(resource);
835 tor_assert(!payload);
836 httpcommand = "GET";
837 len = strlen(resource)+32;
838 url = tor_malloc(len);
839 tor_snprintf(url, len, "/tor/status-vote/next/%s.z", resource);
840 break;
841 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
842 tor_assert(!resource);
843 tor_assert(!payload);
844 httpcommand = "GET";
845 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
846 break;
847 case DIR_PURPOSE_FETCH_SERVERDESC:
848 httpcommand = "GET";
849 len = strlen(resource)+32;
850 url = tor_malloc(len);
851 tor_snprintf(url, len, "/tor/server/%s", resource);
852 break;
853 case DIR_PURPOSE_FETCH_EXTRAINFO:
854 httpcommand = "GET";
855 len = strlen(resource)+32;
856 url = tor_malloc(len);
857 tor_snprintf(url, len, "/tor/extra/%s", resource);
858 break;
859 case DIR_PURPOSE_UPLOAD_DIR:
860 tor_assert(!resource);
861 tor_assert(payload);
862 httpcommand = "POST";
863 url = tor_strdup("/tor/");
864 break;
865 case DIR_PURPOSE_UPLOAD_VOTE:
866 tor_assert(!resource);
867 tor_assert(payload);
868 httpcommand = "POST";
869 url = tor_strdup("/tor/post/vote");
870 break;
871 case DIR_PURPOSE_UPLOAD_SIGNATURES:
872 tor_assert(!resource);
873 tor_assert(payload);
874 httpcommand = "POST";
875 url = tor_strdup("/tor/post/consensus-signature");
876 break;
877 case DIR_PURPOSE_FETCH_RENDDESC:
878 tor_assert(resource);
879 tor_assert(!payload);
881 /* this must be true or we wouldn't be doing the lookup */
882 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN_BASE32);
883 /* This breaks the function abstraction. */
884 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
886 httpcommand = "GET";
887 /* Request the most recent versioned descriptor. */
888 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
889 // but that never got testing, and it wasn't a good design.)
890 len = strlen(resource)+32;
891 url = tor_malloc(len);
892 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
893 break;
894 case DIR_PURPOSE_FETCH_RENDDESC_V2:
895 tor_assert(resource);
896 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
897 /* Remember the query to refer to it when a response arrives. */
898 strlcpy(conn->rend_query, payload, sizeof(conn->rend_query));
899 payload = NULL;
900 httpcommand = "GET";
901 len = strlen(resource) + 32;
902 url = tor_malloc(len);
903 tor_snprintf(url, len, "/tor/rendezvous2/%s", resource);
904 break;
905 case DIR_PURPOSE_UPLOAD_RENDDESC:
906 tor_assert(!resource);
907 tor_assert(payload);
908 httpcommand = "POST";
909 url = tor_strdup("/tor/rendezvous/publish");
910 break;
911 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
912 tor_assert(!resource);
913 tor_assert(payload);
914 httpcommand = "POST";
915 url = tor_strdup("/tor/rendezvous2/publish");
916 break;
917 default:
918 tor_assert(0);
919 return;
922 if (strlen(proxystring) + strlen(url) >= 4096) {
923 log_warn(LD_BUG,
924 "Squid does not like URLs longer than 4095 bytes, and this "
925 "one is %d bytes long: %s%s",
926 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
929 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
930 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
931 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
932 tor_free(url);
934 if (!strcmp(httpcommand, "GET") && !payload) {
935 tor_snprintf(request, sizeof(request),
936 " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
937 hoststring,
938 imsstring,
939 proxyauthstring);
940 } else {
941 tor_snprintf(request, sizeof(request),
942 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
943 payload ? (unsigned long)payload_len : 0,
944 hoststring,
945 imsstring,
946 proxyauthstring);
948 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
950 if (payload) {
951 /* then send the payload afterwards too */
952 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
956 /** Parse an HTTP request string <b>headers</b> of the form
957 * \verbatim
958 * "\%s [http[s]://]\%s HTTP/1..."
959 * \endverbatim
960 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
961 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
962 * so it does. Return 0.
963 * Otherwise, return -1.
965 static int
966 parse_http_url(const char *headers, char **url)
968 char *s, *start, *tmp;
970 s = (char *)eat_whitespace_no_nl(headers);
971 if (!*s) return -1;
972 s = (char *)find_whitespace(s); /* get past GET/POST */
973 if (!*s) return -1;
974 s = (char *)eat_whitespace_no_nl(s);
975 if (!*s) return -1;
976 start = s; /* this is it, assuming it's valid */
977 s = (char *)find_whitespace(start);
978 if (!*s) return -1;
980 /* tolerate the http[s] proxy style of putting the hostname in the url */
981 if (s-start >= 4 && !strcmpstart(start,"http")) {
982 tmp = start + 4;
983 if (*tmp == 's')
984 tmp++;
985 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
986 tmp = strchr(tmp+3, '/');
987 if (tmp && tmp < s) {
988 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
989 start = tmp;
994 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
995 *url = tor_malloc(s - start + 5);
996 strlcpy(*url,"/tor", s-start+5);
997 strlcat((*url)+4, start, s-start+1);
998 } else {
999 *url = tor_strndup(start, s-start);
1001 return 0;
1004 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1005 * <b>which</b>. The key should be given with a terminating colon and space;
1006 * this function copies everything after, up to but not including the
1007 * following \\r\\n. */
1008 static char *
1009 http_get_header(const char *headers, const char *which)
1011 const char *cp = headers;
1012 while (cp) {
1013 if (!strcasecmpstart(cp, which)) {
1014 char *eos;
1015 cp += strlen(which);
1016 if ((eos = strchr(cp,'\r')))
1017 return tor_strndup(cp, eos-cp);
1018 else
1019 return tor_strdup(cp);
1021 cp = strchr(cp, '\n');
1022 if (cp)
1023 ++cp;
1025 return NULL;
1028 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1029 * <b>conn</b>-\>address to describe our best guess of the address that
1030 * originated this HTTP request. */
1031 static void
1032 http_set_address_origin(const char *headers, connection_t *conn)
1034 char *fwd;
1036 fwd = http_get_header(headers, "Forwarded-For: ");
1037 if (!fwd)
1038 fwd = http_get_header(headers, "X-Forwarded-For: ");
1039 if (fwd) {
1040 struct in_addr in;
1041 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
1042 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
1043 escaped(fwd));
1044 tor_free(fwd);
1045 return;
1047 tor_free(conn->address);
1048 conn->address = tor_strdup(fwd);
1049 tor_free(fwd);
1053 /** Parse an HTTP response string <b>headers</b> of the form
1054 * \verbatim
1055 * "HTTP/1.\%d \%d\%s\r\n...".
1056 * \endverbatim
1058 * If it's well-formed, assign the status code to *<b>code</b> and
1059 * return 0. Otherwise, return -1.
1061 * On success: If <b>date</b> is provided, set *date to the Date
1062 * header in the http headers, or 0 if no such header is found. If
1063 * <b>compression</b> is provided, set *<b>compression</b> to the
1064 * compression method given in the Content-Encoding header, or 0 if no
1065 * such header is found, or -1 if the value of the header is not
1066 * recognized. If <b>reason</b> is provided, strdup the reason string
1067 * into it.
1070 parse_http_response(const char *headers, int *code, time_t *date,
1071 compress_method_t *compression, char **reason)
1073 int n1, n2;
1074 char datestr[RFC1123_TIME_LEN+1];
1075 smartlist_t *parsed_headers;
1076 tor_assert(headers);
1077 tor_assert(code);
1079 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1081 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
1082 (n1 != 0 && n1 != 1) ||
1083 (n2 < 100 || n2 >= 600)) {
1084 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1085 return -1;
1087 *code = n2;
1089 parsed_headers = smartlist_create();
1090 smartlist_split_string(parsed_headers, headers, "\n",
1091 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1092 if (reason) {
1093 smartlist_t *status_line_elements = smartlist_create();
1094 tor_assert(smartlist_len(parsed_headers));
1095 smartlist_split_string(status_line_elements,
1096 smartlist_get(parsed_headers, 0),
1097 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1098 tor_assert(smartlist_len(status_line_elements) <= 3);
1099 if (smartlist_len(status_line_elements) == 3) {
1100 *reason = smartlist_get(status_line_elements, 2);
1101 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1103 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1104 smartlist_free(status_line_elements);
1106 if (date) {
1107 *date = 0;
1108 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1109 if (!strcmpstart(s, "Date: ")) {
1110 strlcpy(datestr, s+6, sizeof(datestr));
1111 /* This will do nothing on failure, so we don't need to check
1112 the result. We shouldn't warn, since there are many other valid
1113 date formats besides the one we use. */
1114 parse_rfc1123_time(datestr, date);
1115 break;
1118 if (compression) {
1119 const char *enc = NULL;
1120 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1121 if (!strcmpstart(s, "Content-Encoding: ")) {
1122 enc = s+18; break;
1124 if (!enc || !strcmp(enc, "identity")) {
1125 *compression = NO_METHOD;
1126 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1127 *compression = ZLIB_METHOD;
1128 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1129 *compression = GZIP_METHOD;
1130 } else {
1131 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1132 escaped(enc));
1133 *compression = UNKNOWN_METHOD;
1136 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1137 smartlist_free(parsed_headers);
1139 return 0;
1142 /** Return true iff <b>body</b> doesn't start with a plausible router or
1143 * running-list or directory opening. This is a sign of possible compression.
1145 static int
1146 body_is_plausible(const char *body, size_t len, int purpose)
1148 int i;
1149 if (len == 0)
1150 return 1; /* empty bodies don't need decompression */
1151 if (len < 32)
1152 return 0;
1153 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
1154 if (!strcmpstart(body,"router") ||
1155 !strcmpstart(body,"signed-directory") ||
1156 !strcmpstart(body,"network-status") ||
1157 !strcmpstart(body,"running-routers"))
1158 return 1;
1159 for (i=0;i<32;++i) {
1160 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1161 return 0;
1163 return 1;
1164 } else {
1165 return 1;
1169 /** Called when we've just fetched a bunch of router descriptors in
1170 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1171 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1172 * is true, or identity digests otherwise. Parse the descriptors, validate
1173 * them, and annotate them as having purpose <b>purpose</b> and as having been
1174 * downloaded from <b>source</b>. */
1175 static void
1176 load_downloaded_routers(const char *body, smartlist_t *which,
1177 int descriptor_digests,
1178 int router_purpose,
1179 const char *source)
1181 char buf[256];
1182 char time_buf[ISO_TIME_LEN+1];
1183 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1184 format_iso_time(time_buf, time(NULL));
1185 tor_assert(source);
1187 if (tor_snprintf(buf, sizeof(buf),
1188 "@downloaded-at %s\n"
1189 "@source %s\n"
1190 "%s%s%s", time_buf, escaped(source),
1191 !general ? "@purpose " : "",
1192 !general ? router_purpose_to_string(router_purpose) : "",
1193 !general ? "\n" : "")<0)
1194 return;
1196 router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1197 descriptor_digests, buf);
1200 /** We are a client, and we've finished reading the server's
1201 * response. Parse it and act appropriately.
1203 * If we're still happy with using this directory server in the future, return
1204 * 0. Otherwise return -1; and the caller should consider trying the request
1205 * again.
1207 * The caller will take care of marking the connection for close.
1209 static int
1210 connection_dir_client_reached_eof(dir_connection_t *conn)
1212 char *body;
1213 char *headers;
1214 char *reason = NULL;
1215 size_t body_len=0, orig_len=0;
1216 int status_code;
1217 time_t date_header=0;
1218 int delta;
1219 compress_method_t compression;
1220 int plausible;
1221 int skewed=0;
1222 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1223 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
1224 int was_compressed=0;
1225 time_t now = time(NULL);
1227 switch (fetch_from_buf_http(conn->_base.inbuf,
1228 &headers, MAX_HEADERS_SIZE,
1229 &body, &body_len, MAX_DIR_DL_SIZE,
1230 allow_partial)) {
1231 case -1: /* overflow */
1232 log_warn(LD_PROTOCOL,
1233 "'fetch' response too large (server '%s:%d'). Closing.",
1234 conn->_base.address, conn->_base.port);
1235 return -1;
1236 case 0:
1237 log_info(LD_HTTP,
1238 "'fetch' response not all here, but we're at eof. Closing.");
1239 return -1;
1240 /* case 1, fall through */
1242 orig_len = body_len;
1244 if (parse_http_response(headers, &status_code, &date_header,
1245 &compression, &reason) < 0) {
1246 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1247 conn->_base.address, conn->_base.port);
1248 tor_free(body); tor_free(headers);
1249 return -1;
1251 if (!reason) reason = tor_strdup("[no reason given]");
1253 log_debug(LD_DIR,
1254 "Received response from directory server '%s:%d': %d %s",
1255 conn->_base.address, conn->_base.port, status_code,
1256 escaped(reason));
1258 /* now check if it's got any hints for us about our IP address. */
1259 if (conn->dirconn_direct) {
1260 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1261 if (guess) {
1262 router_new_address_suggestion(guess);
1263 tor_free(guess);
1267 if (date_header > 0) {
1268 /* The date header was written very soon after we sent our request,
1269 * so compute the skew as the difference between sending the request
1270 * and the date header. (We used to check now-date_header, but that's
1271 * inaccurate if we spend a lot of time downloading.)
1273 delta = conn->_base.timestamp_lastwritten - date_header;
1274 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1275 char dbuf[64];
1276 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1277 format_time_interval(dbuf, sizeof(dbuf), delta);
1278 log_fn(trusted ? LOG_WARN : LOG_INFO,
1279 LD_HTTP,
1280 "Received directory with skewed time (server '%s:%d'): "
1281 "It seems that our clock is %s by %s, or that theirs is %s. "
1282 "Tor requires an accurate clock to work: please check your time "
1283 "and date settings.",
1284 conn->_base.address, conn->_base.port,
1285 delta>0 ? "ahead" : "behind", dbuf,
1286 delta>0 ? "behind" : "ahead");
1287 skewed = 1; /* don't check the recommended-versions line */
1288 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1289 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
1290 delta, conn->_base.address, conn->_base.port);
1291 } else {
1292 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1293 "we are %d seconds skewed. (That's okay.)", delta);
1296 (void) skewed; /* skewed isn't used yet. */
1298 if (status_code == 503 && body_len < 16) {
1299 routerstatus_t *rs;
1300 trusted_dir_server_t *ds;
1301 log_info(LD_DIR,"Received http status code %d (%s) from server "
1302 "'%s:%d'. I'll try again soon.",
1303 status_code, escaped(reason), conn->_base.address,
1304 conn->_base.port);
1305 if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
1306 rs->last_dir_503_at = now;
1307 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1308 ds->fake_status.last_dir_503_at = now;
1310 tor_free(body); tor_free(headers); tor_free(reason);
1311 return -1;
1312 } else if (status_code == 503) {
1313 /* XXXX022 Remove this once every server with bug 539 is obsolete. */
1314 log_info(LD_DIR, "Server at '%s:%d' sent us a 503 response, but included "
1315 "a body anyway. We'll pretend it gave us a 200.",
1316 conn->_base.address, conn->_base.port);
1317 status_code = 200;
1320 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1321 if (compression != NO_METHOD || !plausible) {
1322 char *new_body = NULL;
1323 size_t new_len = 0;
1324 compress_method_t guessed = detect_compression_method(body, body_len);
1325 if (compression == UNKNOWN_METHOD || guessed != compression) {
1326 /* Tell the user if we don't believe what we're told about compression.*/
1327 const char *description1, *description2;
1328 if (compression == ZLIB_METHOD)
1329 description1 = "as deflated";
1330 else if (compression == GZIP_METHOD)
1331 description1 = "as gzipped";
1332 else if (compression == NO_METHOD)
1333 description1 = "as uncompressed";
1334 else
1335 description1 = "with an unknown Content-Encoding";
1336 if (guessed == ZLIB_METHOD)
1337 description2 = "deflated";
1338 else if (guessed == GZIP_METHOD)
1339 description2 = "gzipped";
1340 else if (!plausible)
1341 description2 = "confusing binary junk";
1342 else
1343 description2 = "uncompressed";
1345 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1346 "but it seems to be %s.%s",
1347 conn->_base.address, conn->_base.port, description1,
1348 description2,
1349 (compression>0 && guessed>0)?" Trying both.":"");
1351 /* Try declared compression first if we can. */
1352 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1353 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1354 !allow_partial, LOG_PROTOCOL_WARN);
1355 /* Okay, if that didn't work, and we think that it was compressed
1356 * differently, try that. */
1357 if (!new_body &&
1358 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1359 compression != guessed)
1360 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1361 !allow_partial, LOG_PROTOCOL_WARN);
1362 /* If we're pretty sure that we have a compressed directory, and
1363 * we didn't manage to uncompress it, then warn and bail. */
1364 if (!plausible && !new_body) {
1365 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1366 "Unable to decompress HTTP body (server '%s:%d').",
1367 conn->_base.address, conn->_base.port);
1368 tor_free(body); tor_free(headers); tor_free(reason);
1369 return -1;
1371 if (new_body) {
1372 tor_free(body);
1373 body = new_body;
1374 body_len = new_len;
1375 was_compressed = 1;
1379 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
1380 /* fetch/process the directory to cache it. */
1381 log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
1382 (int)body_len, conn->_base.address, conn->_base.port);
1383 if (status_code != 200) {
1384 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1385 "'%s:%d' while fetching directory. I'll try again soon.",
1386 status_code, escaped(reason), conn->_base.address,
1387 conn->_base.port);
1388 tor_free(body); tor_free(headers); tor_free(reason);
1389 return -1;
1391 if (router_parse_directory(body) < 0) {
1392 log_notice(LD_DIR,"I failed to parse the directory I fetched from "
1393 "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
1395 note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
1398 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
1399 /* just update our list of running routers, if this list is new info */
1400 log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
1401 if (status_code != 200) {
1402 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1403 "'%s:%d' while fetching running-routers. I'll try again soon.",
1404 status_code, escaped(reason), conn->_base.address,
1405 conn->_base.port);
1406 tor_free(body); tor_free(headers); tor_free(reason);
1407 return -1;
1409 if (router_parse_runningrouters(body)<0) {
1410 log_warn(LD_DIR,
1411 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1412 conn->_base.address, conn->_base.port);
1413 tor_free(body); tor_free(headers); tor_free(reason);
1414 return -1;
1416 note_request(was_compressed?"dl/running-routers.z":
1417 "dl/running-routers", orig_len);
1420 if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
1421 smartlist_t *which = NULL;
1422 networkstatus_source_t source;
1423 char *cp;
1424 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1425 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1426 if (status_code != 200) {
1427 log_warn(LD_DIR,
1428 "Received http status code %d (%s) from server "
1429 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1430 status_code, escaped(reason), conn->_base.address,
1431 conn->_base.port, conn->requested_resource);
1432 tor_free(body); tor_free(headers); tor_free(reason);
1433 connection_dir_download_networkstatus_failed(conn, status_code);
1434 return -1;
1436 note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
1437 if (conn->requested_resource &&
1438 !strcmpstart(conn->requested_resource,"fp/")) {
1439 source = NS_FROM_DIR_BY_FP;
1440 which = smartlist_create();
1441 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1442 which, NULL, 0, 0);
1443 } else if (conn->requested_resource &&
1444 !strcmpstart(conn->requested_resource, "all")) {
1445 source = NS_FROM_DIR_ALL;
1446 which = smartlist_create();
1447 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1448 trusted_dir_server_t *, ds,
1450 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1451 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1452 smartlist_add(which, hex);
1454 } else {
1455 /* XXXX Can we even end up here? -- weasel*/
1456 source = NS_FROM_DIR_BY_FP;
1457 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1458 "for it by fp, nor did we ask for all.");
1460 cp = body;
1461 while (*cp) {
1462 char *next = strstr(cp, "\nnetwork-status-version");
1463 if (next)
1464 next[1] = '\0';
1465 /* learn from it, and then remove it from 'which' */
1466 if (router_set_networkstatus_v2(cp, now, source, which)<0)
1467 break;
1468 if (next) {
1469 next[1] = 'n';
1470 cp = next+1;
1471 } else
1472 break;
1474 /* launches router downloads as needed */
1475 routers_update_all_from_networkstatus(now, 2);
1476 directory_info_has_arrived(now, 0);
1477 if (which) {
1478 if (smartlist_len(which)) {
1479 dir_networkstatus_download_failed(which, status_code);
1481 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1482 smartlist_free(which);
1486 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1487 int r;
1488 if (status_code != 200) {
1489 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1490 log(severity, LD_DIR,
1491 "Received http status code %d (%s) from server "
1492 "'%s:%d' while fetching consensus directory.",
1493 status_code, escaped(reason), conn->_base.address,
1494 conn->_base.port);
1495 tor_free(body); tor_free(headers); tor_free(reason);
1496 networkstatus_consensus_download_failed(status_code);
1497 return -1;
1499 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1500 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1501 if ((r=networkstatus_set_current_consensus(body, 0))<0) {
1502 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1503 "Unable to load consensus directory downloaded from "
1504 "server '%s:%d'", conn->_base.address, conn->_base.port);
1505 tor_free(body); tor_free(headers); tor_free(reason);
1506 networkstatus_consensus_download_failed(0);
1507 return -1;
1509 /* launches router downloads as needed */
1510 routers_update_all_from_networkstatus(now, 3);
1511 directory_info_has_arrived(now, 0);
1512 log_info(LD_DIR, "Successfully loaded consensus.");
1515 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1516 if (status_code != 200) {
1517 log_warn(LD_DIR,
1518 "Received http status code %d (%s) from server "
1519 "'%s:%d' while fetching \"/tor/keys/%s\".",
1520 status_code, escaped(reason), conn->_base.address,
1521 conn->_base.port, conn->requested_resource);
1522 connection_dir_download_cert_failed(conn, status_code);
1523 tor_free(body); tor_free(headers); tor_free(reason);
1524 return -1;
1526 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1527 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1528 if (trusted_dirs_load_certs_from_string(body, 0)<0) {
1529 log_warn(LD_DIR, "Unable to parse fetched certificates");
1530 connection_dir_download_cert_failed(conn, status_code);
1531 } else {
1532 directory_info_has_arrived(now, 0);
1533 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1536 if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1537 const char *msg;
1538 int st;
1539 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1540 (int) body_len, conn->_base.address, conn->_base.port);
1541 if (status_code != 200) {
1542 log_warn(LD_DIR,
1543 "Received http status code %d (%s) from server "
1544 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1545 status_code, escaped(reason), conn->_base.address,
1546 conn->_base.port, conn->requested_resource);
1547 tor_free(body); tor_free(headers); tor_free(reason);
1548 return -1;
1550 dirvote_add_vote(body, &msg, &st);
1551 if (st > 299) {
1552 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1553 } else {
1554 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1557 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1558 const char *msg = NULL;
1559 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1560 (int) body_len, conn->_base.address, conn->_base.port);
1561 if (status_code != 200) {
1562 log_warn(LD_DIR,
1563 "Received http status code %d (%s) from server "
1564 "'%s:%d' while fetching \"/tor/status-vote/consensus-signatures.z\".",
1565 status_code, escaped(reason), conn->_base.address,
1566 conn->_base.port);
1567 tor_free(body); tor_free(headers); tor_free(reason);
1568 return -1;
1570 if (dirvote_add_signatures(body, conn->_base.address, &msg)<0) {
1571 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1572 conn->_base.address, conn->_base.port, msg?msg:"???");
1576 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1577 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1578 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1579 smartlist_t *which = NULL;
1580 int n_asked_for = 0;
1581 int descriptor_digests = conn->requested_resource &&
1582 !strcmpstart(conn->requested_resource,"d/");
1583 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1584 was_ei ? "extra server info" : "server info",
1585 (int)body_len, conn->_base.address, conn->_base.port);
1586 if (was_ei)
1587 note_request(was_compressed?"dl/extra.z":"dl/extra", orig_len);
1588 else
1589 note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
1590 if (conn->requested_resource &&
1591 (!strcmpstart(conn->requested_resource,"d/") ||
1592 !strcmpstart(conn->requested_resource,"fp/"))) {
1593 which = smartlist_create();
1594 dir_split_resource_into_fingerprints(conn->requested_resource +
1595 (descriptor_digests ? 2 : 3),
1596 which, NULL, 0, 0);
1597 n_asked_for = smartlist_len(which);
1599 if (status_code != 200) {
1600 int dir_okay = status_code == 404 ||
1601 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1602 /* 404 means that it didn't have them; no big deal.
1603 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1604 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1605 "Received http status code %d (%s) from server '%s:%d' "
1606 "while fetching \"/tor/server/%s\". I'll try again soon.",
1607 status_code, escaped(reason), conn->_base.address,
1608 conn->_base.port, conn->requested_resource);
1609 if (!which) {
1610 connection_dir_download_routerdesc_failed(conn);
1611 } else {
1612 dir_routerdesc_download_failed(which, status_code,
1613 conn->router_purpose,
1614 was_ei, descriptor_digests);
1615 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1616 smartlist_free(which);
1618 tor_free(body); tor_free(headers); tor_free(reason);
1619 return dir_okay ? 0 : -1;
1621 /* Learn the routers, assuming we requested by fingerprint or "all"
1622 * or "authority".
1624 * We use "authority" to fetch our own descriptor for
1625 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1626 * the output of "authority" requests unless we are using bridges,
1627 * since otherwise they'll be the response from reachability tests,
1628 * and we don't really want to add that to our routerlist. */
1629 if (which || (conn->requested_resource &&
1630 (!strcmpstart(conn->requested_resource, "all") ||
1631 (!strcmpstart(conn->requested_resource, "authority") &&
1632 get_options()->UseBridges)))) {
1633 /* as we learn from them, we remove them from 'which' */
1634 if (was_ei) {
1635 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1636 descriptor_digests);
1637 } else {
1638 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1639 // descriptor_digests, conn->router_purpose);
1640 load_downloaded_routers(body, which, descriptor_digests,
1641 conn->router_purpose,
1642 conn->_base.address);
1643 directory_info_has_arrived(now, 0);
1646 if (which) { /* mark remaining ones as failed */
1647 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1648 n_asked_for-smartlist_len(which), n_asked_for,
1649 was_ei ? "extra-info documents" : "router descriptors",
1650 conn->_base.address, (int)conn->_base.port);
1651 if (smartlist_len(which)) {
1652 dir_routerdesc_download_failed(which, status_code,
1653 conn->router_purpose,
1654 was_ei, descriptor_digests);
1656 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1657 smartlist_free(which);
1659 if (directory_conn_is_self_reachability_test(conn))
1660 router_dirport_found_reachable();
1663 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1664 switch (status_code) {
1665 case 200: {
1666 trusted_dir_server_t *ds =
1667 router_get_trusteddirserver_by_digest(conn->identity_digest);
1668 char *rejected_hdr = http_get_header(headers,
1669 "X-Descriptor-Not-New: ");
1670 int rejected = 0;
1671 if (rejected_hdr) {
1672 if (!strcmp(rejected_hdr, "Yes")) {
1673 /* XXXX020 use this information; be sure to upload next one
1674 * sooner. */
1675 rejected = 1;
1677 tor_free(rejected_hdr);
1679 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1680 "descriptor: finished.");
1681 control_event_server_status(
1682 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1683 conn->_base.address, conn->_base.port);
1685 ds->has_accepted_serverdesc = 1;
1686 if (directories_have_accepted_server_descriptor())
1687 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1689 break;
1690 case 400:
1691 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1692 "dirserver '%s:%d'. Please correct.",
1693 escaped(reason), conn->_base.address, conn->_base.port);
1694 control_event_server_status(LOG_WARN,
1695 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1696 conn->_base.address, conn->_base.port, escaped(reason));
1697 break;
1698 default:
1699 log_warn(LD_GENERAL,
1700 "http status %d (%s) reason unexpected while uploading "
1701 "descriptor to server '%s:%d').",
1702 status_code, escaped(reason), conn->_base.address,
1703 conn->_base.port);
1704 break;
1706 /* return 0 in all cases, since we don't want to mark any
1707 * dirservers down just because they don't like us. */
1710 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
1711 switch (status_code) {
1712 case 200: {
1713 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
1714 conn->_base.address, conn->_base.port);
1716 break;
1717 case 400:
1718 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1719 "vote to dirserver '%s:%d'. Please correct.",
1720 escaped(reason), conn->_base.address, conn->_base.port);
1721 break;
1722 default:
1723 log_warn(LD_GENERAL,
1724 "http status %d (%s) reason unexpected while uploading "
1725 "vote to server '%s:%d').",
1726 status_code, escaped(reason), conn->_base.address,
1727 conn->_base.port);
1728 break;
1730 /* return 0 in all cases, since we don't want to mark any
1731 * dirservers down just because they don't like us. */
1734 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
1735 switch (status_code) {
1736 case 200: {
1737 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
1738 conn->_base.address, conn->_base.port);
1740 break;
1741 case 400:
1742 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1743 "signatures to dirserver '%s:%d'. Please correct.",
1744 escaped(reason), conn->_base.address, conn->_base.port);
1745 break;
1746 default:
1747 log_warn(LD_GENERAL,
1748 "http status %d (%s) reason unexpected while uploading "
1749 "signatures to server '%s:%d').",
1750 status_code, escaped(reason), conn->_base.address,
1751 conn->_base.port);
1752 break;
1754 /* return 0 in all cases, since we don't want to mark any
1755 * dirservers down just because they don't like us. */
1758 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1759 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1760 "(%s))",
1761 (int)body_len, status_code, escaped(reason));
1762 switch (status_code) {
1763 case 200:
1764 if (rend_cache_store(body, body_len, 0) < 0) {
1765 log_warn(LD_REND,"Failed to fetch rendezvous descriptor.");
1766 /* Any pending rendezvous attempts will notice when
1767 * connection_about_to_close_connection()
1768 * cleans this dir conn up. */
1769 /* We could retry. But since v0 descriptors are going out of
1770 * style, it isn't worth the hassle. We'll do better in v2. */
1771 } else {
1772 /* success. notify pending connections about this. */
1773 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1774 rend_client_desc_here(conn->rend_query);
1776 break;
1777 case 404:
1778 /* Not there. Pending connections will be notified when
1779 * connection_about_to_close_connection() cleans this conn up. */
1780 break;
1781 case 400:
1782 log_warn(LD_REND,
1783 "http status 400 (%s). Dirserver didn't like our "
1784 "rendezvous query?", escaped(reason));
1785 break;
1786 default:
1787 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1788 "fetching hidden service descriptor (server '%s:%d').",
1789 status_code, escaped(reason), conn->_base.address,
1790 conn->_base.port);
1791 break;
1795 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
1796 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1797 "(%s))",
1798 (int)body_len, status_code, escaped(reason));
1799 switch (status_code) {
1800 case 200:
1801 if (rend_cache_store_v2_desc_as_client(body, NULL) < 0) {
1802 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
1803 "Retrying at another directory.");
1804 /* We'll retry when connection_about_to_close_connection()
1805 * cleans this dir conn up. */
1806 } else {
1807 /* success. notify pending connections about this. */
1808 log_info(LD_REND, "Successfully fetched rendezvous descriptor.");
1809 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1810 rend_client_desc_here(conn->rend_query);
1812 break;
1813 case 404:
1814 /* Not there. We'll retry when
1815 * connection_about_to_close_connection() cleans this conn up. */
1816 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
1817 "Retrying at another directory.");
1818 break;
1819 case 400:
1820 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1821 "http status 400 (%s). Dirserver didn't like our "
1822 "v2 rendezvous query? Retrying at another directory.",
1823 escaped(reason));
1824 break;
1825 default:
1826 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1827 "http status %d (%s) response unexpected while "
1828 "fetching v2 hidden service descriptor (server '%s:%d'). "
1829 "Retrying at another directory.",
1830 status_code, escaped(reason), conn->_base.address,
1831 conn->_base.port);
1832 break;
1836 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
1837 conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
1838 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
1839 "(%s))",
1840 status_code, escaped(reason));
1841 switch (status_code) {
1842 case 200:
1843 log_info(LD_REND,
1844 "Uploading rendezvous descriptor: finished with status "
1845 "200 (%s)", escaped(reason));
1846 break;
1847 case 400:
1848 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1849 "'%s:%d'. Malformed rendezvous descriptor?",
1850 escaped(reason), conn->_base.address, conn->_base.port);
1851 break;
1852 case 503:
1853 log_info(LD_REND,"http status 503 (%s) response from dirserver "
1854 "'%s:%d'. Node is (currently) not acting as v2 hidden "
1855 "service directory.",
1856 escaped(reason), conn->_base.address, conn->_base.port);
1857 break;
1858 default:
1859 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1860 "'%s:%d').",
1861 status_code, escaped(reason), conn->_base.address,
1862 conn->_base.port);
1863 break;
1866 tor_free(body); tor_free(headers); tor_free(reason);
1867 return 0;
1870 /** Called when a directory connection reaches EOF */
1872 connection_dir_reached_eof(dir_connection_t *conn)
1874 int retval;
1875 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
1876 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
1877 conn->_base.state);
1878 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
1879 connection_mark_for_close(TO_CONN(conn));
1880 return -1;
1883 retval = connection_dir_client_reached_eof(conn);
1884 if (retval == 0) /* success */
1885 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
1886 connection_mark_for_close(TO_CONN(conn));
1887 return retval;
1890 /** If any directory object is arriving, and it's over 10MB large, we're
1891 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1892 * ask for more than 96 router descriptors at a time.)
1894 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1896 /** Read handler for directory connections. (That's connections <em>to</em>
1897 * directory servers and connections <em>at</em> directory servers.)
1900 connection_dir_process_inbuf(dir_connection_t *conn)
1902 tor_assert(conn);
1903 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1905 /* Directory clients write, then read data until they receive EOF;
1906 * directory servers read data until they get an HTTP command, then
1907 * write their response (when it's finished flushing, they mark for
1908 * close).
1911 /* If we're on the dirserver side, look for a command. */
1912 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1913 if (directory_handle_command(conn) < 0) {
1914 connection_mark_for_close(TO_CONN(conn));
1915 return -1;
1917 return 0;
1920 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
1921 log_warn(LD_HTTP, "Too much data received from directory connection: "
1922 "denial of service attempt, or you need to upgrade?");
1923 connection_mark_for_close(TO_CONN(conn));
1924 return -1;
1927 if (!conn->_base.inbuf_reached_eof)
1928 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1929 return 0;
1932 /** Create an http response for the client <b>conn</b> out of
1933 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1935 static void
1936 write_http_status_line(dir_connection_t *conn, int status,
1937 const char *reason_phrase)
1939 char buf[256];
1940 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1941 status, reason_phrase ? reason_phrase : "OK") < 0) {
1942 log_warn(LD_BUG,"status line too long.");
1943 return;
1945 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
1948 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1949 * with <b>type</b> as the Content-Type.
1951 * If <b>length</b> is nonnegative, it is the Content-Length.
1952 * If <b>encoding</b> is provided, it is the Content-Encoding.
1953 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1954 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1955 static void
1956 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
1957 const char *type, const char *encoding,
1958 const char *extra_headers,
1959 int cache_lifetime)
1961 char date[RFC1123_TIME_LEN+1];
1962 char tmp[1024];
1963 char *cp;
1964 time_t now = time(NULL);
1966 tor_assert(conn);
1968 format_rfc1123_time(date, now);
1969 cp = tmp;
1970 tor_snprintf(cp, sizeof(tmp),
1971 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
1972 date);
1973 cp += strlen(tmp);
1974 if (type) {
1975 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
1976 cp += strlen(cp);
1978 if (!is_internal_IP(conn->_base.addr, 0)) {
1979 /* Don't report the source address for a localhost/private connection. */
1980 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1981 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
1982 cp += strlen(cp);
1984 if (encoding) {
1985 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1986 "Content-Encoding: %s\r\n", encoding);
1987 cp += strlen(cp);
1989 if (length >= 0) {
1990 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1991 "Content-Length: %ld\r\n", (long)length);
1992 cp += strlen(cp);
1994 if (cache_lifetime > 0) {
1995 char expbuf[RFC1123_TIME_LEN+1];
1996 format_rfc1123_time(expbuf, now + cache_lifetime);
1997 /* We could say 'Cache-control: max-age=%d' here if we start doing
1998 * http/1.1 */
1999 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2000 "Expires: %s\r\n", expbuf);
2001 cp += strlen(cp);
2002 } else if (cache_lifetime == 0) {
2003 /* We could say 'Cache-control: no-cache' here if we start doing
2004 * http/1.1 */
2005 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2006 cp += strlen(cp);
2008 if (extra_headers)
2009 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2010 if (sizeof(tmp)-(cp-tmp) > 3)
2011 memcpy(cp, "\r\n", 3);
2012 else
2013 tor_assert(0);
2014 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2017 /** As write_http_response_header_impl, but sets encoding and content-typed
2018 * based on whether the response will be <b>deflated</b> or not. */
2019 static void
2020 write_http_response_header(dir_connection_t *conn, ssize_t length,
2021 int deflated, int cache_lifetime)
2023 write_http_response_header_impl(conn, length,
2024 deflated?"application/octet-stream":"text/plain",
2025 deflated?"deflate":"identity",
2026 NULL,
2027 cache_lifetime);
2030 /** Helper function: return 1 if there are any dir conns of purpose
2031 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
2032 * Else return 0.
2034 static int
2035 already_fetching_directory(int purpose)
2037 smartlist_t *conns = get_connection_array();
2038 SMARTLIST_FOREACH(conns, connection_t *, conn,
2040 if (conn->type == CONN_TYPE_DIR &&
2041 conn->purpose == purpose &&
2042 !conn->marked_for_close &&
2043 !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
2044 return 1;
2046 return 0;
2049 #ifdef INSTRUMENT_DOWNLOADS
2050 /** Map used to keep track of how much data we've up/downloaded in what kind
2051 * of request. Maps from request type to pointer to uint64_t. */
2052 static strmap_t *request_bytes_map = NULL;
2054 /** Called when we just transmitted or received <b>bytes</b> worth of data
2055 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2056 * <b>bytes</b> to the total associated with key. */
2057 static void
2058 note_request(const char *key, size_t bytes)
2060 uint64_t *n;
2061 if (!request_bytes_map)
2062 request_bytes_map = strmap_new();
2064 n = strmap_get(request_bytes_map, key);
2065 if (!n) {
2066 n = tor_malloc_zero(sizeof(uint64_t));
2067 strmap_set(request_bytes_map, key, n);
2069 *n += bytes;
2072 /** Return a newly allocated string holding a summary of bytes used per
2073 * request type. */
2074 char *
2075 directory_dump_request_log(void)
2077 smartlist_t *lines;
2078 char tmp[256];
2079 char *result;
2080 strmap_iter_t *iter;
2082 if (!request_bytes_map)
2083 request_bytes_map = strmap_new();
2085 lines = smartlist_create();
2087 for (iter = strmap_iter_init(request_bytes_map);
2088 !strmap_iter_done(iter);
2089 iter = strmap_iter_next(request_bytes_map, iter)) {
2090 const char *key;
2091 void *val;
2092 uint64_t *n;
2093 strmap_iter_get(iter, &key, &val);
2094 n = val;
2095 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT"\n",
2096 key, U64_PRINTF_ARG(*n));
2097 smartlist_add(lines, tor_strdup(tmp));
2099 smartlist_sort_strings(lines);
2100 result = smartlist_join_strings(lines, "", 0, NULL);
2101 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2102 smartlist_free(lines);
2103 return result;
2105 #else
2106 static void
2107 note_request(const char *key, size_t bytes)
2109 (void)key;
2110 (void)bytes;
2113 char *
2114 directory_dump_request_log(void)
2116 return tor_strdup("Not supported.");
2118 #endif
2120 /** Helper function: called when a dirserver gets a complete HTTP GET
2121 * request. Look for a request for a directory or for a rendezvous
2122 * service descriptor. On finding one, write a response into
2123 * conn-\>outbuf. If the request is unrecognized, send a 400.
2124 * Always return 0. */
2125 static int
2126 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2127 const char *body, size_t body_len)
2129 size_t dlen;
2130 char *url, *url_mem, *header;
2131 or_options_t *options = get_options();
2132 time_t if_modified_since = 0;
2133 int deflated = 0;
2134 size_t url_len;
2136 /* We ignore the body of a GET request. */
2137 (void)body;
2138 (void)body_len;
2140 log_debug(LD_DIRSERV,"Received GET command.");
2142 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2144 if (parse_http_url(headers, &url) < 0) {
2145 write_http_status_line(conn, 400, "Bad request");
2146 return 0;
2148 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2149 struct tm tm;
2150 if (parse_http_time(header, &tm) == 0) {
2151 if_modified_since = tor_timegm(&tm);
2153 /* The correct behavior on a malformed If-Modified-Since header is to
2154 * act as if no If-Modified-Since header had been given. */
2155 tor_free(header);
2157 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2159 url_mem = url;
2160 url_len = strlen(url);
2161 deflated = url_len > 2 && !strcmp(url+url_len-2, ".z");
2162 if (deflated) {
2163 url[url_len-2] = '\0';
2164 url_len -= 2;
2167 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* dir fetch */
2168 cached_dir_t *d = dirserv_get_directory();
2170 if (!d) {
2171 log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
2172 "don't have a good one yet. Sending 503 Dir not available.");
2173 write_http_status_line(conn, 503, "Directory unavailable");
2174 /* try to get a new one now */
2175 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR) &&
2176 !should_delay_dir_fetches(options))
2177 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR,
2178 ROUTER_PURPOSE_GENERAL, NULL, 1);
2179 goto done;
2181 if (d->published < if_modified_since) {
2182 write_http_status_line(conn, 304, "Not modified");
2183 goto done;
2186 dlen = deflated ? d->dir_z_len : d->dir_len;
2188 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2189 log_info(LD_DIRSERV,
2190 "Client asked for the mirrored directory, but we've been "
2191 "writing too many bytes lately. Sending 503 Dir busy.");
2192 write_http_status_line(conn, 503, "Directory busy, try again later");
2193 goto done;
2196 note_request(url, dlen);
2198 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
2199 deflated?"deflated ":"");
2200 write_http_response_header(conn, dlen, deflated,
2201 FULL_DIR_CACHE_LIFETIME);
2202 conn->cached_dir = d;
2203 conn->cached_dir_offset = 0;
2204 if (! deflated)
2205 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2206 ++d->refcnt;
2208 /* Prime the connection with some data. */
2209 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
2210 connection_dirserv_flushed_some(conn);
2211 goto done;
2214 if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
2215 cached_dir_t *d = dirserv_get_runningrouters();
2216 if (!d) {
2217 write_http_status_line(conn, 503, "Directory unavailable");
2218 /* try to get a new one now */
2219 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST) &&
2220 !should_delay_dir_fetches(options))
2221 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST,
2222 ROUTER_PURPOSE_GENERAL, NULL, 1);
2223 goto done;
2225 if (d->published < if_modified_since) {
2226 write_http_status_line(conn, 304, "Not modified");
2227 goto done;
2229 dlen = deflated ? d->dir_z_len : d->dir_len;
2231 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2232 log_info(LD_DIRSERV,
2233 "Client asked for running-routers, but we've been "
2234 "writing too many bytes lately. Sending 503 Dir busy.");
2235 write_http_status_line(conn, 503, "Directory busy, try again later");
2236 goto done;
2238 note_request(url, dlen);
2239 write_http_response_header(conn, dlen, deflated,
2240 RUNNINGROUTERS_CACHE_LIFETIME);
2241 connection_write_to_buf(deflated ? d->dir_z : d->dir, dlen, TO_CONN(conn));
2242 goto done;
2245 if (!strcmpstart(url,"/tor/status/")
2246 || !strcmp(url, "/tor/status-vote/current/consensus")) {
2247 /* v2 or v3 network status fetch. */
2248 smartlist_t *dir_fps = smartlist_create();
2249 int is_v3 = !strcmpstart(url, "/tor/status-vote");
2250 const char *request_type = NULL;
2251 const char *key = url + strlen("/tor/status/");
2252 int lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2253 if (!is_v3) {
2254 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
2255 if (!strcmpstart(key, "fp/"))
2256 request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
2257 else if (!strcmpstart(key, "authority"))
2258 request_type = deflated?"/tor/status/authority.z":
2259 "/tor/status/authority";
2260 else if (!strcmpstart(key, "all"))
2261 request_type = deflated?"/tor/status/all.z":"/tor/status/all";
2262 else
2263 request_type = "/tor/status/?";
2264 } else {
2265 networkstatus_vote_t *v = networkstatus_get_latest_consensus();
2266 time_t now = time(NULL);
2267 smartlist_add(dir_fps, tor_memdup("\0\0\0\0\0\0\0\0\0\0"
2268 "\0\0\0\0\0\0\0\0\0\0", 20));
2269 request_type = deflated?"v3.z":"v3";
2270 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2273 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2274 write_http_status_line(conn, 503, "Network status object unavailable");
2275 smartlist_free(dir_fps);
2276 goto done;
2279 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2280 write_http_status_line(conn, 404, "Not found");
2281 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2282 smartlist_free(dir_fps);
2283 goto done;
2284 } else if (!smartlist_len(dir_fps)) {
2285 write_http_status_line(conn, 304, "Not modified");
2286 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2287 smartlist_free(dir_fps);
2288 goto done;
2291 dlen = dirserv_estimate_data_size(dir_fps, 0, deflated);
2292 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2293 log_info(LD_DIRSERV,
2294 "Client asked for network status lists, but we've been "
2295 "writing too many bytes lately. Sending 503 Dir busy.");
2296 write_http_status_line(conn, 503, "Directory busy, try again later");
2297 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2298 smartlist_free(dir_fps);
2299 goto done;
2302 // note_request(request_type,dlen);
2303 (void) request_type;
2304 write_http_response_header(conn, -1, deflated,
2305 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2306 conn->fingerprint_stack = dir_fps;
2307 if (! deflated)
2308 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2310 /* Prime the connection with some data. */
2311 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2312 connection_dirserv_flushed_some(conn);
2313 goto done;
2316 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2317 !strcmpstart(url,"/tor/status-vote/next/")) {
2318 /* XXXX If-modified-since is only implemented for the current
2319 * consensus: that's probably fine, since it's the only vote document
2320 * people fetch much.*/
2321 int current = 1;
2322 ssize_t body_len = 0;
2323 ssize_t estimated_len = 0;
2324 smartlist_t *items = smartlist_create();
2325 smartlist_t *dir_items = smartlist_create();
2326 int lifetime = 60; /* XXXX020 should actually use vote intervals. */
2327 url += strlen("/tor/status-vote/");
2328 current = !strcmpstart(url, "current/");
2329 url = strchr(url, '/');
2330 tor_assert(url);
2331 ++url;
2332 if (!strcmp(url, "consensus")) {
2333 const char *item;
2334 tor_assert(!current); /* we handle current consensus specially above,
2335 * since it wants to be spooled. */
2336 if ((item = dirvote_get_pending_consensus()))
2337 smartlist_add(items, (char*)item);
2338 } else if (!current && !strcmp(url, "consensus-signatures")) {
2339 /* XXXX020 the spec says that we should implement
2340 * current/consensus-signatures too. Why? -NM */
2341 const char *item;
2342 if ((item=dirvote_get_pending_detached_signatures()))
2343 smartlist_add(items, (char*)item);
2344 } else if (!strcmp(url, "authority")) {
2345 const cached_dir_t *d;
2346 int flags = DGV_BY_ID |
2347 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2348 if ((d=dirvote_get_vote(NULL, flags)))
2349 smartlist_add(dir_items, (cached_dir_t*)d);
2350 } else {
2351 const cached_dir_t *d;
2352 smartlist_t *fps = smartlist_create();
2353 int flags;
2354 if (!strcmpstart(url, "d/")) {
2355 url += 2;
2356 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2357 } else {
2358 flags = DGV_BY_ID |
2359 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2361 dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1);
2362 SMARTLIST_FOREACH(fps, char *, fp, {
2363 if ((d = dirvote_get_vote(fp, flags)))
2364 smartlist_add(dir_items, (cached_dir_t*)d);
2365 tor_free(fp);
2367 smartlist_free(fps);
2369 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2370 write_http_status_line(conn, 404, "Not found");
2371 goto vote_done;
2373 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2374 body_len += deflated ? d->dir_z_len : d->dir_len);
2375 estimated_len += body_len;
2376 SMARTLIST_FOREACH(items, const char *, item, {
2377 size_t ln = strlen(item);
2378 if (deflated) {
2379 body_len += ln; estimated_len += ln;
2380 } else {
2381 estimated_len += ln/2;
2385 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 1)) {
2386 write_http_status_line(conn, 503, "Directory busy, try again later.");
2387 goto vote_done;
2389 write_http_response_header(conn, body_len ? body_len : -1, deflated,
2390 lifetime);
2392 if (smartlist_len(items)) {
2393 if (deflated) {
2394 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2395 SMARTLIST_FOREACH(items, const char *, c,
2396 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2397 connection_write_to_buf_zlib("", 0, conn, 1);
2398 } else {
2399 SMARTLIST_FOREACH(items, const char *, c,
2400 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2402 } else {
2403 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2404 connection_write_to_buf(deflated ? d->dir_z : d->dir,
2405 deflated ? d->dir_z_len : d->dir_len,
2406 TO_CONN(conn)));
2408 vote_done:
2409 smartlist_free(items);
2410 smartlist_free(dir_items);
2411 goto done;
2414 if (!strcmpstart(url,"/tor/server/") ||
2415 !strcmpstart(url,"/tor/extra/")) {
2416 int res;
2417 const char *msg;
2418 const char *request_type = NULL;
2419 int cache_lifetime = 0;
2420 int is_extra = !strcmpstart(url,"/tor/extra/");
2421 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2422 conn->fingerprint_stack = smartlist_create();
2423 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2424 &msg,
2425 !connection_dir_is_encrypted(conn));
2427 if (!strcmpstart(url, "fp/")) {
2428 request_type = deflated?"/tor/server/fp.z":"/tor/server/fp";
2429 if (smartlist_len(conn->fingerprint_stack) == 1)
2430 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2431 } else if (!strcmpstart(url, "authority")) {
2432 request_type = deflated?"/tor/server/authority.z":
2433 "/tor/server/authority";
2434 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2435 } else if (!strcmpstart(url, "all")) {
2436 request_type = deflated?"/tor/server/all.z":"/tor/server/all";
2437 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2438 } else if (!strcmpstart(url, "d/")) {
2439 request_type = deflated?"/tor/server/d.z":"/tor/server/d";
2440 if (smartlist_len(conn->fingerprint_stack) == 1)
2441 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2442 } else {
2443 request_type = "/tor/server/?";
2445 (void) request_type; /* usable for note_request. */
2446 if (!strcmpstart(url, "d/"))
2447 conn->dir_spool_src =
2448 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2449 else
2450 conn->dir_spool_src =
2451 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2453 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2454 conn->dir_spool_src)) {
2455 res = -1;
2456 msg = "Not found";
2459 if (res < 0)
2460 write_http_status_line(conn, 404, msg);
2461 else {
2462 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2463 1, deflated);
2464 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2465 log_info(LD_DIRSERV,
2466 "Client asked for server descriptors, but we've been "
2467 "writing too many bytes lately. Sending 503 Dir busy.");
2468 write_http_status_line(conn, 503, "Directory busy, try again later");
2469 conn->dir_spool_src = DIR_SPOOL_NONE;
2470 goto done;
2472 write_http_response_header(conn, -1, deflated, cache_lifetime);
2473 if (deflated)
2474 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2475 /* Prime the connection with some data. */
2476 connection_dirserv_flushed_some(conn);
2478 goto done;
2481 if (!strcmpstart(url,"/tor/keys/")) {
2482 smartlist_t *certs = smartlist_create();
2483 ssize_t len = -1;
2484 if (!strcmp(url, "/tor/keys/all")) {
2485 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
2486 trusted_dir_server_t *, ds,
2488 if (!ds->v3_certs)
2489 continue;
2490 SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
2491 smartlist_add(certs, cert));
2493 } else if (!strcmp(url, "/tor/keys/authority")) {
2494 authority_cert_t *cert = get_my_v3_authority_cert();
2495 if (cert)
2496 smartlist_add(certs, cert);
2497 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
2498 smartlist_t *fps = smartlist_create();
2499 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
2500 fps, NULL, 1, 1);
2501 SMARTLIST_FOREACH(fps, char *, d, {
2502 authority_cert_t *c = authority_cert_get_newest_by_id(d);
2503 if (c) smartlist_add(certs, c);
2504 tor_free(d);
2506 smartlist_free(fps);
2507 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
2508 smartlist_t *fps = smartlist_create();
2509 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
2510 fps, NULL, 1, 1);
2511 SMARTLIST_FOREACH(fps, char *, d, {
2512 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
2513 if (c) smartlist_add(certs, c);
2514 tor_free(d);
2516 smartlist_free(fps);
2517 } else {
2518 write_http_status_line(conn, 400, "Bad request");
2519 goto keys_done;
2521 if (!smartlist_len(certs)) {
2522 write_http_status_line(conn, 404, "Not found");
2523 goto keys_done;
2525 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2526 if (c->cache_info.published_on < if_modified_since)
2527 SMARTLIST_DEL_CURRENT(certs, c));
2528 if (!smartlist_len(certs)) {
2529 write_http_status_line(conn, 304, "Not modified");
2530 goto keys_done;
2532 len = 0;
2533 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2534 len += c->cache_info.signed_descriptor_len);
2536 if (global_write_bucket_low(TO_CONN(conn), deflated?len/2:len, 1)) {
2537 write_http_status_line(conn, 503, "Directory busy, try again later.");
2538 goto keys_done;
2541 write_http_response_header(conn, deflated?-1:len, deflated, 60*60);
2542 if (deflated) {
2543 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2544 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2545 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
2546 c->cache_info.signed_descriptor_len,
2547 conn, 0));
2548 connection_write_to_buf_zlib("", 0, conn, 1);
2549 } else {
2550 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2551 connection_write_to_buf(c->cache_info.signed_descriptor_body,
2552 c->cache_info.signed_descriptor_len,
2553 TO_CONN(conn)));
2555 keys_done:
2556 smartlist_free(certs);
2557 goto done;
2560 if (options->HidServDirectoryV2 &&
2561 !strcmpstart(url,"/tor/rendezvous2/")) {
2562 /* Handle v2 rendezvous descriptor fetch request. */
2563 const char *descp;
2564 const char *query = url + strlen("/tor/rendezvous2/");
2565 if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) {
2566 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
2567 query);
2568 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
2569 case 1: /* valid */
2570 write_http_response_header(conn, strlen(descp), 0, 0);
2571 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
2572 break;
2573 case 0: /* well-formed but not present */
2574 write_http_status_line(conn, 404, "Not found");
2575 break;
2576 case -1: /* not well-formed */
2577 write_http_status_line(conn, 400, "Bad request");
2578 break;
2580 } else { /* not well-formed */
2581 write_http_status_line(conn, 400, "Bad request");
2583 goto done;
2586 if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) {
2587 /* rendezvous descriptor fetch */
2588 const char *descp;
2589 size_t desc_len;
2590 const char *query = url+strlen("/tor/rendezvous/");
2592 log_info(LD_REND, "Handling rendezvous descriptor get");
2593 switch (rend_cache_lookup_desc(query, 0, &descp, &desc_len)) {
2594 case 1: /* valid */
2595 write_http_response_header_impl(conn, desc_len,
2596 "application/octet-stream",
2597 NULL, NULL, 0);
2598 note_request("/tor/rendezvous?/", desc_len);
2599 /* need to send descp separately, because it may include nuls */
2600 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
2601 /* report successful fetch to statistic */
2602 if (options->HSAuthorityRecordStats) {
2603 hs_usage_note_fetch_total(query, time(NULL));
2604 hs_usage_note_fetch_successful(query, time(NULL));
2606 break;
2607 case 0: /* well-formed but not present */
2608 write_http_status_line(conn, 404, "Not found");
2609 /* report (unsuccessful) fetch to statistic */
2610 if (options->HSAuthorityRecordStats) {
2611 hs_usage_note_fetch_total(query, time(NULL));
2613 break;
2614 case -1: /* not well-formed */
2615 write_http_status_line(conn, 400, "Bad request");
2616 break;
2618 goto done;
2621 if (options->BridgeAuthoritativeDir &&
2622 options->BridgePassword &&
2623 connection_dir_is_encrypted(conn) &&
2624 !strcmp(url,"/tor/networkstatus-bridges")) {
2625 char *status;
2626 char decoded[64];
2627 char *secret;
2628 int r;
2630 header = http_get_header(headers, "Authorization: Basic ");
2632 if (!header) {
2633 write_http_status_line(conn, 404, "Not found");
2634 goto done;
2637 /* now make sure the password is right */
2638 r = base64_decode(decoded, sizeof(decoded), header, strlen(header));
2639 secret = alloc_http_authenticator(options->BridgePassword);
2640 if (r < 0 || (unsigned)r != strlen(secret) || memcmp(decoded, secret, r)) {
2641 /* failed to decode, or didn't match. Refuse. */
2642 write_http_status_line(conn, 404, "Not found");
2643 tor_free(header);
2644 goto done;
2646 tor_free(secret);
2648 /* all happy now. send an answer. */
2649 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
2650 dlen = strlen(status);
2651 write_http_response_header(conn, dlen, 0, 0);
2652 connection_write_to_buf(status, dlen, TO_CONN(conn));
2653 tor_free(status);
2654 goto done;
2657 if (!strcmpstart(url,"/tor/bytes.txt")) {
2658 char *bytes = directory_dump_request_log();
2659 size_t len = strlen(bytes);
2660 write_http_response_header(conn, len, 0, 0);
2661 connection_write_to_buf(bytes, len, TO_CONN(conn));
2662 tor_free(bytes);
2663 goto done;
2666 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
2667 rewritten to /tor/robots.txt */
2668 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
2669 size_t len = strlen(robots);
2670 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
2671 connection_write_to_buf(robots, len, TO_CONN(conn));
2672 goto done;
2675 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
2676 #define ADD_MALLINFO_LINE(x) do { \
2677 tor_snprintf(tmp, sizeof(tmp), "%s %d\n", #x, mi.x); \
2678 smartlist_add(lines, tor_strdup(tmp)); \
2679 }while(0);
2681 if (!strcmp(url,"/tor/mallinfo.txt") &&
2682 (conn->_base.addr == 0x7f000001ul)) {
2683 char *result;
2684 size_t len;
2685 struct mallinfo mi;
2686 smartlist_t *lines;
2687 char tmp[256];
2689 memset(&mi, 0, sizeof(mi));
2690 mi = mallinfo();
2691 lines = smartlist_create();
2693 ADD_MALLINFO_LINE(arena)
2694 ADD_MALLINFO_LINE(ordblks)
2695 ADD_MALLINFO_LINE(smblks)
2696 ADD_MALLINFO_LINE(hblks)
2697 ADD_MALLINFO_LINE(hblkhd)
2698 ADD_MALLINFO_LINE(usmblks)
2699 ADD_MALLINFO_LINE(fsmblks)
2700 ADD_MALLINFO_LINE(uordblks)
2701 ADD_MALLINFO_LINE(fordblks)
2702 ADD_MALLINFO_LINE(keepcost)
2704 result = smartlist_join_strings(lines, "", 0, NULL);
2705 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2706 smartlist_free(lines);
2708 len = strlen(result);
2709 write_http_response_header(conn, len, 0, 0);
2710 connection_write_to_buf(result, len, TO_CONN(conn));
2711 tor_free(result);
2712 goto done;
2714 #endif
2716 /* we didn't recognize the url */
2717 write_http_status_line(conn, 404, "Not found");
2719 done:
2720 tor_free(url_mem);
2721 return 0;
2724 /** Helper function: called when a dirserver gets a complete HTTP POST
2725 * request. Look for an uploaded server descriptor or rendezvous
2726 * service descriptor. On finding one, process it and write a
2727 * response into conn-\>outbuf. If the request is unrecognized, send a
2728 * 400. Always return 0. */
2729 static int
2730 directory_handle_command_post(dir_connection_t *conn, const char *headers,
2731 const char *body, size_t body_len)
2733 char *url = NULL;
2734 or_options_t *options = get_options();
2736 log_debug(LD_DIRSERV,"Received POST command.");
2738 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2740 if (parse_http_url(headers, &url) < 0) {
2741 write_http_status_line(conn, 400, "Bad request");
2742 return 0;
2744 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2746 /* Handle v2 rendezvous service publish request. */
2747 if (options->HidServDirectoryV2 &&
2748 !strcmpstart(url,"/tor/rendezvous2/publish")) {
2749 switch (rend_cache_store_v2_desc_as_dir(body)) {
2750 case -2:
2751 log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
2752 "since we're not currently a hidden service directory.",
2753 (int)body_len, conn->_base.address);
2754 write_http_status_line(conn, 503, "Currently not acting as v2 "
2755 "hidden service directory");
2756 break;
2757 case -1:
2758 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
2759 (int)body_len, conn->_base.address);
2760 write_http_status_line(conn, 400, "Invalid service descriptor "
2761 "rejected");
2762 break;
2763 default:
2764 write_http_status_line(conn, 200, "Service descriptor stored");
2765 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
2767 goto done;
2770 if (!authdir_mode(options)) {
2771 /* we just provide cached directories; we don't want to
2772 * receive anything. */
2773 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
2774 "accept posted server descriptors");
2775 return 0;
2778 if (authdir_mode_handles_descs(options, -1) &&
2779 !strcmp(url,"/tor/")) { /* server descriptor post */
2780 const char *msg = NULL;
2781 uint8_t purpose = authdir_mode_bridge(options) ?
2782 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
2783 int r = dirserv_add_multiple_descriptors(body, purpose,
2784 conn->_base.address, &msg);
2785 tor_assert(msg);
2786 if (r > 0)
2787 dirserv_get_directory(); /* rebuild and write to disk */
2788 switch (r) {
2789 case -1:
2790 log_notice(LD_DIRSERV,
2791 "Rejected router descriptor or extra-info from %s "
2792 "(\"%s\").",
2793 conn->_base.address, msg);
2794 /* fall through */
2795 case 1:
2796 /* malformed descriptor, or something wrong */
2797 write_http_status_line(conn, 400, msg);
2798 break;
2799 case 0: /* accepted but discarded */
2800 write_http_response_header_impl(conn, -1, NULL, NULL,
2801 "X-Descriptor-Not-New: Yes\r\n", -1);
2802 break;
2803 case 2: /* accepted */
2804 write_http_status_line(conn, 200, msg);
2805 break;
2807 goto done;
2810 if (options->HSAuthoritativeDir &&
2811 !strcmpstart(url,"/tor/rendezvous/publish")) {
2812 /* rendezvous descriptor post */
2813 log_info(LD_REND, "Handling rendezvous descriptor post.");
2814 if (rend_cache_store(body, body_len, 1) < 0) {
2815 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
2816 "Rejected rend descriptor (length %d) from %s.",
2817 (int)body_len, conn->_base.address);
2818 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
2819 } else {
2820 write_http_status_line(conn, 200, "Service descriptor stored");
2822 goto done;
2825 if (authdir_mode_v3(options) &&
2826 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
2827 const char *msg = "OK";
2828 int status;
2829 if (dirvote_add_vote(body, &msg, &status)) {
2830 write_http_status_line(conn, status, "Vote stored");
2831 } else {
2832 tor_assert(msg);
2833 write_http_status_line(conn, status, msg);
2835 goto done;
2838 if (authdir_mode_v3(options) &&
2839 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
2840 const char *msg = NULL;
2841 if (dirvote_add_signatures(body, conn->_base.address, &msg)>=0) {
2842 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
2843 } else {
2844 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
2845 conn->_base.address, msg?msg:"???");
2846 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
2848 goto done;
2851 /* we didn't recognize the url */
2852 write_http_status_line(conn, 404, "Not found");
2854 done:
2855 tor_free(url);
2856 return 0;
2859 /** Called when a dirserver receives data on a directory connection;
2860 * looks for an HTTP request. If the request is complete, remove it
2861 * from the inbuf, try to process it; otherwise, leave it on the
2862 * buffer. Return a 0 on success, or -1 on error.
2864 static int
2865 directory_handle_command(dir_connection_t *conn)
2867 char *headers=NULL, *body=NULL;
2868 size_t body_len=0;
2869 int r;
2871 tor_assert(conn);
2872 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2874 switch (fetch_from_buf_http(conn->_base.inbuf,
2875 &headers, MAX_HEADERS_SIZE,
2876 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
2877 case -1: /* overflow */
2878 log_warn(LD_DIRSERV,
2879 "Invalid input from address '%s'. Closing.",
2880 conn->_base.address);
2881 return -1;
2882 case 0:
2883 log_debug(LD_DIRSERV,"command not all here yet.");
2884 return 0;
2885 /* case 1, fall through */
2888 http_set_address_origin(headers, TO_CONN(conn));
2889 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
2891 if (!strncasecmp(headers,"GET",3))
2892 r = directory_handle_command_get(conn, headers, body, body_len);
2893 else if (!strncasecmp(headers,"POST",4))
2894 r = directory_handle_command_post(conn, headers, body, body_len);
2895 else {
2896 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
2897 "Got headers %s with unknown command. Closing.",
2898 escaped(headers));
2899 r = -1;
2902 tor_free(headers); tor_free(body);
2903 return r;
2906 /** Write handler for directory connections; called when all data has
2907 * been flushed. Close the connection or wait for a response as
2908 * appropriate.
2911 connection_dir_finished_flushing(dir_connection_t *conn)
2913 tor_assert(conn);
2914 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2916 switch (conn->_base.state) {
2917 case DIR_CONN_STATE_CLIENT_SENDING:
2918 log_debug(LD_DIR,"client finished sending command.");
2919 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
2920 connection_stop_writing(TO_CONN(conn));
2921 return 0;
2922 case DIR_CONN_STATE_SERVER_WRITING:
2923 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
2924 connection_mark_for_close(TO_CONN(conn));
2925 return 0;
2926 default:
2927 log_warn(LD_BUG,"called in unexpected state %d.",
2928 conn->_base.state);
2929 tor_fragile_assert();
2930 return -1;
2932 return 0;
2935 /** Connected handler for directory connections: begin sending data to the
2936 * server */
2938 connection_dir_finished_connecting(dir_connection_t *conn)
2940 tor_assert(conn);
2941 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2942 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
2944 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
2945 conn->_base.address,conn->_base.port);
2947 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
2948 return 0;
2951 /** Called when one or more networkstatus fetches have failed (with uppercase
2952 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
2953 * failed once, unless they failed with status code 503. */
2954 static void
2955 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
2957 if (status_code == 503)
2958 return;
2959 SMARTLIST_FOREACH(failed, const char *, fp,
2961 char digest[DIGEST_LEN];
2962 trusted_dir_server_t *dir;
2963 if (base16_decode(digest, DIGEST_LEN, fp, strlen(fp))<0) {
2964 log_warn(LD_BUG, "Called with bad fingerprint in list: %s",
2965 escaped(fp));
2966 continue;
2968 dir = router_get_trusteddirserver_by_digest(digest);
2970 if (dir)
2971 download_status_failed(&dir->v2_ns_dl_status, status_code);
2975 static const int server_dl_schedule[] = {
2976 0, 0, 0, 60, 60, 60*2, 60*5, 60*15, INT_MAX
2978 static const int client_dl_schedule[] = {
2979 0, 0, 60, 60*5, 60*10, INT_MAX
2981 static const int server_consensus_dl_schedule[] = {
2982 0, 0, 60, 60*5, 60*10, 60*30, 60*30, 60*30, 60*30, 60*30, 60*60, 60*60*2
2984 static const int client_consensus_dl_schedule[] = {
2985 0, 0, 60, 60*5, 60*10, 60*30, 60*60, 60*60, 60*60, 60*60*3, 60*60*6, 60*60*12
2988 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
2989 * <b>status_code</b>. Increment the failure count (if the code indicates a
2990 * real failure) and set <b>dls<b>->next_attempt_at to an appropriate time in
2991 * the future. */
2992 time_t
2993 download_status_increment_failure(download_status_t *dls, int status_code,
2994 const char *item, int server, time_t now)
2996 const int *schedule;
2997 int schedule_len;
2998 int increment;
2999 tor_assert(dls);
3000 if (status_code != 503 || server)
3001 ++dls->n_download_failures;
3003 switch (dls->schedule) {
3004 case DL_SCHED_GENERIC:
3005 if (server) {
3006 schedule = server_dl_schedule;
3007 schedule_len = sizeof(server_dl_schedule)/sizeof(int);
3008 } else {
3009 schedule = client_dl_schedule;
3010 schedule_len = sizeof(client_dl_schedule)/sizeof(int);
3012 break;
3013 case DL_SCHED_CONSENSUS:
3014 if (server) {
3015 schedule = server_consensus_dl_schedule;
3016 schedule_len = sizeof(server_consensus_dl_schedule)/sizeof(int);
3017 } else {
3018 schedule = client_consensus_dl_schedule;
3019 schedule_len = sizeof(client_consensus_dl_schedule)/sizeof(int);
3021 break;
3022 default:
3023 tor_assert(0);
3026 if (dls->n_download_failures < schedule_len)
3027 increment = schedule[dls->n_download_failures];
3028 else
3029 increment = schedule[schedule_len-1];
3031 if (increment < INT_MAX)
3032 dls->next_attempt_at = now+increment;
3033 else
3034 dls->next_attempt_at = TIME_MAX;
3036 if (item) {
3037 if (dls->next_attempt_at == 0)
3038 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
3039 item, (int)dls->n_download_failures);
3040 else if (dls->next_attempt_at < TIME_MAX)
3041 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
3042 item, (int)dls->n_download_failures,
3043 (int)(dls->next_attempt_at-now));
3044 else
3045 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
3046 item, (int)dls->n_download_failures);
3048 return dls->next_attempt_at;
3051 /** Reset <b>dls</b> so that it will be considered downloadable
3052 * immediately. */
3053 void
3054 download_status_reset(download_status_t *dls)
3056 dls->n_download_failures = 0;
3057 dls->next_attempt_at = 0;
3060 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
3061 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
3062 * either as descriptor digests or as identity digests based on
3063 * <b>was_descriptor_digests</b>).
3065 static void
3066 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
3067 int router_purpose,
3068 int was_extrainfo, int was_descriptor_digests)
3070 char digest[DIGEST_LEN];
3071 time_t now = time(NULL);
3072 int server = directory_fetches_from_authorities(get_options());
3073 if (!was_descriptor_digests) {
3074 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
3075 tor_assert(!was_extrainfo); /* not supported yet */
3076 SMARTLIST_FOREACH(failed, const char *, cp,
3078 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
3079 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
3080 escaped(cp));
3081 continue;
3083 retry_bridge_descriptor_fetch_directly(digest);
3086 return; /* FFFF should implement for other-than-router-purpose someday */
3088 SMARTLIST_FOREACH(failed, const char *, cp,
3090 download_status_t *dls = NULL;
3091 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) {
3092 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
3093 continue;
3095 if (was_extrainfo) {
3096 signed_descriptor_t *sd =
3097 router_get_by_extrainfo_digest(digest);
3098 if (sd)
3099 dls = &sd->ei_dl_status;
3100 } else {
3101 dls = router_get_dl_status_by_descriptor_digest(digest);
3103 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
3104 continue;
3105 download_status_increment_failure(dls, status_code, cp, server, now);
3108 /* No need to relaunch descriptor downloads here: we already do it
3109 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3112 /** Given a directory <b>resource</b> request, containing zero
3113 * or more strings separated by plus signs, followed optionally by ".z", store
3114 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3115 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
3116 * decode_hex is true, then delete all elements that aren't hex digests, and
3117 * decode the rest. If sort_uniq is true, then sort the list and remove
3118 * all duplicates.
3121 dir_split_resource_into_fingerprints(const char *resource,
3122 smartlist_t *fp_out, int *compressed_out,
3123 int decode_hex, int sort_uniq)
3125 smartlist_t *fp_tmp = smartlist_create();
3126 tor_assert(fp_out);
3127 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
3128 if (compressed_out)
3129 *compressed_out = 0;
3130 if (smartlist_len(fp_tmp)) {
3131 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3132 size_t last_len = strlen(last);
3133 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3134 last[last_len-2] = '\0';
3135 if (compressed_out)
3136 *compressed_out = 1;
3139 if (decode_hex) {
3140 int i;
3141 char *cp, *d = NULL;
3142 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3143 cp = smartlist_get(fp_tmp, i);
3144 if (strlen(cp) != HEX_DIGEST_LEN) {
3145 log_info(LD_DIR,
3146 "Skipping digest %s with non-standard length.", escaped(cp));
3147 smartlist_del_keeporder(fp_tmp, i--);
3148 goto again;
3150 d = tor_malloc_zero(DIGEST_LEN);
3151 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
3152 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3153 smartlist_del_keeporder(fp_tmp, i--);
3154 goto again;
3156 smartlist_set(fp_tmp, i, d);
3157 d = NULL;
3158 again:
3159 tor_free(cp);
3160 tor_free(d);
3163 if (sort_uniq) {
3164 smartlist_t *fp_tmp2 = smartlist_create();
3165 int i;
3166 if (decode_hex)
3167 smartlist_sort_digests(fp_tmp);
3168 else
3169 smartlist_sort_strings(fp_tmp);
3170 if (smartlist_len(fp_tmp))
3171 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
3172 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
3173 char *cp = smartlist_get(fp_tmp, i);
3174 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
3176 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
3177 || (!decode_hex && strcasecmp(cp, last)))
3178 smartlist_add(fp_tmp2, cp);
3179 else
3180 tor_free(cp);
3182 smartlist_free(fp_tmp);
3183 fp_tmp = fp_tmp2;
3185 smartlist_add_all(fp_out, fp_tmp);
3186 smartlist_free(fp_tmp);
3187 return 0;
3190 /** Determine the responsible hidden service directories for the
3191 * rend_encoded_v2_service_descriptor_t's in <b>descs</b> and upload them;
3192 * <b>service_id</b> and <b>seconds_valid</b> are only passed for logging
3193 * purposes. */
3194 void
3195 directory_post_to_hs_dir(smartlist_t *descs, const char *service_id,
3196 int seconds_valid)
3198 int i, j;
3199 smartlist_t *responsible_dirs;
3200 routerstatus_t *hs_dir;
3201 responsible_dirs = smartlist_create();
3202 for (i = 0; i < smartlist_len(descs); i++) {
3203 rend_encoded_v2_service_descriptor_t *desc = smartlist_get(descs, i);
3204 /* Determine responsible dirs. */
3205 if (hid_serv_get_responsible_directories(responsible_dirs,
3206 desc->desc_id) < 0) {
3207 log_warn(LD_REND, "Could not determine the responsible hidden service "
3208 "directories to post descriptors to.");
3209 smartlist_free(responsible_dirs);
3210 return;
3212 tor_assert(smartlist_len(responsible_dirs) ==
3213 REND_NUMBER_OF_CONSECUTIVE_REPLICAS);
3214 for (j = 0; j < REND_NUMBER_OF_CONSECUTIVE_REPLICAS; j++) {
3215 char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
3216 hs_dir = smartlist_get(responsible_dirs, j);
3217 /* Send publish request. */
3218 directory_initiate_command_routerstatus(hs_dir,
3219 DIR_PURPOSE_UPLOAD_RENDDESC_V2,
3220 ROUTER_PURPOSE_GENERAL,
3221 1, NULL, desc->desc_str,
3222 strlen(desc->desc_str), 0);
3223 base32_encode(desc_id_base32, sizeof(desc_id_base32),
3224 desc->desc_id, DIGEST_LEN);
3225 log_info(LD_REND, "Sending publish request for v2 descriptor for "
3226 "service '%s' with descriptor ID '%s' with validity "
3227 "of %d seconds to hidden service directory '%s' on "
3228 "port %d.",
3229 service_id,
3230 desc_id_base32,
3231 seconds_valid,
3232 hs_dir->nickname,
3233 hs_dir->dir_port);
3235 smartlist_clear(responsible_dirs);
3237 smartlist_free(responsible_dirs);
3240 /** The period for which a hidden service directory cannot be queried for
3241 * the same descriptor ID again. */
3242 #define REND_HID_SERV_DIR_REQUERY_PERIOD (15 * 60)
3244 /** Contains the last request times to hidden service directories for
3245 * certain queries; keys are strings consisting of base32-encoded
3246 * hidden service directory identities and base32-encoded descriptor IDs;
3247 * values are pointers to timestamps of the last requests. */
3248 static strmap_t *last_hid_serv_requests = NULL;
3250 /** Look up the last request time to hidden service directory <b>hs_dir</b>
3251 * for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero,
3252 * assign the current time <b>now</b> and return that. Otherwise, return
3253 * the most recent request time, or 0 if no such request has been sent
3254 * before. */
3255 static time_t
3256 lookup_last_hid_serv_request(routerstatus_t *hs_dir,
3257 const char *desc_id_base32, time_t now, int set)
3259 char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
3260 char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 1];
3261 time_t *last_request_ptr;
3262 if (!last_hid_serv_requests) last_hid_serv_requests = strmap_new();
3263 base32_encode(hsdir_id_base32, sizeof(hsdir_id_base32),
3264 hs_dir->identity_digest, DIGEST_LEN);
3265 tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s",
3266 hsdir_id_base32, desc_id_base32);
3267 if (set) {
3268 last_request_ptr = tor_malloc_zero(sizeof(time_t *));
3269 *last_request_ptr = now;
3270 strmap_set(last_hid_serv_requests, hsdir_desc_comb_id, last_request_ptr);
3271 } else
3272 last_request_ptr = strmap_get_lc(last_hid_serv_requests,
3273 hsdir_desc_comb_id);
3274 return (last_request_ptr) ? *last_request_ptr : 0;
3277 /** Clean the history of request times to hidden service directories, so that
3278 * it does not contain requests older than REND_HID_SERV_DIR_REQUERY_PERIOD
3279 * seconds any more. */
3280 static void
3281 directory_clean_last_hid_serv_requests(void)
3283 strmap_iter_t *iter;
3284 time_t cutoff = time(NULL) - REND_HID_SERV_DIR_REQUERY_PERIOD;
3285 for (iter = strmap_iter_init(last_hid_serv_requests);
3286 !strmap_iter_done(iter); ) {
3287 const char *key;
3288 void *val;
3289 time_t *ent;
3290 strmap_iter_get(iter, &key, &val);
3291 ent = (time_t *) val;
3292 if (*ent < cutoff) {
3293 iter = strmap_iter_next_rmv(last_hid_serv_requests, iter);
3294 tor_free(ent);
3295 } else {
3296 iter = strmap_iter_next(last_hid_serv_requests, iter);
3301 /** Determine the responsible hidden service directories for <b>desc_id</b>
3302 * and fetch the descriptor belonging to that ID from one of them. Only
3303 * send a request to hidden service directories that we did not try within
3304 * the last REND_HID_SERV_DIR_REQUERY_PERIOD seconds; on success, return 1,
3305 * in the case that no hidden service directory is left to ask for the
3306 * descriptor, return 0, and in case of a failure -1. <b>query</b> is only
3307 * passed for pretty log statements. */
3309 directory_get_from_hs_dir(const char *desc_id, const char *query)
3311 smartlist_t *responsible_dirs = smartlist_create();
3312 smartlist_t *selectible_dirs = smartlist_create();
3313 routerstatus_t *hs_dir;
3314 char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
3315 time_t now = time(NULL);
3316 tor_assert(desc_id);
3317 tor_assert(query);
3318 tor_assert(strlen(query) == REND_SERVICE_ID_LEN_BASE32);
3319 /* Determine responsible dirs. */
3320 if (hid_serv_get_responsible_directories(responsible_dirs, desc_id) < 0) {
3321 /* XXX020 make this louder once we have some v2hidservs */
3322 log_info(LD_REND, "Could not determine the responsible hidden service "
3323 "directories to fetch descriptors.");
3324 smartlist_free(responsible_dirs);
3325 return -1;
3328 base32_encode(desc_id_base32, sizeof(desc_id_base32),
3329 desc_id, DIGEST_LEN);
3331 /* Only select those hidden service directories to which we did not send
3332 * a request earlier. */
3333 if (last_hid_serv_requests) {
3334 /* Clean up request history first. */
3335 directory_clean_last_hid_serv_requests();
3337 SMARTLIST_FOREACH(responsible_dirs, routerstatus_t *, dir, {
3338 time_t last_request =
3339 lookup_last_hid_serv_request(dir, desc_id_base32, 0, 0);
3340 if (!last_request ||
3341 last_request + REND_HID_SERV_DIR_REQUERY_PERIOD < now)
3342 smartlist_add(selectible_dirs, dir);
3344 } else {
3345 smartlist_add_all(selectible_dirs, responsible_dirs);
3347 smartlist_free(responsible_dirs);
3349 if (smartlist_len(selectible_dirs) == 0) {
3350 log_info(LD_REND, "Could not pick one of the responsible hidden "
3351 "service directories, because we requested them all "
3352 "recently without success.");
3353 return 0;
3355 hs_dir = smartlist_choose(selectible_dirs);
3356 smartlist_free(selectible_dirs);
3357 if (!hs_dir) {
3358 log_warn(LD_BUG, "Could not pick one of the responsible hidden service "
3359 "directories to fetch descriptors.");
3360 return -1;
3363 /* Remember, that we are requesting a descriptor from this hidden service
3364 * directory now. */
3365 lookup_last_hid_serv_request(hs_dir, desc_id_base32, now, 1);
3367 /* Send fetch request. (Pass query as payload to write it to the directory
3368 * connection so that it can be referred to when the response arrives.) */
3369 directory_initiate_command_routerstatus(hs_dir,
3370 DIR_PURPOSE_FETCH_RENDDESC_V2,
3371 ROUTER_PURPOSE_GENERAL,
3372 1, desc_id_base32, query, 0, 0);
3373 log_info(LD_REND, "Sending fetch request for v2 descriptor for "
3374 "service '%s' with descriptor ID '%s' to hidden "
3375 "service directory '%s' on port %d.",
3376 query, desc_id_base32, hs_dir->nickname, hs_dir->dir_port);
3377 return 1;