log more verbosely when we accept or decline a router descriptor,
[tor/rransom.git] / src / or / directory.c
blob8117dc5f0e37efd89c50ff430e9bf485b6849484
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2008, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "or.h"
7 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
8 #ifndef OPENBSD
9 #include <malloc.h>
10 #endif
11 #endif
13 /**
14 * \file directory.c
15 * \brief Code to send and fetch directories and router
16 * descriptors via HTTP. Directories use dirserv.c to generate the
17 * results; clients use routers.c to parse them.
18 **/
20 /* In-points to directory.c:
22 * - directory_post_to_dirservers(), called from
23 * router_upload_dir_desc_to_dirservers() in router.c
24 * upload_service_descriptor() in rendservice.c
25 * - directory_get_from_dirserver(), called from
26 * rend_client_refetch_renddesc() in rendclient.c
27 * run_scheduled_events() in main.c
28 * do_hup() in main.c
29 * - connection_dir_process_inbuf(), called from
30 * connection_process_inbuf() in connection.c
31 * - connection_dir_finished_flushing(), called from
32 * connection_finished_flushing() in connection.c
33 * - connection_dir_finished_connecting(), called from
34 * connection_finished_connecting() in connection.c
36 static void directory_send_command(dir_connection_t *conn,
37 int purpose, int direct, const char *resource,
38 const char *payload, size_t payload_len,
39 int supports_conditional_consensus,
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_client_request(int purpose, int compressed, size_t bytes);
60 static int client_likes_consensus(networkstatus_t *v, const char *want_url);
62 static void directory_initiate_command_rend(const char *address,
63 const tor_addr_t *addr,
64 uint16_t or_port,
65 uint16_t dir_port,
66 int supports_conditional_consensus,
67 int supports_begindir,
68 const char *digest,
69 uint8_t dir_purpose,
70 uint8_t router_purpose,
71 int anonymized_connection,
72 const char *resource,
73 const char *payload,
74 size_t payload_len,
75 time_t if_modified_since,
76 const rend_data_t *rend_query);
78 /********* START VARIABLES **********/
80 /** How far in the future do we allow a directory server to tell us it is
81 * before deciding that one of us has the wrong time? */
82 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
84 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
86 /** HTTP cache control: how long do we tell proxies they can cache each
87 * kind of document we serve? */
88 #define FULL_DIR_CACHE_LIFETIME (60*60)
89 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
90 #define DIRPORTFRONTPAGE_CACHE_LIFETIME (20*60)
91 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
92 #define ROUTERDESC_CACHE_LIFETIME (30*60)
93 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
94 #define ROBOTS_CACHE_LIFETIME (24*60*60)
96 /********* END VARIABLES ************/
98 /** Return true iff the directory purpose 'purpose' must use an
99 * anonymous connection to a directory. */
100 static int
101 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
103 if (get_options()->AllDirActionsPrivate)
104 return 1;
105 if (router_purpose == ROUTER_PURPOSE_BRIDGE && has_completed_circuit)
106 return 1; /* if no circuits yet, we may need this info to bootstrap. */
107 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
108 dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
109 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
110 dir_purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS ||
111 dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
112 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
113 dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
114 dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
115 dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
116 dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
117 return 0;
118 return 1;
121 /** Return a newly allocated string describing <b>auth</b>. */
122 char *
123 authority_type_to_string(authority_type_t auth)
125 char *result;
126 smartlist_t *lst = smartlist_create();
127 if (auth & V1_AUTHORITY)
128 smartlist_add(lst, (void*)"V1");
129 if (auth & V2_AUTHORITY)
130 smartlist_add(lst, (void*)"V2");
131 if (auth & BRIDGE_AUTHORITY)
132 smartlist_add(lst, (void*)"Bridge");
133 if (auth & HIDSERV_AUTHORITY)
134 smartlist_add(lst, (void*)"Hidden service");
135 if (smartlist_len(lst)) {
136 result = smartlist_join_strings(lst, ", ", 0, NULL);
137 } else {
138 result = tor_strdup("[Not an authority]");
140 smartlist_free(lst);
141 return result;
144 /** Return a string describing a given directory connection purpose. */
145 static const char *
146 dir_conn_purpose_to_string(int purpose)
148 switch (purpose)
150 case DIR_PURPOSE_FETCH_RENDDESC:
151 return "hidden-service descriptor fetch";
152 case DIR_PURPOSE_UPLOAD_DIR:
153 return "server descriptor upload";
154 case DIR_PURPOSE_UPLOAD_RENDDESC:
155 return "hidden-service descriptor upload";
156 case DIR_PURPOSE_UPLOAD_VOTE:
157 return "server vote upload";
158 case DIR_PURPOSE_UPLOAD_SIGNATURES:
159 return "consensus signature upload";
160 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
161 return "network-status fetch";
162 case DIR_PURPOSE_FETCH_SERVERDESC:
163 return "server descriptor fetch";
164 case DIR_PURPOSE_FETCH_EXTRAINFO:
165 return "extra-info fetch";
166 case DIR_PURPOSE_FETCH_CONSENSUS:
167 return "consensus network-status fetch";
168 case DIR_PURPOSE_FETCH_CERTIFICATE:
169 return "authority cert fetch";
170 case DIR_PURPOSE_FETCH_STATUS_VOTE:
171 return "status vote fetch";
172 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
173 return "consensus signature fetch";
174 case DIR_PURPOSE_FETCH_RENDDESC_V2:
175 return "hidden-service v2 descriptor fetch";
176 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
177 return "hidden-service v2 descriptor upload";
180 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
181 return "(unknown)";
184 /** Return true iff <b>identity_digest</b> is the digest of a router we
185 * believe to support extrainfo downloads. (If <b>is_authority</b> we do
186 * additional checking that's only valid for authorities.) */
188 router_supports_extrainfo(const char *identity_digest, int is_authority)
190 routerinfo_t *ri = router_get_by_digest(identity_digest);
192 if (ri) {
193 if (ri->caches_extra_info)
194 return 1;
195 if (is_authority && ri->platform &&
196 tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
197 return 1;
199 if (is_authority) {
200 routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
201 if (rs && rs->version_supports_extrainfo_upload)
202 return 1;
204 return 0;
207 /** Return true iff any trusted directory authority has accepted our
208 * server descriptor.
210 * We consider any authority sufficient because waiting for all of
211 * them means it never happens while any authority is down; we don't
212 * go for something more complex in the middle (like \>1/3 or \>1/2 or
213 * \>=1/2) because that doesn't seem necessary yet.
216 directories_have_accepted_server_descriptor(void)
218 smartlist_t *servers = router_get_trusted_dir_servers();
219 or_options_t *options = get_options();
220 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
221 if ((d->type & options->_PublishServerDescriptor) &&
222 d->has_accepted_serverdesc) {
223 return 1;
226 return 0;
229 /** Start a connection to every suitable directory authority, using
230 * connection purpose 'purpose' and uploading the payload 'payload'
231 * (length 'payload_len'). The purpose should be one of
232 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
234 * <b>type</b> specifies what sort of dir authorities (V1, V2,
235 * HIDSERV, BRIDGE) we should upload to.
237 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
238 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
239 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
240 * to all authorities, and the extra-info document to all authorities that
241 * support it.
243 void
244 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
245 authority_type_t type,
246 const char *payload,
247 size_t payload_len, size_t extrainfo_len)
249 int post_via_tor;
250 smartlist_t *dirservers = router_get_trusted_dir_servers();
251 int found = 0;
252 tor_assert(dirservers);
253 /* This tries dirservers which we believe to be down, but ultimately, that's
254 * harmless, and we may as well err on the side of getting things uploaded.
256 SMARTLIST_FOREACH_BEGIN(dirservers, trusted_dir_server_t *, ds) {
257 routerstatus_t *rs = &(ds->fake_status);
258 size_t upload_len = payload_len;
259 tor_addr_t ds_addr;
261 if ((type & ds->type) == 0)
262 continue;
264 found = 1; /* at least one authority of this type was listed */
265 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
266 ds->has_accepted_serverdesc = 0;
268 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
269 upload_len += extrainfo_len;
270 log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
271 (int) extrainfo_len);
273 tor_addr_from_ipv4h(&ds_addr, ds->addr);
274 post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) ||
275 !fascist_firewall_allows_address_dir(&ds_addr, ds->dir_port);
276 directory_initiate_command_routerstatus(rs, dir_purpose,
277 router_purpose,
278 post_via_tor,
279 NULL, payload, upload_len, 0);
280 } SMARTLIST_FOREACH_END(ds);
281 if (!found) {
282 char *s = authority_type_to_string(type);
283 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
284 "of type '%s', but no authorities of that type listed!", s);
285 tor_free(s);
289 /** Start a connection to a random running directory server, using
290 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
291 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
292 * Use <b>pds_flags</b> as arguments to router_pick_directory_server()
293 * or router_pick_trusteddirserver().
295 void
296 directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
297 const char *resource, int pds_flags)
299 routerstatus_t *rs = NULL;
300 or_options_t *options = get_options();
301 int prefer_authority = directory_fetches_from_authorities(options);
302 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
303 authority_type_t type;
304 time_t if_modified_since = 0;
306 /* FFFF we could break this switch into its own function, and call
307 * it elsewhere in directory.c. -RD */
308 switch (dir_purpose) {
309 case DIR_PURPOSE_FETCH_EXTRAINFO:
310 type = EXTRAINFO_CACHE |
311 (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
312 V2_AUTHORITY);
313 break;
314 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
315 case DIR_PURPOSE_FETCH_SERVERDESC:
316 type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
317 V2_AUTHORITY);
318 break;
319 case DIR_PURPOSE_FETCH_RENDDESC:
320 type = HIDSERV_AUTHORITY;
321 break;
322 case DIR_PURPOSE_FETCH_STATUS_VOTE:
323 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
324 type = V3_AUTHORITY;
325 break;
326 case DIR_PURPOSE_FETCH_CONSENSUS:
327 case DIR_PURPOSE_FETCH_CERTIFICATE:
328 type = V3_AUTHORITY;
329 break;
330 default:
331 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
332 return;
335 if (DIR_PURPOSE_FETCH_CONSENSUS) {
336 networkstatus_t *v = networkstatus_get_latest_consensus();
337 if (v)
338 if_modified_since = v->valid_after + 180;
341 if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
342 return;
344 if (!get_via_tor) {
345 if (options->UseBridges && type != BRIDGE_AUTHORITY) {
346 /* want to ask a running bridge for which we have a descriptor. */
347 /* XXX022 we assume that all of our bridges can answer any
348 * possible directory question. This won't be true forever. -RD */
349 /* It certainly is not true with conditional consensus downloading,
350 * so, for now, never assume the server supports that. */
351 routerinfo_t *ri = choose_random_entry(NULL);
352 if (ri) {
353 tor_addr_t addr;
354 tor_addr_from_ipv4h(&addr, ri->addr);
355 directory_initiate_command(ri->address, &addr,
356 ri->or_port, 0,
357 0, /* don't use conditional consensus url */
358 1, ri->cache_info.identity_digest,
359 dir_purpose,
360 router_purpose,
361 0, resource, NULL, 0, if_modified_since);
362 } else
363 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
364 "nodes are available yet.");
365 return;
366 } else {
367 if (prefer_authority || type == BRIDGE_AUTHORITY) {
368 /* only ask authdirservers, and don't ask myself */
369 rs = router_pick_trusteddirserver(type, pds_flags);
370 if (rs == NULL && (pds_flags & PDS_NO_EXISTING_SERVERDESC_FETCH)) {
371 /* We don't want to fetch from any authorities that we're currently
372 * fetching server descriptors from, and we got no match. Did we
373 * get no match because all the authorities have connections
374 * fetching server descriptors (in which case we should just
375 * return,) or because all the authorities are down or on fire or
376 * unreachable or something (in which case we should go on with
377 * our fallback code)? */
378 pds_flags &= ~PDS_NO_EXISTING_SERVERDESC_FETCH;
379 rs = router_pick_trusteddirserver(type, pds_flags);
380 if (rs) {
381 log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
382 "are in use.");
383 return;
387 if (!rs && type != BRIDGE_AUTHORITY) {
388 /* anybody with a non-zero dirport will do */
389 rs = router_pick_directory_server(type, pds_flags);
390 if (!rs) {
391 log_info(LD_DIR, "No router found for %s; falling back to "
392 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
393 rs = router_pick_trusteddirserver(type, pds_flags);
394 if (!rs)
395 get_via_tor = 1; /* last resort: try routing it via Tor */
399 } else { /* get_via_tor */
400 /* Never use fascistfirewall; we're going via Tor. */
401 if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
402 /* only ask hidserv authorities, any of them will do */
403 pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
404 rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, pds_flags);
405 } else {
406 /* anybody with a non-zero dirport will do. Disregard firewalls. */
407 pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
408 rs = router_pick_directory_server(type, pds_flags);
409 /* If we have any hope of building an indirect conn, we know some router
410 * descriptors. If (rs==NULL), we can't build circuits anyway, so
411 * there's no point in falling back to the authorities in this case. */
415 if (rs)
416 directory_initiate_command_routerstatus(rs, dir_purpose,
417 router_purpose,
418 get_via_tor,
419 resource, NULL, 0,
420 if_modified_since);
421 else {
422 log_notice(LD_DIR,
423 "While fetching directory info, "
424 "no running dirservers known. Will try again later. "
425 "(purpose %d)", dir_purpose);
426 if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
427 /* remember we tried them all and failed. */
428 directory_all_unreachable(time(NULL));
433 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
434 * directory authority other than ourself. Only for use by authorities when
435 * searching for missing information while voting. */
436 void
437 directory_get_from_all_authorities(uint8_t dir_purpose,
438 uint8_t router_purpose,
439 const char *resource)
441 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
442 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
444 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
445 trusted_dir_server_t *, ds,
447 routerstatus_t *rs;
448 if (router_digest_is_me(ds->digest))
449 continue;
450 if (!(ds->type & V3_AUTHORITY))
451 continue;
452 rs = &ds->fake_status;
453 directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
454 0, resource, NULL, 0, 0);
458 /** Same as directory_initiate_command_routerstatus(), but accepts
459 * rendezvous data to fetch a hidden service descriptor. */
460 void
461 directory_initiate_command_routerstatus_rend(routerstatus_t *status,
462 uint8_t dir_purpose,
463 uint8_t router_purpose,
464 int anonymized_connection,
465 const char *resource,
466 const char *payload,
467 size_t payload_len,
468 time_t if_modified_since,
469 const rend_data_t *rend_query)
471 routerinfo_t *router;
472 char address_buf[INET_NTOA_BUF_LEN+1];
473 struct in_addr in;
474 const char *address;
475 tor_addr_t addr;
476 router = router_get_by_digest(status->identity_digest);
477 if (!router && anonymized_connection) {
478 log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
479 "don't have its router descriptor.", status->nickname);
480 return;
481 } else if (router) {
482 address = router->address;
483 } else {
484 in.s_addr = htonl(status->addr);
485 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
486 address = address_buf;
488 tor_addr_from_ipv4h(&addr, status->addr);
489 directory_initiate_command_rend(address, &addr,
490 status->or_port, status->dir_port,
491 status->version_supports_conditional_consensus,
492 status->version_supports_begindir,
493 status->identity_digest,
494 dir_purpose, router_purpose,
495 anonymized_connection, resource,
496 payload, payload_len, if_modified_since,
497 rend_query);
500 /** Launch a new connection to the directory server <b>status</b> to
501 * upload or download a server or rendezvous
502 * descriptor. <b>dir_purpose</b> determines what
503 * kind of directory connection we're launching, and must be one of
504 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC|RENDDESC_V2}. <b>router_purpose</b>
505 * specifies the descriptor purposes we have in mind (currently only
506 * used for FETCH_DIR).
508 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
509 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
511 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
512 * want to fetch.
514 void
515 directory_initiate_command_routerstatus(routerstatus_t *status,
516 uint8_t dir_purpose,
517 uint8_t router_purpose,
518 int anonymized_connection,
519 const char *resource,
520 const char *payload,
521 size_t payload_len,
522 time_t if_modified_since)
524 directory_initiate_command_routerstatus_rend(status, dir_purpose,
525 router_purpose,
526 anonymized_connection, resource,
527 payload, payload_len,
528 if_modified_since, NULL);
531 /** Return true iff <b>conn</b> is the client side of a directory connection
532 * we launched to ourself in order to determine the reachability of our
533 * dir_port. */
534 static int
535 directory_conn_is_self_reachability_test(dir_connection_t *conn)
537 if (conn->requested_resource &&
538 !strcmpstart(conn->requested_resource,"authority")) {
539 routerinfo_t *me = router_get_my_routerinfo();
540 if (me &&
541 router_digest_is_me(conn->identity_digest) &&
542 tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/
543 me->dir_port == conn->_base.port)
544 return 1;
546 return 0;
549 /** Called when we are unable to complete the client's request to a directory
550 * server due to a network error: Mark the router as down and try again if
551 * possible.
553 void
554 connection_dir_request_failed(dir_connection_t *conn)
556 if (directory_conn_is_self_reachability_test(conn)) {
557 routerinfo_t *me = router_get_my_routerinfo();
558 if (me)
559 control_event_server_status(LOG_WARN,
560 "REACHABILITY_FAILED DIRADDRESS=%s:%d",
561 me->address, me->dir_port);
562 return; /* this was a test fetch. don't retry. */
564 if (entry_list_can_grow(get_options()))
565 router_set_status(conn->identity_digest, 0); /* don't try him again */
566 if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
567 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
568 conn->_base.address);
569 connection_dir_download_networkstatus_failed(conn, -1);
570 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
571 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
572 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
573 conn->_base.address);
574 connection_dir_download_routerdesc_failed(conn);
575 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
576 networkstatus_consensus_download_failed(0);
577 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
578 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
579 conn->_base.address);
580 connection_dir_download_cert_failed(conn, 0);
581 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
582 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
583 conn->_base.address);
584 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
585 log_info(LD_DIR, "Giving up downloading votes from '%s'",
586 conn->_base.address);
590 /** Called when an attempt to download one or more network status
591 * documents on connection <b>conn</b> failed. Decide whether to
592 * retry the fetch now, later, or never.
594 static void
595 connection_dir_download_networkstatus_failed(dir_connection_t *conn,
596 int status_code)
598 if (!conn->requested_resource) {
599 /* We never reached directory_send_command, which means that we never
600 * opened a network connection. Either we're out of sockets, or the
601 * network is down. Either way, retrying would be pointless. */
602 return;
604 if (!strcmpstart(conn->requested_resource, "all")) {
605 /* We're a non-authoritative directory cache; try again. Ignore status
606 * code, since we don't want to keep trying forever in a tight loop
607 * if all the authorities are shutting us out. */
608 smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
609 SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
610 download_status_failed(&ds->v2_ns_dl_status, 0));
611 directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose,
612 "all.z", 0 /* don't retry_if_no_servers */);
613 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
614 /* We were trying to download by fingerprint; mark them all as having
615 * failed, and possibly retry them later.*/
616 smartlist_t *failed = smartlist_create();
617 dir_split_resource_into_fingerprints(conn->requested_resource+3,
618 failed, NULL, 0, 0);
619 if (smartlist_len(failed)) {
620 dir_networkstatus_download_failed(failed, status_code);
621 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
623 smartlist_free(failed);
627 /** Called when an attempt to download one or more router descriptors
628 * or extra-info documents on connection <b>conn</b> failed.
630 static void
631 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
633 /* No need to increment the failure count for routerdescs, since
634 * it's not their fault. */
636 /* No need to relaunch descriptor downloads here: we already do it
637 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
638 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
639 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
641 (void) conn;
644 /** Called when an attempt to fetch a certificate fails. */
645 static void
646 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
648 smartlist_t *failed;
649 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
651 if (!conn->requested_resource)
652 return;
653 failed = smartlist_create();
654 dir_split_resource_into_fingerprints(conn->requested_resource+3,
655 failed, NULL, 1, 0);
656 SMARTLIST_FOREACH(failed, char *, cp,
658 authority_cert_dl_failed(cp, status);
659 tor_free(cp);
661 smartlist_free(failed);
663 update_certificate_downloads(time(NULL));
666 /** Evaluate the situation and decide if we should use an encrypted
667 * "begindir-style" connection for this directory request.
668 * 1) If or_port is 0, or it's a direct conn and or_port is firewalled
669 * or we're a dir mirror, no.
670 * 2) If we prefer to avoid begindir conns, and we're not fetching or
671 * publishing a bridge relay descriptor, no.
672 * 3) Else yes.
674 static int
675 directory_command_should_use_begindir(or_options_t *options,
676 const tor_addr_t *addr,
677 int or_port, uint8_t router_purpose,
678 int anonymized_connection)
680 if (!or_port)
681 return 0; /* We don't know an ORPort -- no chance. */
682 if (!anonymized_connection)
683 if (!fascist_firewall_allows_address_or(addr, or_port) ||
684 directory_fetches_from_authorities(options))
685 return 0; /* We're firewalled or are acting like a relay -- also no. */
686 if (!options->TunnelDirConns &&
687 router_purpose != ROUTER_PURPOSE_BRIDGE)
688 return 0; /* We prefer to avoid using begindir conns. Fine. */
689 return 1;
692 /** Helper for directory_initiate_command_routerstatus: send the
693 * command to a server whose address is <b>address</b>, whose IP is
694 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
695 * <b>supports_begindir</b>, and whose identity key digest is
696 * <b>digest</b>. */
697 void
698 directory_initiate_command(const char *address, const tor_addr_t *_addr,
699 uint16_t or_port, uint16_t dir_port,
700 int supports_conditional_consensus,
701 int supports_begindir, const char *digest,
702 uint8_t dir_purpose, uint8_t router_purpose,
703 int anonymized_connection, const char *resource,
704 const char *payload, size_t payload_len,
705 time_t if_modified_since)
707 directory_initiate_command_rend(address, _addr, or_port, dir_port,
708 supports_conditional_consensus,
709 supports_begindir, digest, dir_purpose,
710 router_purpose, anonymized_connection,
711 resource, payload, payload_len,
712 if_modified_since, NULL);
715 /** Same as directory_initiate_command(), but accepts rendezvous data to
716 * fetch a hidden service descriptor. */
717 static void
718 directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
719 uint16_t or_port, uint16_t dir_port,
720 int supports_conditional_consensus,
721 int supports_begindir, const char *digest,
722 uint8_t dir_purpose, uint8_t router_purpose,
723 int anonymized_connection,
724 const char *resource,
725 const char *payload, size_t payload_len,
726 time_t if_modified_since,
727 const rend_data_t *rend_query)
729 dir_connection_t *conn;
730 or_options_t *options = get_options();
731 int socket_error = 0;
732 int use_begindir = supports_begindir &&
733 directory_command_should_use_begindir(options, _addr,
734 or_port, router_purpose, anonymized_connection);
735 tor_addr_t addr;
737 tor_assert(address);
738 tor_assert(_addr);
739 tor_assert(or_port || dir_port);
740 tor_assert(digest);
742 tor_addr_copy(&addr, _addr);
744 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
745 anonymized_connection, use_begindir);
747 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
749 conn = dir_connection_new(AF_INET);
751 /* set up conn so it's got all the data we need to remember */
752 tor_addr_copy(&conn->_base.addr, &addr);
753 conn->_base.port = use_begindir ? or_port : dir_port;
754 conn->_base.address = tor_strdup(address);
755 memcpy(conn->identity_digest, digest, DIGEST_LEN);
757 conn->_base.purpose = dir_purpose;
758 conn->router_purpose = router_purpose;
760 /* give it an initial state */
761 conn->_base.state = DIR_CONN_STATE_CONNECTING;
763 /* decide whether we can learn our IP address from this conn */
764 conn->dirconn_direct = !anonymized_connection;
766 /* copy rendezvous data, if any */
767 if (rend_query)
768 conn->rend_data = rend_data_dup(rend_query);
770 if (!anonymized_connection && !use_begindir) {
771 /* then we want to connect to dirport directly */
773 if (options->HttpProxy) {
774 tor_addr_from_ipv4h(&addr, options->HttpProxyAddr);
775 dir_port = options->HttpProxyPort;
778 switch (connection_connect(TO_CONN(conn), conn->_base.address, &addr,
779 dir_port, &socket_error)) {
780 case -1:
781 connection_dir_request_failed(conn); /* retry if we want */
782 /* XXX we only pass 'conn' above, not 'resource', 'payload',
783 * etc. So in many situations it can't retry! -RD */
784 connection_free(TO_CONN(conn));
785 return;
786 case 1:
787 /* start flushing conn */
788 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
789 /* fall through */
790 case 0:
791 /* queue the command on the outbuf */
792 directory_send_command(conn, dir_purpose, 1, resource,
793 payload, payload_len,
794 supports_conditional_consensus,
795 if_modified_since);
796 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
797 /* writable indicates finish, readable indicates broken link,
798 error indicates broken link in windowsland. */
800 } else { /* we want to connect via a tor connection */
801 edge_connection_t *linked_conn;
803 /* If it's an anonymized connection, remember the fact that we
804 * wanted it for later: maybe we'll want it again soon. */
805 if (anonymized_connection && use_begindir)
806 rep_hist_note_used_internal(time(NULL), 0, 1);
807 else if (anonymized_connection && !use_begindir)
808 rep_hist_note_used_port(time(NULL), conn->_base.port);
810 /* make an AP connection
811 * populate it and add it at the right state
812 * hook up both sides
814 linked_conn =
815 connection_ap_make_link(conn->_base.address, conn->_base.port,
816 digest, use_begindir, conn->dirconn_direct);
817 if (!linked_conn) {
818 log_warn(LD_NET,"Making tunnel to dirserver failed.");
819 connection_mark_for_close(TO_CONN(conn));
820 return;
822 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
824 if (connection_add(TO_CONN(conn)) < 0) {
825 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
826 connection_mark_for_close(TO_CONN(conn));
827 return;
829 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
830 /* queue the command on the outbuf */
831 directory_send_command(conn, dir_purpose, 0, resource,
832 payload, payload_len,
833 supports_conditional_consensus,
834 if_modified_since);
835 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
836 connection_start_reading(TO_CONN(linked_conn));
840 /** Return true iff anything we say on <b>conn</b> is being encrypted before
841 * we send it to the client/server. */
843 connection_dir_is_encrypted(dir_connection_t *conn)
845 /* Right now it's sufficient to see if conn is or has been linked, since
846 * the only thing it could be linked to is an edge connection on a
847 * circuit, and the only way it could have been unlinked is at the edge
848 * connection getting closed.
850 return TO_CONN(conn)->linked;
853 /** Helper for sorting
855 * sort strings alphabetically
857 static int
858 _compare_strs(const void **a, const void **b)
860 const char *s1 = *a, *s2 = *b;
861 return strcmp(s1, s2);
864 #define CONDITIONAL_CONSENSUS_FPR_LEN 3
865 #if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
866 #error "conditional consensus fingerprint length is larger than digest length"
867 #endif
869 /** Return the URL we should use for a consensus download.
871 * This url depends on whether or not the server we go to
872 * is sufficiently new to support conditional consensus downloading,
873 * i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
875 static char *
876 directory_get_consensus_url(int supports_conditional_consensus)
878 char *url;
879 int len;
881 if (supports_conditional_consensus) {
882 char *authority_id_list;
883 smartlist_t *authority_digets = smartlist_create();
885 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
886 trusted_dir_server_t *, ds,
888 char *hex;
889 if (!(ds->type & V3_AUTHORITY))
890 continue;
892 hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
893 base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
894 ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN);
895 smartlist_add(authority_digets, hex);
897 smartlist_sort(authority_digets, _compare_strs);
898 authority_id_list = smartlist_join_strings(authority_digets,
899 "+", 0, NULL);
901 len = strlen(authority_id_list)+64;
902 url = tor_malloc(len);
903 tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z",
904 authority_id_list);
906 SMARTLIST_FOREACH(authority_digets, char *, cp, tor_free(cp));
907 smartlist_free(authority_digets);
908 tor_free(authority_id_list);
909 } else {
910 url = tor_strdup("/tor/status-vote/current/consensus.z");
912 return url;
915 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
916 * are as in directory_initiate_command.
918 static void
919 directory_send_command(dir_connection_t *conn,
920 int purpose, int direct, const char *resource,
921 const char *payload, size_t payload_len,
922 int supports_conditional_consensus,
923 time_t if_modified_since)
925 char proxystring[256];
926 char proxyauthstring[256];
927 char hoststring[128];
928 char imsstring[RFC1123_TIME_LEN+32];
929 char *url;
930 char request[8192];
931 const char *httpcommand = NULL;
932 size_t len;
934 tor_assert(conn);
935 tor_assert(conn->_base.type == CONN_TYPE_DIR);
937 tor_free(conn->requested_resource);
938 if (resource)
939 conn->requested_resource = tor_strdup(resource);
941 /* come up with a string for which Host: we want */
942 if (conn->_base.port == 80) {
943 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
944 } else {
945 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
946 conn->_base.address, conn->_base.port);
949 /* Format if-modified-since */
950 if (!if_modified_since) {
951 imsstring[0] = '\0';
952 } else {
953 char b[RFC1123_TIME_LEN+1];
954 format_rfc1123_time(b, if_modified_since);
955 tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
958 /* come up with some proxy lines, if we're using one. */
959 if (direct && get_options()->HttpProxy) {
960 char *base64_authenticator=NULL;
961 const char *authenticator = get_options()->HttpProxyAuthenticator;
963 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
964 if (authenticator) {
965 base64_authenticator = alloc_http_authenticator(authenticator);
966 if (!base64_authenticator)
967 log_warn(LD_BUG, "Encoding http authenticator failed");
969 if (base64_authenticator) {
970 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
971 "\r\nProxy-Authorization: Basic %s",
972 base64_authenticator);
973 tor_free(base64_authenticator);
974 } else {
975 proxyauthstring[0] = 0;
977 } else {
978 proxystring[0] = 0;
979 proxyauthstring[0] = 0;
982 switch (purpose) {
983 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
984 tor_assert(resource);
985 httpcommand = "GET";
986 len = strlen(resource)+32;
987 url = tor_malloc(len);
988 tor_snprintf(url, len, "/tor/status/%s", resource);
989 break;
990 case DIR_PURPOSE_FETCH_CONSENSUS:
991 tor_assert(!resource);
992 tor_assert(!payload);
993 httpcommand = "GET";
994 url = directory_get_consensus_url(supports_conditional_consensus);
995 log_info(LD_DIR, "Downloading consensus from %s using %s",
996 hoststring, url);
997 break;
998 case DIR_PURPOSE_FETCH_CERTIFICATE:
999 tor_assert(resource);
1000 tor_assert(!payload);
1001 httpcommand = "GET";
1002 len = strlen(resource)+32;
1003 url = tor_malloc(len);
1004 tor_snprintf(url, len, "/tor/keys/%s", resource);
1005 break;
1006 case DIR_PURPOSE_FETCH_STATUS_VOTE:
1007 tor_assert(resource);
1008 tor_assert(!payload);
1009 httpcommand = "GET";
1010 len = strlen(resource)+32;
1011 url = tor_malloc(len);
1012 tor_snprintf(url, len, "/tor/status-vote/next/%s.z", resource);
1013 break;
1014 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
1015 tor_assert(!resource);
1016 tor_assert(!payload);
1017 httpcommand = "GET";
1018 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
1019 break;
1020 case DIR_PURPOSE_FETCH_SERVERDESC:
1021 tor_assert(resource);
1022 httpcommand = "GET";
1023 len = strlen(resource)+32;
1024 url = tor_malloc(len);
1025 tor_snprintf(url, len, "/tor/server/%s", resource);
1026 break;
1027 case DIR_PURPOSE_FETCH_EXTRAINFO:
1028 tor_assert(resource);
1029 httpcommand = "GET";
1030 len = strlen(resource)+32;
1031 url = tor_malloc(len);
1032 tor_snprintf(url, len, "/tor/extra/%s", resource);
1033 break;
1034 case DIR_PURPOSE_UPLOAD_DIR:
1035 tor_assert(!resource);
1036 tor_assert(payload);
1037 httpcommand = "POST";
1038 url = tor_strdup("/tor/");
1039 break;
1040 case DIR_PURPOSE_UPLOAD_VOTE:
1041 tor_assert(!resource);
1042 tor_assert(payload);
1043 httpcommand = "POST";
1044 url = tor_strdup("/tor/post/vote");
1045 break;
1046 case DIR_PURPOSE_UPLOAD_SIGNATURES:
1047 tor_assert(!resource);
1048 tor_assert(payload);
1049 httpcommand = "POST";
1050 url = tor_strdup("/tor/post/consensus-signature");
1051 break;
1052 case DIR_PURPOSE_FETCH_RENDDESC:
1053 tor_assert(resource);
1054 tor_assert(!payload);
1056 /* this must be true or we wouldn't be doing the lookup */
1057 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN_BASE32);
1058 /* This breaks the function abstraction. */
1059 conn->rend_data = tor_malloc_zero(sizeof(rend_data_t));
1060 strlcpy(conn->rend_data->onion_address, resource,
1061 sizeof(conn->rend_data->onion_address));
1062 conn->rend_data->rend_desc_version = 0;
1064 httpcommand = "GET";
1065 /* Request the most recent versioned descriptor. */
1066 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
1067 // but that never got testing, and it wasn't a good design.)
1068 len = strlen(resource)+32;
1069 url = tor_malloc(len);
1070 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
1071 break;
1072 case DIR_PURPOSE_FETCH_RENDDESC_V2:
1073 tor_assert(resource);
1074 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
1075 tor_assert(!payload);
1076 conn->rend_data->rend_desc_version = 2;
1077 httpcommand = "GET";
1078 len = strlen(resource) + 32;
1079 url = tor_malloc(len);
1080 tor_snprintf(url, len, "/tor/rendezvous2/%s", resource);
1081 break;
1082 case DIR_PURPOSE_UPLOAD_RENDDESC:
1083 tor_assert(!resource);
1084 tor_assert(payload);
1085 httpcommand = "POST";
1086 url = tor_strdup("/tor/rendezvous/publish");
1087 break;
1088 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
1089 tor_assert(!resource);
1090 tor_assert(payload);
1091 httpcommand = "POST";
1092 url = tor_strdup("/tor/rendezvous2/publish");
1093 break;
1094 default:
1095 tor_assert(0);
1096 return;
1099 if (strlen(proxystring) + strlen(url) >= 4096) {
1100 log_warn(LD_BUG,
1101 "Squid does not like URLs longer than 4095 bytes, and this "
1102 "one is %d bytes long: %s%s",
1103 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
1106 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
1107 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1108 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
1109 tor_free(url);
1111 if (!strcmp(httpcommand, "GET") && !payload) {
1112 tor_snprintf(request, sizeof(request),
1113 " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
1114 hoststring,
1115 imsstring,
1116 proxyauthstring);
1117 } else {
1118 tor_snprintf(request, sizeof(request),
1119 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
1120 payload ? (unsigned long)payload_len : 0,
1121 hoststring,
1122 imsstring,
1123 proxyauthstring);
1125 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1127 if (payload) {
1128 /* then send the payload afterwards too */
1129 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
1133 /** Parse an HTTP request string <b>headers</b> of the form
1134 * \verbatim
1135 * "\%s [http[s]://]\%s HTTP/1..."
1136 * \endverbatim
1137 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
1138 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
1139 * so it does. Return 0.
1140 * Otherwise, return -1.
1142 static int
1143 parse_http_url(const char *headers, char **url)
1145 char *s, *start, *tmp;
1147 s = (char *)eat_whitespace_no_nl(headers);
1148 if (!*s) return -1;
1149 s = (char *)find_whitespace(s); /* get past GET/POST */
1150 if (!*s) return -1;
1151 s = (char *)eat_whitespace_no_nl(s);
1152 if (!*s) return -1;
1153 start = s; /* this is it, assuming it's valid */
1154 s = (char *)find_whitespace(start);
1155 if (!*s) return -1;
1157 /* tolerate the http[s] proxy style of putting the hostname in the url */
1158 if (s-start >= 4 && !strcmpstart(start,"http")) {
1159 tmp = start + 4;
1160 if (*tmp == 's')
1161 tmp++;
1162 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
1163 tmp = strchr(tmp+3, '/');
1164 if (tmp && tmp < s) {
1165 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
1166 start = tmp;
1171 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
1172 *url = tor_malloc(s - start + 5);
1173 strlcpy(*url,"/tor", s-start+5);
1174 strlcat((*url)+4, start, s-start+1);
1175 } else {
1176 *url = tor_strndup(start, s-start);
1178 return 0;
1181 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1182 * <b>which</b>. The key should be given with a terminating colon and space;
1183 * this function copies everything after, up to but not including the
1184 * following \\r\\n. */
1185 static char *
1186 http_get_header(const char *headers, const char *which)
1188 const char *cp = headers;
1189 while (cp) {
1190 if (!strcasecmpstart(cp, which)) {
1191 char *eos;
1192 cp += strlen(which);
1193 if ((eos = strchr(cp,'\r')))
1194 return tor_strndup(cp, eos-cp);
1195 else
1196 return tor_strdup(cp);
1198 cp = strchr(cp, '\n');
1199 if (cp)
1200 ++cp;
1202 return NULL;
1205 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1206 * <b>conn</b>-\>address to describe our best guess of the address that
1207 * originated this HTTP request. */
1208 static void
1209 http_set_address_origin(const char *headers, connection_t *conn)
1211 char *fwd;
1213 fwd = http_get_header(headers, "Forwarded-For: ");
1214 if (!fwd)
1215 fwd = http_get_header(headers, "X-Forwarded-For: ");
1216 if (fwd) {
1217 struct in_addr in;
1218 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
1219 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
1220 escaped(fwd));
1221 tor_free(fwd);
1222 return;
1224 tor_free(conn->address);
1225 conn->address = tor_strdup(fwd);
1226 tor_free(fwd);
1230 /** Parse an HTTP response string <b>headers</b> of the form
1231 * \verbatim
1232 * "HTTP/1.\%d \%d\%s\r\n...".
1233 * \endverbatim
1235 * If it's well-formed, assign the status code to *<b>code</b> and
1236 * return 0. Otherwise, return -1.
1238 * On success: If <b>date</b> is provided, set *date to the Date
1239 * header in the http headers, or 0 if no such header is found. If
1240 * <b>compression</b> is provided, set *<b>compression</b> to the
1241 * compression method given in the Content-Encoding header, or 0 if no
1242 * such header is found, or -1 if the value of the header is not
1243 * recognized. If <b>reason</b> is provided, strdup the reason string
1244 * into it.
1247 parse_http_response(const char *headers, int *code, time_t *date,
1248 compress_method_t *compression, char **reason)
1250 unsigned n1, n2;
1251 char datestr[RFC1123_TIME_LEN+1];
1252 smartlist_t *parsed_headers;
1253 tor_assert(headers);
1254 tor_assert(code);
1256 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1258 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
1259 (n1 != 0 && n1 != 1) ||
1260 (n2 < 100 || n2 >= 600)) {
1261 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1262 return -1;
1264 *code = n2;
1266 parsed_headers = smartlist_create();
1267 smartlist_split_string(parsed_headers, headers, "\n",
1268 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1269 if (reason) {
1270 smartlist_t *status_line_elements = smartlist_create();
1271 tor_assert(smartlist_len(parsed_headers));
1272 smartlist_split_string(status_line_elements,
1273 smartlist_get(parsed_headers, 0),
1274 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1275 tor_assert(smartlist_len(status_line_elements) <= 3);
1276 if (smartlist_len(status_line_elements) == 3) {
1277 *reason = smartlist_get(status_line_elements, 2);
1278 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1280 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1281 smartlist_free(status_line_elements);
1283 if (date) {
1284 *date = 0;
1285 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1286 if (!strcmpstart(s, "Date: ")) {
1287 strlcpy(datestr, s+6, sizeof(datestr));
1288 /* This will do nothing on failure, so we don't need to check
1289 the result. We shouldn't warn, since there are many other valid
1290 date formats besides the one we use. */
1291 parse_rfc1123_time(datestr, date);
1292 break;
1295 if (compression) {
1296 const char *enc = NULL;
1297 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1298 if (!strcmpstart(s, "Content-Encoding: ")) {
1299 enc = s+18; break;
1301 if (!enc || !strcmp(enc, "identity")) {
1302 *compression = NO_METHOD;
1303 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1304 *compression = ZLIB_METHOD;
1305 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1306 *compression = GZIP_METHOD;
1307 } else {
1308 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1309 escaped(enc));
1310 *compression = UNKNOWN_METHOD;
1313 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1314 smartlist_free(parsed_headers);
1316 return 0;
1319 /** Return true iff <b>body</b> doesn't start with a plausible router or
1320 * running-list or directory opening. This is a sign of possible compression.
1322 static int
1323 body_is_plausible(const char *body, size_t len, int purpose)
1325 int i;
1326 if (len == 0)
1327 return 1; /* empty bodies don't need decompression */
1328 if (len < 32)
1329 return 0;
1330 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
1331 if (!strcmpstart(body,"router") ||
1332 !strcmpstart(body,"signed-directory") ||
1333 !strcmpstart(body,"network-status") ||
1334 !strcmpstart(body,"running-routers"))
1335 return 1;
1336 for (i=0;i<32;++i) {
1337 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1338 return 0;
1340 return 1;
1341 } else {
1342 return 1;
1346 /** Called when we've just fetched a bunch of router descriptors in
1347 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1348 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1349 * is true, or identity digests otherwise. Parse the descriptors, validate
1350 * them, and annotate them as having purpose <b>purpose</b> and as having been
1351 * downloaded from <b>source</b>.
1353 * Return the number of routers actually added. */
1354 static int
1355 load_downloaded_routers(const char *body, smartlist_t *which,
1356 int descriptor_digests,
1357 int router_purpose,
1358 const char *source)
1360 char buf[256];
1361 char time_buf[ISO_TIME_LEN+1];
1362 int added = 0;
1363 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1364 format_iso_time(time_buf, time(NULL));
1365 tor_assert(source);
1367 if (tor_snprintf(buf, sizeof(buf),
1368 "@downloaded-at %s\n"
1369 "@source %s\n"
1370 "%s%s%s", time_buf, escaped(source),
1371 !general ? "@purpose " : "",
1372 !general ? router_purpose_to_string(router_purpose) : "",
1373 !general ? "\n" : "")<0)
1374 return added;
1376 added = router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1377 descriptor_digests, buf);
1378 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
1379 count_loading_descriptors_progress());
1380 return added;
1383 /** We are a client, and we've finished reading the server's
1384 * response. Parse it and act appropriately.
1386 * If we're still happy with using this directory server in the future, return
1387 * 0. Otherwise return -1; and the caller should consider trying the request
1388 * again.
1390 * The caller will take care of marking the connection for close.
1392 static int
1393 connection_dir_client_reached_eof(dir_connection_t *conn)
1395 char *body;
1396 char *headers;
1397 char *reason = NULL;
1398 size_t body_len=0, orig_len=0;
1399 int status_code;
1400 time_t date_header=0;
1401 long delta;
1402 compress_method_t compression;
1403 int plausible;
1404 int skewed=0;
1405 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1406 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
1407 int was_compressed=0;
1408 time_t now = time(NULL);
1410 switch (fetch_from_buf_http(conn->_base.inbuf,
1411 &headers, MAX_HEADERS_SIZE,
1412 &body, &body_len, MAX_DIR_DL_SIZE,
1413 allow_partial)) {
1414 case -1: /* overflow */
1415 log_warn(LD_PROTOCOL,
1416 "'fetch' response too large (server '%s:%d'). Closing.",
1417 conn->_base.address, conn->_base.port);
1418 return -1;
1419 case 0:
1420 log_info(LD_HTTP,
1421 "'fetch' response not all here, but we're at eof. Closing.");
1422 return -1;
1423 /* case 1, fall through */
1425 orig_len = body_len;
1427 if (parse_http_response(headers, &status_code, &date_header,
1428 &compression, &reason) < 0) {
1429 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1430 conn->_base.address, conn->_base.port);
1431 tor_free(body); tor_free(headers);
1432 return -1;
1434 if (!reason) reason = tor_strdup("[no reason given]");
1436 log_debug(LD_DIR,
1437 "Received response from directory server '%s:%d': %d %s",
1438 conn->_base.address, conn->_base.port, status_code,
1439 escaped(reason));
1441 /* now check if it's got any hints for us about our IP address. */
1442 if (conn->dirconn_direct) {
1443 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1444 if (guess) {
1445 router_new_address_suggestion(guess, conn);
1446 tor_free(guess);
1450 if (date_header > 0) {
1451 /* The date header was written very soon after we sent our request,
1452 * so compute the skew as the difference between sending the request
1453 * and the date header. (We used to check now-date_header, but that's
1454 * inaccurate if we spend a lot of time downloading.)
1456 delta = conn->_base.timestamp_lastwritten - date_header;
1457 if (labs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1458 char dbuf[64];
1459 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1460 format_time_interval(dbuf, sizeof(dbuf), delta);
1461 log_fn(trusted ? LOG_WARN : LOG_INFO,
1462 LD_HTTP,
1463 "Received directory with skewed time (server '%s:%d'): "
1464 "It seems that our clock is %s by %s, or that theirs is %s. "
1465 "Tor requires an accurate clock to work: please check your time, "
1466 "timezone, and date settings.",
1467 conn->_base.address, conn->_base.port,
1468 delta>0 ? "ahead" : "behind", dbuf,
1469 delta>0 ? "behind" : "ahead");
1470 skewed = 1; /* don't check the recommended-versions line */
1471 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1472 "CLOCK_SKEW SKEW=%ld SOURCE=DIRSERV:%s:%d",
1473 delta, conn->_base.address, conn->_base.port);
1474 } else {
1475 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1476 "we are %ld seconds skewed. (That's okay.)", delta);
1479 (void) skewed; /* skewed isn't used yet. */
1481 if (status_code == 503 && body_len < 16) {
1482 routerstatus_t *rs;
1483 trusted_dir_server_t *ds;
1484 log_info(LD_DIR,"Received http status code %d (%s) from server "
1485 "'%s:%d'. I'll try again soon.",
1486 status_code, escaped(reason), conn->_base.address,
1487 conn->_base.port);
1488 if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
1489 rs->last_dir_503_at = now;
1490 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1491 ds->fake_status.last_dir_503_at = now;
1493 tor_free(body); tor_free(headers); tor_free(reason);
1494 return -1;
1495 } else if (status_code == 503) {
1496 /* XXXX022 Remove this once every server with bug 539 is obsolete. */
1497 log_info(LD_DIR, "Server at '%s:%d' sent us a 503 response, but included "
1498 "a body anyway. We'll pretend it gave us a 200.",
1499 conn->_base.address, conn->_base.port);
1500 status_code = 200;
1503 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1504 if (compression != NO_METHOD || !plausible) {
1505 char *new_body = NULL;
1506 size_t new_len = 0;
1507 compress_method_t guessed = detect_compression_method(body, body_len);
1508 if (compression == UNKNOWN_METHOD || guessed != compression) {
1509 /* Tell the user if we don't believe what we're told about compression.*/
1510 const char *description1, *description2;
1511 if (compression == ZLIB_METHOD)
1512 description1 = "as deflated";
1513 else if (compression == GZIP_METHOD)
1514 description1 = "as gzipped";
1515 else if (compression == NO_METHOD)
1516 description1 = "as uncompressed";
1517 else
1518 description1 = "with an unknown Content-Encoding";
1519 if (guessed == ZLIB_METHOD)
1520 description2 = "deflated";
1521 else if (guessed == GZIP_METHOD)
1522 description2 = "gzipped";
1523 else if (!plausible)
1524 description2 = "confusing binary junk";
1525 else
1526 description2 = "uncompressed";
1528 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1529 "but it seems to be %s.%s",
1530 conn->_base.address, conn->_base.port, description1,
1531 description2,
1532 (compression>0 && guessed>0)?" Trying both.":"");
1534 /* Try declared compression first if we can. */
1535 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1536 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1537 !allow_partial, LOG_PROTOCOL_WARN);
1538 /* Okay, if that didn't work, and we think that it was compressed
1539 * differently, try that. */
1540 if (!new_body &&
1541 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1542 compression != guessed)
1543 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1544 !allow_partial, LOG_PROTOCOL_WARN);
1545 /* If we're pretty sure that we have a compressed directory, and
1546 * we didn't manage to uncompress it, then warn and bail. */
1547 if (!plausible && !new_body) {
1548 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1549 "Unable to decompress HTTP body (server '%s:%d').",
1550 conn->_base.address, conn->_base.port);
1551 tor_free(body); tor_free(headers); tor_free(reason);
1552 return -1;
1554 if (new_body) {
1555 tor_free(body);
1556 body = new_body;
1557 body_len = new_len;
1558 was_compressed = 1;
1562 if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
1563 smartlist_t *which = NULL;
1564 v2_networkstatus_source_t source;
1565 char *cp;
1566 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1567 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1568 if (status_code != 200) {
1569 log_warn(LD_DIR,
1570 "Received http status code %d (%s) from server "
1571 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1572 status_code, escaped(reason), conn->_base.address,
1573 conn->_base.port, conn->requested_resource);
1574 tor_free(body); tor_free(headers); tor_free(reason);
1575 connection_dir_download_networkstatus_failed(conn, status_code);
1576 return -1;
1578 if (conn->requested_resource &&
1579 !strcmpstart(conn->requested_resource,"fp/")) {
1580 source = NS_FROM_DIR_BY_FP;
1581 which = smartlist_create();
1582 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1583 which, NULL, 0, 0);
1584 } else if (conn->requested_resource &&
1585 !strcmpstart(conn->requested_resource, "all")) {
1586 source = NS_FROM_DIR_ALL;
1587 which = smartlist_create();
1588 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1589 trusted_dir_server_t *, ds,
1591 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1592 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1593 smartlist_add(which, hex);
1595 } else {
1596 /* XXXX Can we even end up here? -- weasel*/
1597 source = NS_FROM_DIR_BY_FP;
1598 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1599 "for it by fp, nor did we ask for all.");
1601 cp = body;
1602 while (*cp) {
1603 char *next = strstr(cp, "\nnetwork-status-version");
1604 if (next)
1605 next[1] = '\0';
1606 /* learn from it, and then remove it from 'which' */
1607 if (router_set_networkstatus_v2(cp, now, source, which)<0)
1608 break;
1609 if (next) {
1610 next[1] = 'n';
1611 cp = next+1;
1612 } else
1613 break;
1615 /* launches router downloads as needed */
1616 routers_update_all_from_networkstatus(now, 2);
1617 directory_info_has_arrived(now, 0);
1618 if (which) {
1619 if (smartlist_len(which)) {
1620 dir_networkstatus_download_failed(which, status_code);
1622 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1623 smartlist_free(which);
1627 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1628 int r;
1629 if (status_code != 200) {
1630 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1631 log(severity, LD_DIR,
1632 "Received http status code %d (%s) from server "
1633 "'%s:%d' while fetching consensus directory.",
1634 status_code, escaped(reason), conn->_base.address,
1635 conn->_base.port);
1636 tor_free(body); tor_free(headers); tor_free(reason);
1637 networkstatus_consensus_download_failed(status_code);
1638 return -1;
1640 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1641 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1642 if ((r=networkstatus_set_current_consensus(body, 0))<0) {
1643 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1644 "Unable to load consensus directory downloaded from "
1645 "server '%s:%d'. I'll try again soon.",
1646 conn->_base.address, conn->_base.port);
1647 tor_free(body); tor_free(headers); tor_free(reason);
1648 networkstatus_consensus_download_failed(0);
1649 return -1;
1651 /* launches router downloads as needed */
1652 routers_update_all_from_networkstatus(now, 3);
1653 directory_info_has_arrived(now, 0);
1654 log_info(LD_DIR, "Successfully loaded consensus.");
1657 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1658 if (status_code != 200) {
1659 log_warn(LD_DIR,
1660 "Received http status code %d (%s) from server "
1661 "'%s:%d' while fetching \"/tor/keys/%s\".",
1662 status_code, escaped(reason), conn->_base.address,
1663 conn->_base.port, conn->requested_resource);
1664 connection_dir_download_cert_failed(conn, status_code);
1665 tor_free(body); tor_free(headers); tor_free(reason);
1666 return -1;
1668 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1669 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1670 if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) {
1671 log_warn(LD_DIR, "Unable to parse fetched certificates");
1672 connection_dir_download_cert_failed(conn, status_code);
1673 } else {
1674 directory_info_has_arrived(now, 0);
1675 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1678 if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1679 const char *msg;
1680 int st;
1681 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1682 (int) body_len, conn->_base.address, conn->_base.port);
1683 if (status_code != 200) {
1684 log_warn(LD_DIR,
1685 "Received http status code %d (%s) from server "
1686 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1687 status_code, escaped(reason), conn->_base.address,
1688 conn->_base.port, conn->requested_resource);
1689 tor_free(body); tor_free(headers); tor_free(reason);
1690 return -1;
1692 dirvote_add_vote(body, &msg, &st);
1693 if (st > 299) {
1694 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1695 } else {
1696 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1699 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1700 const char *msg = NULL;
1701 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1702 (int) body_len, conn->_base.address, conn->_base.port);
1703 if (status_code != 200) {
1704 log_warn(LD_DIR,
1705 "Received http status code %d (%s) from server "
1706 "'%s:%d' while fetching \"/tor/status-vote/consensus-signatures.z\".",
1707 status_code, escaped(reason), conn->_base.address,
1708 conn->_base.port);
1709 tor_free(body); tor_free(headers); tor_free(reason);
1710 return -1;
1712 if (dirvote_add_signatures(body, conn->_base.address, &msg)<0) {
1713 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1714 conn->_base.address, conn->_base.port, msg?msg:"???");
1718 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1719 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1720 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1721 smartlist_t *which = NULL;
1722 int n_asked_for = 0;
1723 int descriptor_digests = conn->requested_resource &&
1724 !strcmpstart(conn->requested_resource,"d/");
1725 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1726 was_ei ? "extra server info" : "server info",
1727 (int)body_len, conn->_base.address, conn->_base.port);
1728 if (conn->requested_resource &&
1729 (!strcmpstart(conn->requested_resource,"d/") ||
1730 !strcmpstart(conn->requested_resource,"fp/"))) {
1731 which = smartlist_create();
1732 dir_split_resource_into_fingerprints(conn->requested_resource +
1733 (descriptor_digests ? 2 : 3),
1734 which, NULL, 0, 0);
1735 n_asked_for = smartlist_len(which);
1737 if (status_code != 200) {
1738 int dir_okay = status_code == 404 ||
1739 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1740 /* 404 means that it didn't have them; no big deal.
1741 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1742 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1743 "Received http status code %d (%s) from server '%s:%d' "
1744 "while fetching \"/tor/server/%s\". I'll try again soon.",
1745 status_code, escaped(reason), conn->_base.address,
1746 conn->_base.port, conn->requested_resource);
1747 if (!which) {
1748 connection_dir_download_routerdesc_failed(conn);
1749 } else {
1750 dir_routerdesc_download_failed(which, status_code,
1751 conn->router_purpose,
1752 was_ei, descriptor_digests);
1753 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1754 smartlist_free(which);
1756 tor_free(body); tor_free(headers); tor_free(reason);
1757 return dir_okay ? 0 : -1;
1759 /* Learn the routers, assuming we requested by fingerprint or "all"
1760 * or "authority".
1762 * We use "authority" to fetch our own descriptor for
1763 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1764 * the output of "authority" requests unless we are using bridges,
1765 * since otherwise they'll be the response from reachability tests,
1766 * and we don't really want to add that to our routerlist. */
1767 if (which || (conn->requested_resource &&
1768 (!strcmpstart(conn->requested_resource, "all") ||
1769 (!strcmpstart(conn->requested_resource, "authority") &&
1770 get_options()->UseBridges)))) {
1771 /* as we learn from them, we remove them from 'which' */
1772 if (was_ei) {
1773 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1774 descriptor_digests);
1775 } else {
1776 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1777 // descriptor_digests, conn->router_purpose);
1778 if (load_downloaded_routers(body, which, descriptor_digests,
1779 conn->router_purpose,
1780 conn->_base.address))
1781 directory_info_has_arrived(now, 0);
1784 if (which) { /* mark remaining ones as failed */
1785 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1786 n_asked_for-smartlist_len(which), n_asked_for,
1787 was_ei ? "extra-info documents" : "router descriptors",
1788 conn->_base.address, (int)conn->_base.port);
1789 if (smartlist_len(which)) {
1790 dir_routerdesc_download_failed(which, status_code,
1791 conn->router_purpose,
1792 was_ei, descriptor_digests);
1794 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1795 smartlist_free(which);
1797 if (directory_conn_is_self_reachability_test(conn))
1798 router_dirport_found_reachable();
1801 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1802 switch (status_code) {
1803 case 200: {
1804 trusted_dir_server_t *ds =
1805 router_get_trusteddirserver_by_digest(conn->identity_digest);
1806 char *rejected_hdr = http_get_header(headers,
1807 "X-Descriptor-Not-New: ");
1808 int rejected = 0;
1809 if (rejected_hdr) {
1810 if (!strcmp(rejected_hdr, "Yes")) {
1811 log_info(LD_GENERAL,
1812 "Authority '%s' declined our descriptor (not new)",
1813 ds->nickname);
1814 /* XXXX use this information; be sure to upload next one
1815 * sooner. -NM */
1816 /* XXXX021 On further thought, the task above implies that we're
1817 * basing our regenerate-descriptor time on when we uploaded the
1818 * last descriptor, not on the published time of the last
1819 * descriptor. If those are different, that's a bad thing to
1820 * do. -NM */
1821 rejected = 1;
1823 tor_free(rejected_hdr);
1825 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1826 "descriptor: finished.");
1827 control_event_server_status(
1828 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1829 conn->_base.address, conn->_base.port);
1831 ds->has_accepted_serverdesc = 1;
1832 if (directories_have_accepted_server_descriptor())
1833 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1835 break;
1836 case 400:
1837 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1838 "dirserver '%s:%d'. Please correct.",
1839 escaped(reason), conn->_base.address, conn->_base.port);
1840 control_event_server_status(LOG_WARN,
1841 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1842 conn->_base.address, conn->_base.port, escaped(reason));
1843 break;
1844 default:
1845 log_warn(LD_GENERAL,
1846 "http status %d (%s) reason unexpected while uploading "
1847 "descriptor to server '%s:%d').",
1848 status_code, escaped(reason), conn->_base.address,
1849 conn->_base.port);
1850 break;
1852 /* return 0 in all cases, since we don't want to mark any
1853 * dirservers down just because they don't like us. */
1856 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
1857 switch (status_code) {
1858 case 200: {
1859 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
1860 conn->_base.address, conn->_base.port);
1862 break;
1863 case 400:
1864 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1865 "vote to dirserver '%s:%d'. Please correct.",
1866 escaped(reason), conn->_base.address, conn->_base.port);
1867 break;
1868 default:
1869 log_warn(LD_GENERAL,
1870 "http status %d (%s) reason unexpected while uploading "
1871 "vote to server '%s:%d').",
1872 status_code, escaped(reason), conn->_base.address,
1873 conn->_base.port);
1874 break;
1876 /* return 0 in all cases, since we don't want to mark any
1877 * dirservers down just because they don't like us. */
1880 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
1881 switch (status_code) {
1882 case 200: {
1883 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
1884 conn->_base.address, conn->_base.port);
1886 break;
1887 case 400:
1888 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1889 "signatures to dirserver '%s:%d'. Please correct.",
1890 escaped(reason), conn->_base.address, conn->_base.port);
1891 break;
1892 default:
1893 log_warn(LD_GENERAL,
1894 "http status %d (%s) reason unexpected while uploading "
1895 "signatures to server '%s:%d').",
1896 status_code, escaped(reason), conn->_base.address,
1897 conn->_base.port);
1898 break;
1900 /* return 0 in all cases, since we don't want to mark any
1901 * dirservers down just because they don't like us. */
1904 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1905 tor_assert(conn->rend_data);
1906 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1907 "(%s))",
1908 (int)body_len, status_code, escaped(reason));
1909 switch (status_code) {
1910 case 200:
1911 if (rend_cache_store(body, body_len, 0) < -1) {
1912 log_warn(LD_REND,"Failed to parse rendezvous descriptor.");
1913 /* Any pending rendezvous attempts will notice when
1914 * connection_about_to_close_connection()
1915 * cleans this dir conn up. */
1916 /* We could retry. But since v0 descriptors are going out of
1917 * style, it isn't worth the hassle. We'll do better in v2. */
1918 } else {
1919 /* Success, or at least there's a v2 descriptor already
1920 * present. Notify pending connections about this. */
1921 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1922 rend_client_desc_trynow(conn->rend_data->onion_address, -1);
1924 break;
1925 case 404:
1926 /* Not there. Pending connections will be notified when
1927 * connection_about_to_close_connection() cleans this conn up. */
1928 break;
1929 case 400:
1930 log_warn(LD_REND,
1931 "http status 400 (%s). Dirserver didn't like our "
1932 "rendezvous query?", escaped(reason));
1933 break;
1934 default:
1935 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1936 "fetching hidden service descriptor (server '%s:%d').",
1937 status_code, escaped(reason), conn->_base.address,
1938 conn->_base.port);
1939 break;
1943 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
1944 tor_assert(conn->rend_data);
1945 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1946 "(%s))",
1947 (int)body_len, status_code, escaped(reason));
1948 switch (status_code) {
1949 case 200:
1950 switch (rend_cache_store_v2_desc_as_client(body, conn->rend_data)) {
1951 case -2:
1952 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
1953 "Retrying at another directory.");
1954 /* We'll retry when connection_about_to_close_connection()
1955 * cleans this dir conn up. */
1956 break;
1957 case -1:
1958 /* We already have a v0 descriptor here. Ignoring this one
1959 * and _not_ performing another request. */
1960 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1961 "descriptor, but we already have a v0 descriptor.");
1962 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1963 break;
1964 default:
1965 /* success. notify pending connections about this. */
1966 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1967 "descriptor.");
1968 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1969 rend_client_desc_trynow(conn->rend_data->onion_address, -1);
1970 break;
1972 break;
1973 case 404:
1974 /* Not there. We'll retry when
1975 * connection_about_to_close_connection() cleans this conn up. */
1976 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
1977 "Retrying at another directory.");
1978 break;
1979 case 400:
1980 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1981 "http status 400 (%s). Dirserver didn't like our "
1982 "v2 rendezvous query? Retrying at another directory.",
1983 escaped(reason));
1984 break;
1985 default:
1986 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1987 "http status %d (%s) response unexpected while "
1988 "fetching v2 hidden service descriptor (server '%s:%d'). "
1989 "Retrying at another directory.",
1990 status_code, escaped(reason), conn->_base.address,
1991 conn->_base.port);
1992 break;
1996 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
1997 conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
1998 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
1999 "(%s))",
2000 status_code, escaped(reason));
2001 switch (status_code) {
2002 case 200:
2003 log_info(LD_REND,
2004 "Uploading rendezvous descriptor: finished with status "
2005 "200 (%s)", escaped(reason));
2006 break;
2007 case 400:
2008 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
2009 "'%s:%d'. Malformed rendezvous descriptor?",
2010 escaped(reason), conn->_base.address, conn->_base.port);
2011 break;
2012 case 503:
2013 log_info(LD_REND,"http status 503 (%s) response from dirserver "
2014 "'%s:%d'. Node is (currently) not acting as v2 hidden "
2015 "service directory.",
2016 escaped(reason), conn->_base.address, conn->_base.port);
2017 break;
2018 default:
2019 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
2020 "'%s:%d').",
2021 status_code, escaped(reason), conn->_base.address,
2022 conn->_base.port);
2023 break;
2026 note_client_request(conn->_base.purpose, was_compressed, orig_len);
2027 tor_free(body); tor_free(headers); tor_free(reason);
2028 return 0;
2031 /** Called when a directory connection reaches EOF. */
2033 connection_dir_reached_eof(dir_connection_t *conn)
2035 int retval;
2036 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
2037 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
2038 conn->_base.state);
2039 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
2040 connection_mark_for_close(TO_CONN(conn));
2041 return -1;
2044 retval = connection_dir_client_reached_eof(conn);
2045 if (retval == 0) /* success */
2046 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
2047 connection_mark_for_close(TO_CONN(conn));
2048 return retval;
2051 /** If any directory object is arriving, and it's over 10MB large, we're
2052 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
2053 * ask for more than 96 router descriptors at a time.)
2055 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
2057 /** Read handler for directory connections. (That's connections <em>to</em>
2058 * directory servers and connections <em>at</em> directory servers.)
2061 connection_dir_process_inbuf(dir_connection_t *conn)
2063 tor_assert(conn);
2064 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2066 /* Directory clients write, then read data until they receive EOF;
2067 * directory servers read data until they get an HTTP command, then
2068 * write their response (when it's finished flushing, they mark for
2069 * close).
2072 /* If we're on the dirserver side, look for a command. */
2073 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
2074 if (directory_handle_command(conn) < 0) {
2075 connection_mark_for_close(TO_CONN(conn));
2076 return -1;
2078 return 0;
2081 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
2082 log_warn(LD_HTTP, "Too much data received from directory connection: "
2083 "denial of service attempt, or you need to upgrade?");
2084 connection_mark_for_close(TO_CONN(conn));
2085 return -1;
2088 if (!conn->_base.inbuf_reached_eof)
2089 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
2090 return 0;
2093 /** Create an http response for the client <b>conn</b> out of
2094 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
2096 static void
2097 write_http_status_line(dir_connection_t *conn, int status,
2098 const char *reason_phrase)
2100 char buf[256];
2101 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
2102 status, reason_phrase ? reason_phrase : "OK") < 0) {
2103 log_warn(LD_BUG,"status line too long.");
2104 return;
2106 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
2109 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
2110 * with <b>type</b> as the Content-Type.
2112 * If <b>length</b> is nonnegative, it is the Content-Length.
2113 * If <b>encoding</b> is provided, it is the Content-Encoding.
2114 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
2115 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
2116 static void
2117 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
2118 const char *type, const char *encoding,
2119 const char *extra_headers,
2120 long cache_lifetime)
2122 char date[RFC1123_TIME_LEN+1];
2123 char tmp[1024];
2124 char *cp;
2125 time_t now = time(NULL);
2127 tor_assert(conn);
2129 format_rfc1123_time(date, now);
2130 cp = tmp;
2131 tor_snprintf(cp, sizeof(tmp),
2132 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
2133 date);
2134 cp += strlen(tmp);
2135 if (type) {
2136 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
2137 cp += strlen(cp);
2139 if (!is_local_addr(&conn->_base.addr)) {
2140 /* Don't report the source address for a nearby/private connection.
2141 * Otherwise we tend to mis-report in cases where incoming ports are
2142 * being forwarded to a Tor server running behind the firewall. */
2143 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2144 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
2145 cp += strlen(cp);
2147 if (encoding) {
2148 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2149 "Content-Encoding: %s\r\n", encoding);
2150 cp += strlen(cp);
2152 if (length >= 0) {
2153 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2154 "Content-Length: %ld\r\n", (long)length);
2155 cp += strlen(cp);
2157 if (cache_lifetime > 0) {
2158 char expbuf[RFC1123_TIME_LEN+1];
2159 format_rfc1123_time(expbuf, now + cache_lifetime);
2160 /* We could say 'Cache-control: max-age=%d' here if we start doing
2161 * http/1.1 */
2162 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2163 "Expires: %s\r\n", expbuf);
2164 cp += strlen(cp);
2165 } else if (cache_lifetime == 0) {
2166 /* We could say 'Cache-control: no-cache' here if we start doing
2167 * http/1.1 */
2168 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2169 cp += strlen(cp);
2171 if (extra_headers) {
2172 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2173 cp += strlen(cp);
2175 if (sizeof(tmp)-(cp-tmp) > 3)
2176 memcpy(cp, "\r\n", 3);
2177 else
2178 tor_assert(0);
2179 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2182 /** As write_http_response_header_impl, but sets encoding and content-typed
2183 * based on whether the response will be <b>compressed</b> or not. */
2184 static void
2185 write_http_response_header(dir_connection_t *conn, ssize_t length,
2186 int compressed, long cache_lifetime)
2188 write_http_response_header_impl(conn, length,
2189 compressed?"application/octet-stream":"text/plain",
2190 compressed?"deflate":"identity",
2191 NULL,
2192 cache_lifetime);
2195 #ifdef INSTRUMENT_DOWNLOADS
2196 typedef struct request_t {
2197 uint64_t bytes; /**< How many bytes have we transferred? */
2198 uint64_t count; /**< How many requests have we made? */
2199 } request_t;
2201 /** Map used to keep track of how much data we've up/downloaded in what kind
2202 * of request. Maps from request type to pointer to request_t. */
2203 static strmap_t *request_map = NULL;
2205 /** Record that a client request of <b>purpose</b> was made, and that
2206 * <b>bytes</b> bytes of possibly <b>compressed</b> data were sent/received.
2207 * Used to keep track of how much we've up/downloaded in what kind of
2208 * request. */
2209 static void
2210 note_client_request(int purpose, int compressed, size_t bytes)
2212 char *key;
2213 const char *kind = NULL;
2214 switch (purpose) {
2215 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS: kind = "dl/status"; break;
2216 case DIR_PURPOSE_FETCH_CONSENSUS: kind = "dl/consensus"; break;
2217 case DIR_PURPOSE_FETCH_CERTIFICATE: kind = "dl/cert"; break;
2218 case DIR_PURPOSE_FETCH_STATUS_VOTE: kind = "dl/vote"; break;
2219 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: kind = "dl/detached_sig";
2220 break;
2221 case DIR_PURPOSE_FETCH_SERVERDESC: kind = "dl/server"; break;
2222 case DIR_PURPOSE_FETCH_EXTRAINFO: kind = "dl/extra"; break;
2223 case DIR_PURPOSE_UPLOAD_DIR: kind = "dl/ul-dir"; break;
2224 case DIR_PURPOSE_UPLOAD_VOTE: kind = "dl/ul-vote"; break;
2225 case DIR_PURPOSE_UPLOAD_SIGNATURES: kind = "dl/ul-sig"; break;
2226 case DIR_PURPOSE_FETCH_RENDDESC: kind = "dl/rend"; break;
2227 case DIR_PURPOSE_FETCH_RENDDESC_V2: kind = "dl/rend2"; break;
2228 case DIR_PURPOSE_UPLOAD_RENDDESC: kind = "dl/ul-rend"; break;
2229 case DIR_PURPOSE_UPLOAD_RENDDESC_V2: kind = "dl/ul-rend2"; break;
2231 if (kind) {
2232 key = tor_malloc(256);
2233 tor_snprintf(key, 256, "%s%s", kind, compressed?".z":"");
2234 } else {
2235 key = tor_malloc(256);
2236 tor_snprintf(key, 256, "unknown purpose (%d)%s",
2237 purpose, compressed?".z":"");
2239 note_request(key, bytes);
2240 tor_free(key);
2243 /** Helper: initialize the request map to instrument downloads. */
2244 static void
2245 ensure_request_map_initialized(void)
2247 if (!request_map)
2248 request_map = strmap_new();
2251 /** Called when we just transmitted or received <b>bytes</b> worth of data
2252 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2253 * <b>bytes</b> to the total associated with key. */
2254 void
2255 note_request(const char *key, size_t bytes)
2257 request_t *r;
2258 ensure_request_map_initialized();
2260 r = strmap_get(request_map, key);
2261 if (!r) {
2262 r = tor_malloc_zero(sizeof(request_t));
2263 strmap_set(request_map, key, r);
2265 r->bytes += bytes;
2266 r->count++;
2269 /** Return a newly allocated string holding a summary of bytes used per
2270 * request type. */
2271 char *
2272 directory_dump_request_log(void)
2274 smartlist_t *lines;
2275 char tmp[256];
2276 char *result;
2277 strmap_iter_t *iter;
2279 ensure_request_map_initialized();
2281 lines = smartlist_create();
2283 for (iter = strmap_iter_init(request_map);
2284 !strmap_iter_done(iter);
2285 iter = strmap_iter_next(request_map, iter)) {
2286 const char *key;
2287 void *val;
2288 request_t *r;
2289 strmap_iter_get(iter, &key, &val);
2290 r = val;
2291 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT" "U64_FORMAT"\n",
2292 key, U64_PRINTF_ARG(r->bytes), U64_PRINTF_ARG(r->count));
2293 smartlist_add(lines, tor_strdup(tmp));
2295 smartlist_sort_strings(lines);
2296 result = smartlist_join_strings(lines, "", 0, NULL);
2297 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2298 smartlist_free(lines);
2299 return result;
2301 #else
2302 static void
2303 note_client_request(int purpose, int compressed, size_t bytes)
2305 (void)purpose;
2306 (void)compressed;
2307 (void)bytes;
2310 void
2311 note_request(const char *key, size_t bytes)
2313 (void)key;
2314 (void)bytes;
2317 char *
2318 directory_dump_request_log(void)
2320 return tor_strdup("Not supported.");
2322 #endif
2324 /** Decide whether a client would accept the consensus we have
2326 * Clients can say they only want a consensus if it's signed by more
2327 * than half the authorities in a list. They pass this list in
2328 * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
2330 * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
2331 * of the full authority identity digest. (Only strings of even length,
2332 * i.e. encodings of full bytes, are handled correctly. In the case
2333 * of an odd number of hex digits the last one is silently ignored.)
2335 * Returns 1 if more than half of the requested authorities signed the
2336 * consensus, 0 otherwise.
2339 client_likes_consensus(networkstatus_t *v, const char *want_url)
2341 smartlist_t *want_authorities = smartlist_create();
2342 int need_at_least;
2343 int have = 0;
2345 dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0, 0);
2346 need_at_least = smartlist_len(want_authorities)/2+1;
2347 SMARTLIST_FOREACH(want_authorities, const char *, d, {
2348 char want_digest[DIGEST_LEN];
2349 int want_len = strlen(d)/2;
2350 if (want_len > DIGEST_LEN)
2351 want_len = DIGEST_LEN;
2353 if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) {
2354 log_warn(LD_DIR,"Failed to decode requested authority digest %s.", d);
2355 continue;
2358 SMARTLIST_FOREACH(v->voters, networkstatus_voter_info_t *, vi, {
2359 if (vi->signature &&
2360 !memcmp(vi->identity_digest, want_digest, want_len)) {
2361 have++;
2362 break;
2366 /* early exit, if we already have enough */
2367 if (have >= need_at_least)
2368 break;
2371 SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
2372 smartlist_free(want_authorities);
2373 return (have >= need_at_least);
2376 /** Helper function: called when a dirserver gets a complete HTTP GET
2377 * request. Look for a request for a directory or for a rendezvous
2378 * service descriptor. On finding one, write a response into
2379 * conn-\>outbuf. If the request is unrecognized, send a 400.
2380 * Always return 0. */
2381 static int
2382 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2383 const char *body, size_t body_len)
2385 size_t dlen;
2386 char *url, *url_mem, *header;
2387 or_options_t *options = get_options();
2388 time_t if_modified_since = 0;
2389 int compressed;
2390 size_t url_len;
2392 /* We ignore the body of a GET request. */
2393 (void)body;
2394 (void)body_len;
2396 log_debug(LD_DIRSERV,"Received GET command.");
2398 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2400 if (parse_http_url(headers, &url) < 0) {
2401 write_http_status_line(conn, 400, "Bad request");
2402 return 0;
2404 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2405 struct tm tm;
2406 if (parse_http_time(header, &tm) == 0) {
2407 if_modified_since = tor_timegm(&tm);
2409 /* The correct behavior on a malformed If-Modified-Since header is to
2410 * act as if no If-Modified-Since header had been given. */
2411 tor_free(header);
2413 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2415 url_mem = url;
2416 url_len = strlen(url);
2417 compressed = url_len > 2 && !strcmp(url+url_len-2, ".z");
2418 if (compressed) {
2419 url[url_len-2] = '\0';
2420 url_len -= 2;
2423 if (!strcmp(url,"/tor/")) {
2424 const char *frontpage = get_dirportfrontpage();
2426 if (frontpage) {
2427 dlen = strlen(frontpage);
2428 /* Let's return a disclaimer page (users shouldn't use V1 anymore,
2429 and caches don't fetch '/', so this is safe). */
2430 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2431 log_info(LD_DIRSERV,
2432 "Client asked for DirPortFrontPage content, but we've been "
2433 "writing too many bytes lately. Sending 503 Dir busy.");
2434 write_http_status_line(conn, 503, "Directory busy, try again later");
2435 goto done;
2437 note_request(url, dlen);
2438 write_http_response_header_impl(conn, dlen, "text/html", "identity",
2439 NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
2440 connection_write_to_buf(frontpage, dlen, TO_CONN(conn));
2441 goto done;
2443 /* if no disclaimer file, fall through and continue */
2446 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* v1 dir fetch */
2447 cached_dir_t *d = dirserv_get_directory();
2449 if (!d) {
2450 log_info(LD_DIRSERV,"Client asked for the mirrored directory, but we "
2451 "don't have a good one yet. Sending 503 Dir not available.");
2452 write_http_status_line(conn, 503, "Directory unavailable");
2453 goto done;
2455 if (d->published < if_modified_since) {
2456 write_http_status_line(conn, 304, "Not modified");
2457 goto done;
2460 dlen = compressed ? d->dir_z_len : d->dir_len;
2462 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2463 log_debug(LD_DIRSERV,
2464 "Client asked for the mirrored directory, but we've been "
2465 "writing too many bytes lately. Sending 503 Dir busy.");
2466 write_http_status_line(conn, 503, "Directory busy, try again later");
2467 goto done;
2470 note_request(url, dlen);
2472 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
2473 compressed?"compressed ":"");
2474 write_http_response_header(conn, dlen, compressed,
2475 FULL_DIR_CACHE_LIFETIME);
2476 conn->cached_dir = d;
2477 conn->cached_dir_offset = 0;
2478 if (!compressed)
2479 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2480 ++d->refcnt;
2482 /* Prime the connection with some data. */
2483 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
2484 connection_dirserv_flushed_some(conn);
2485 goto done;
2488 if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
2489 cached_dir_t *d = dirserv_get_runningrouters();
2490 if (!d) {
2491 write_http_status_line(conn, 503, "Directory unavailable");
2492 goto done;
2494 if (d->published < if_modified_since) {
2495 write_http_status_line(conn, 304, "Not modified");
2496 goto done;
2498 dlen = compressed ? d->dir_z_len : d->dir_len;
2500 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2501 log_info(LD_DIRSERV,
2502 "Client asked for running-routers, but we've been "
2503 "writing too many bytes lately. Sending 503 Dir busy.");
2504 write_http_status_line(conn, 503, "Directory busy, try again later");
2505 goto done;
2507 note_request(url, dlen);
2508 write_http_response_header(conn, dlen, compressed,
2509 RUNNINGROUTERS_CACHE_LIFETIME);
2510 connection_write_to_buf(compressed ? d->dir_z : d->dir, dlen,
2511 TO_CONN(conn));
2512 goto done;
2515 if (!strcmpstart(url,"/tor/status/")
2516 || !strcmpstart(url, "/tor/status-vote/current/consensus")) {
2517 /* v2 or v3 network status fetch. */
2518 smartlist_t *dir_fps = smartlist_create();
2519 int is_v3 = !strcmpstart(url, "/tor/status-vote");
2520 const char *request_type = NULL;
2521 const char *key = url + strlen("/tor/status/");
2522 long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2523 if (!is_v3) {
2524 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
2525 if (!strcmpstart(key, "fp/"))
2526 request_type = compressed?"/tor/status/fp.z":"/tor/status/fp";
2527 else if (!strcmpstart(key, "authority"))
2528 request_type = compressed?"/tor/status/authority.z":
2529 "/tor/status/authority";
2530 else if (!strcmpstart(key, "all"))
2531 request_type = compressed?"/tor/status/all.z":"/tor/status/all";
2532 else
2533 request_type = "/tor/status/?";
2534 } else {
2535 networkstatus_t *v = networkstatus_get_latest_consensus();
2536 time_t now = time(NULL);
2537 #define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/"
2538 if (v &&
2539 !strcmpstart(url, CONSENSUS_URL_PREFIX) &&
2540 !client_likes_consensus(v, url + strlen(CONSENSUS_URL_PREFIX))) {
2541 write_http_status_line(conn, 404, "Consensus not signed by sufficient "
2542 "number of requested authorities");
2543 smartlist_free(dir_fps);
2544 goto done;
2547 smartlist_add(dir_fps, tor_memdup("\0\0\0\0\0\0\0\0\0\0"
2548 "\0\0\0\0\0\0\0\0\0\0", 20));
2549 request_type = compressed?"v3.z":"v3";
2550 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2553 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2554 write_http_status_line(conn, 503, "Network status object unavailable");
2555 smartlist_free(dir_fps);
2556 goto done;
2559 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2560 write_http_status_line(conn, 404, "Not found");
2561 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2562 smartlist_free(dir_fps);
2563 goto done;
2564 } else if (!smartlist_len(dir_fps)) {
2565 write_http_status_line(conn, 304, "Not modified");
2566 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2567 smartlist_free(dir_fps);
2568 goto done;
2571 dlen = dirserv_estimate_data_size(dir_fps, 0, compressed);
2572 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2573 log_debug(LD_DIRSERV,
2574 "Client asked for network status lists, but we've been "
2575 "writing too many bytes lately. Sending 503 Dir busy.");
2576 write_http_status_line(conn, 503, "Directory busy, try again later");
2577 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2578 smartlist_free(dir_fps);
2579 goto done;
2582 #ifdef ENABLE_GEOIP_STATS
2584 geoip_client_action_t act =
2585 is_v3 ? GEOIP_CLIENT_NETWORKSTATUS : GEOIP_CLIENT_NETWORKSTATUS_V2;
2586 struct in_addr in;
2587 if (tor_inet_aton((TO_CONN(conn))->address, &in))
2588 geoip_note_client_seen(act, ntohl(in.s_addr), time(NULL));
2590 #endif
2592 // note_request(request_type,dlen);
2593 (void) request_type;
2594 write_http_response_header(conn, -1, compressed,
2595 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2596 conn->fingerprint_stack = dir_fps;
2597 if (! compressed)
2598 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2600 /* Prime the connection with some data. */
2601 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2602 connection_dirserv_flushed_some(conn);
2603 goto done;
2606 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2607 !strcmpstart(url,"/tor/status-vote/next/")) {
2608 /* XXXX If-modified-since is only implemented for the current
2609 * consensus: that's probably fine, since it's the only vote document
2610 * people fetch much. */
2611 int current;
2612 ssize_t body_len = 0;
2613 ssize_t estimated_len = 0;
2614 smartlist_t *items = smartlist_create();
2615 smartlist_t *dir_items = smartlist_create();
2616 int lifetime = 60; /* XXXX022 should actually use vote intervals. */
2617 url += strlen("/tor/status-vote/");
2618 current = !strcmpstart(url, "current/");
2619 url = strchr(url, '/');
2620 tor_assert(url);
2621 ++url;
2622 if (!strcmp(url, "consensus")) {
2623 const char *item;
2624 tor_assert(!current); /* we handle current consensus specially above,
2625 * since it wants to be spooled. */
2626 if ((item = dirvote_get_pending_consensus()))
2627 smartlist_add(items, (char*)item);
2628 } else if (!current && !strcmp(url, "consensus-signatures")) {
2629 /* XXXX the spec says that we should implement
2630 * current/consensus-signatures too. It doesn't seem to be needed,
2631 * though. */
2632 const char *item;
2633 if ((item=dirvote_get_pending_detached_signatures()))
2634 smartlist_add(items, (char*)item);
2635 } else if (!strcmp(url, "authority")) {
2636 const cached_dir_t *d;
2637 int flags = DGV_BY_ID |
2638 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2639 if ((d=dirvote_get_vote(NULL, flags)))
2640 smartlist_add(dir_items, (cached_dir_t*)d);
2641 } else {
2642 const cached_dir_t *d;
2643 smartlist_t *fps = smartlist_create();
2644 int flags;
2645 if (!strcmpstart(url, "d/")) {
2646 url += 2;
2647 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2648 } else {
2649 flags = DGV_BY_ID |
2650 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2652 dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1);
2653 SMARTLIST_FOREACH(fps, char *, fp, {
2654 if ((d = dirvote_get_vote(fp, flags)))
2655 smartlist_add(dir_items, (cached_dir_t*)d);
2656 tor_free(fp);
2658 smartlist_free(fps);
2660 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2661 write_http_status_line(conn, 404, "Not found");
2662 goto vote_done;
2664 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2665 body_len += compressed ? d->dir_z_len : d->dir_len);
2666 estimated_len += body_len;
2667 SMARTLIST_FOREACH(items, const char *, item, {
2668 size_t ln = strlen(item);
2669 if (compressed) {
2670 estimated_len += ln/2;
2671 } else {
2672 body_len += ln; estimated_len += ln;
2676 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
2677 write_http_status_line(conn, 503, "Directory busy, try again later.");
2678 goto vote_done;
2680 write_http_response_header(conn, body_len ? body_len : -1, compressed,
2681 lifetime);
2683 if (smartlist_len(items)) {
2684 if (compressed) {
2685 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2686 SMARTLIST_FOREACH(items, const char *, c,
2687 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2688 connection_write_to_buf_zlib("", 0, conn, 1);
2689 } else {
2690 SMARTLIST_FOREACH(items, const char *, c,
2691 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2693 } else {
2694 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2695 connection_write_to_buf(compressed ? d->dir_z : d->dir,
2696 compressed ? d->dir_z_len : d->dir_len,
2697 TO_CONN(conn)));
2699 vote_done:
2700 smartlist_free(items);
2701 smartlist_free(dir_items);
2702 goto done;
2705 if (!strcmpstart(url,"/tor/server/") ||
2706 (!options->BridgeAuthoritativeDir &&
2707 !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
2708 int res;
2709 const char *msg;
2710 const char *request_type = NULL;
2711 int cache_lifetime = 0;
2712 int is_extra = !strcmpstart(url,"/tor/extra/");
2713 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2714 conn->fingerprint_stack = smartlist_create();
2715 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2716 &msg,
2717 !connection_dir_is_encrypted(conn),
2718 is_extra);
2720 if (!strcmpstart(url, "fp/")) {
2721 request_type = compressed?"/tor/server/fp.z":"/tor/server/fp";
2722 if (smartlist_len(conn->fingerprint_stack) == 1)
2723 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2724 } else if (!strcmpstart(url, "authority")) {
2725 request_type = compressed?"/tor/server/authority.z":
2726 "/tor/server/authority";
2727 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2728 } else if (!strcmpstart(url, "all")) {
2729 request_type = compressed?"/tor/server/all.z":"/tor/server/all";
2730 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2731 } else if (!strcmpstart(url, "d/")) {
2732 request_type = compressed?"/tor/server/d.z":"/tor/server/d";
2733 if (smartlist_len(conn->fingerprint_stack) == 1)
2734 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2735 } else {
2736 request_type = "/tor/server/?";
2738 (void) request_type; /* usable for note_request. */
2739 if (!strcmpstart(url, "d/"))
2740 conn->dir_spool_src =
2741 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2742 else
2743 conn->dir_spool_src =
2744 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2746 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2747 conn->dir_spool_src)) {
2748 res = -1;
2749 msg = "Not found";
2752 if (res < 0)
2753 write_http_status_line(conn, 404, msg);
2754 else {
2755 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2756 1, compressed);
2757 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2758 log_info(LD_DIRSERV,
2759 "Client asked for server descriptors, but we've been "
2760 "writing too many bytes lately. Sending 503 Dir busy.");
2761 write_http_status_line(conn, 503, "Directory busy, try again later");
2762 conn->dir_spool_src = DIR_SPOOL_NONE;
2763 goto done;
2765 write_http_response_header(conn, -1, compressed, cache_lifetime);
2766 if (compressed)
2767 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2768 /* Prime the connection with some data. */
2769 connection_dirserv_flushed_some(conn);
2771 goto done;
2774 if (!strcmpstart(url,"/tor/keys/")) {
2775 smartlist_t *certs = smartlist_create();
2776 ssize_t len = -1;
2777 if (!strcmp(url, "/tor/keys/all")) {
2778 authority_cert_get_all(certs);
2779 } else if (!strcmp(url, "/tor/keys/authority")) {
2780 authority_cert_t *cert = get_my_v3_authority_cert();
2781 if (cert)
2782 smartlist_add(certs, cert);
2783 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
2784 smartlist_t *fps = smartlist_create();
2785 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
2786 fps, NULL, 1, 1);
2787 SMARTLIST_FOREACH(fps, char *, d, {
2788 authority_cert_t *c = authority_cert_get_newest_by_id(d);
2789 if (c) smartlist_add(certs, c);
2790 tor_free(d);
2792 smartlist_free(fps);
2793 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
2794 smartlist_t *fps = smartlist_create();
2795 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
2796 fps, NULL, 1, 1);
2797 SMARTLIST_FOREACH(fps, char *, d, {
2798 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
2799 if (c) smartlist_add(certs, c);
2800 tor_free(d);
2802 smartlist_free(fps);
2803 } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
2804 smartlist_t *fp_sks = smartlist_create();
2805 dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
2806 fp_sks);
2807 SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
2808 authority_cert_t *c = authority_cert_get_by_digests(pair->first,
2809 pair->second);
2810 if (c) smartlist_add(certs, c);
2811 tor_free(pair);
2813 smartlist_free(fp_sks);
2814 } else {
2815 write_http_status_line(conn, 400, "Bad request");
2816 goto keys_done;
2818 if (!smartlist_len(certs)) {
2819 write_http_status_line(conn, 404, "Not found");
2820 goto keys_done;
2822 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2823 if (c->cache_info.published_on < if_modified_since)
2824 SMARTLIST_DEL_CURRENT(certs, c));
2825 if (!smartlist_len(certs)) {
2826 write_http_status_line(conn, 304, "Not modified");
2827 goto keys_done;
2829 len = 0;
2830 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2831 len += c->cache_info.signed_descriptor_len);
2833 if (global_write_bucket_low(TO_CONN(conn), compressed?len/2:len, 2)) {
2834 write_http_status_line(conn, 503, "Directory busy, try again later.");
2835 goto keys_done;
2838 write_http_response_header(conn, compressed?-1:len, compressed, 60*60);
2839 if (compressed) {
2840 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2841 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2842 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
2843 c->cache_info.signed_descriptor_len,
2844 conn, 0));
2845 connection_write_to_buf_zlib("", 0, conn, 1);
2846 } else {
2847 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2848 connection_write_to_buf(c->cache_info.signed_descriptor_body,
2849 c->cache_info.signed_descriptor_len,
2850 TO_CONN(conn)));
2852 keys_done:
2853 smartlist_free(certs);
2854 goto done;
2857 if (options->HidServDirectoryV2 &&
2858 !strcmpstart(url,"/tor/rendezvous2/")) {
2859 /* Handle v2 rendezvous descriptor fetch request. */
2860 const char *descp;
2861 const char *query = url + strlen("/tor/rendezvous2/");
2862 if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) {
2863 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
2864 safe_str(query));
2865 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
2866 case 1: /* valid */
2867 write_http_response_header(conn, strlen(descp), 0, 0);
2868 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
2869 break;
2870 case 0: /* well-formed but not present */
2871 write_http_status_line(conn, 404, "Not found");
2872 break;
2873 case -1: /* not well-formed */
2874 write_http_status_line(conn, 400, "Bad request");
2875 break;
2877 } else { /* not well-formed */
2878 write_http_status_line(conn, 400, "Bad request");
2880 goto done;
2883 if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) {
2884 /* rendezvous descriptor fetch */
2885 const char *descp;
2886 size_t desc_len;
2887 const char *query = url+strlen("/tor/rendezvous/");
2889 log_info(LD_REND, "Handling rendezvous descriptor get");
2890 switch (rend_cache_lookup_desc(query, 0, &descp, &desc_len)) {
2891 case 1: /* valid */
2892 write_http_response_header_impl(conn, desc_len,
2893 "application/octet-stream",
2894 NULL, NULL, 0);
2895 note_request("/tor/rendezvous?/", desc_len);
2896 /* need to send descp separately, because it may include nuls */
2897 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
2898 /* report successful fetch to statistic */
2899 if (options->HSAuthorityRecordStats) {
2900 hs_usage_note_fetch_total(query, time(NULL));
2901 hs_usage_note_fetch_successful(query, time(NULL));
2903 break;
2904 case 0: /* well-formed but not present */
2905 write_http_status_line(conn, 404, "Not found");
2906 /* report (unsuccessful) fetch to statistic */
2907 if (options->HSAuthorityRecordStats) {
2908 hs_usage_note_fetch_total(query, time(NULL));
2910 break;
2911 case -1: /* not well-formed */
2912 write_http_status_line(conn, 400, "Bad request");
2913 break;
2915 goto done;
2918 if (options->BridgeAuthoritativeDir &&
2919 options->BridgePassword &&
2920 connection_dir_is_encrypted(conn) &&
2921 !strcmp(url,"/tor/networkstatus-bridges")) {
2922 char *status;
2923 char *secret = alloc_http_authenticator(options->BridgePassword);
2925 header = http_get_header(headers, "Authorization: Basic ");
2927 /* now make sure the password is there and right */
2928 if (!header || strcmp(header, secret)) {
2929 write_http_status_line(conn, 404, "Not found");
2930 tor_free(secret);
2931 tor_free(header);
2932 goto done;
2934 tor_free(secret);
2935 tor_free(header);
2937 /* all happy now. send an answer. */
2938 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
2939 dlen = strlen(status);
2940 write_http_response_header(conn, dlen, 0, 0);
2941 connection_write_to_buf(status, dlen, TO_CONN(conn));
2942 tor_free(status);
2943 goto done;
2946 if (!strcmpstart(url,"/tor/bytes.txt")) {
2947 char *bytes = directory_dump_request_log();
2948 size_t len = strlen(bytes);
2949 write_http_response_header(conn, len, 0, 0);
2950 connection_write_to_buf(bytes, len, TO_CONN(conn));
2951 tor_free(bytes);
2952 goto done;
2955 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
2956 rewritten to /tor/robots.txt */
2957 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
2958 size_t len = strlen(robots);
2959 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
2960 connection_write_to_buf(robots, len, TO_CONN(conn));
2961 goto done;
2964 if (!strcmp(url,"/tor/dbg-stability.txt")) {
2965 const char *stability;
2966 size_t len;
2967 if (! authdir_mode_tests_reachability(options) ||
2968 ! (stability = rep_hist_get_router_stability_doc(time(NULL)))) {
2969 write_http_status_line(conn, 404, "Not found.");
2970 goto done;
2973 len = strlen(stability);
2974 write_http_response_header(conn, len, 0, 0);
2975 connection_write_to_buf(stability, len, TO_CONN(conn));
2976 goto done;
2979 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
2980 #define ADD_MALLINFO_LINE(x) do { \
2981 tor_snprintf(tmp, sizeof(tmp), "%s %d\n", #x, mi.x); \
2982 smartlist_add(lines, tor_strdup(tmp)); \
2983 }while(0);
2985 if (!strcmp(url,"/tor/mallinfo.txt") &&
2986 (tor_addr_eq_ipv4h(&conn->_base.addr, 0x7f000001ul))) {
2987 char *result;
2988 size_t len;
2989 struct mallinfo mi;
2990 smartlist_t *lines;
2991 char tmp[256];
2993 memset(&mi, 0, sizeof(mi));
2994 mi = mallinfo();
2995 lines = smartlist_create();
2997 ADD_MALLINFO_LINE(arena)
2998 ADD_MALLINFO_LINE(ordblks)
2999 ADD_MALLINFO_LINE(smblks)
3000 ADD_MALLINFO_LINE(hblks)
3001 ADD_MALLINFO_LINE(hblkhd)
3002 ADD_MALLINFO_LINE(usmblks)
3003 ADD_MALLINFO_LINE(fsmblks)
3004 ADD_MALLINFO_LINE(uordblks)
3005 ADD_MALLINFO_LINE(fordblks)
3006 ADD_MALLINFO_LINE(keepcost)
3008 result = smartlist_join_strings(lines, "", 0, NULL);
3009 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
3010 smartlist_free(lines);
3012 len = strlen(result);
3013 write_http_response_header(conn, len, 0, 0);
3014 connection_write_to_buf(result, len, TO_CONN(conn));
3015 tor_free(result);
3016 goto done;
3018 #endif
3020 /* we didn't recognize the url */
3021 write_http_status_line(conn, 404, "Not found");
3023 done:
3024 tor_free(url_mem);
3025 return 0;
3028 /** Helper function: called when a dirserver gets a complete HTTP POST
3029 * request. Look for an uploaded server descriptor or rendezvous
3030 * service descriptor. On finding one, process it and write a
3031 * response into conn-\>outbuf. If the request is unrecognized, send a
3032 * 400. Always return 0. */
3033 static int
3034 directory_handle_command_post(dir_connection_t *conn, const char *headers,
3035 const char *body, size_t body_len)
3037 char *url = NULL;
3038 or_options_t *options = get_options();
3040 log_debug(LD_DIRSERV,"Received POST command.");
3042 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
3044 if (parse_http_url(headers, &url) < 0) {
3045 write_http_status_line(conn, 400, "Bad request");
3046 return 0;
3048 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
3050 /* Handle v2 rendezvous service publish request. */
3051 if (options->HidServDirectoryV2 &&
3052 !strcmpstart(url,"/tor/rendezvous2/publish")) {
3053 switch (rend_cache_store_v2_desc_as_dir(body)) {
3054 case -2:
3055 log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
3056 "since we're not currently a hidden service directory.",
3057 (int)body_len, conn->_base.address);
3058 write_http_status_line(conn, 503, "Currently not acting as v2 "
3059 "hidden service directory");
3060 break;
3061 case -1:
3062 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
3063 (int)body_len, conn->_base.address);
3064 write_http_status_line(conn, 400,
3065 "Invalid v2 service descriptor rejected");
3066 break;
3067 default:
3068 write_http_status_line(conn, 200, "Service descriptor (v2) stored");
3069 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
3071 goto done;
3074 if (!authdir_mode(options)) {
3075 /* we just provide cached directories; we don't want to
3076 * receive anything. */
3077 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
3078 "accept posted server descriptors");
3079 goto done;
3082 if (authdir_mode_handles_descs(options, -1) &&
3083 !strcmp(url,"/tor/")) { /* server descriptor post */
3084 const char *msg = "[None]";
3085 uint8_t purpose = authdir_mode_bridge(options) ?
3086 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
3087 was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
3088 conn->_base.address, &msg);
3089 tor_assert(msg);
3090 if (WRA_WAS_ADDED(r))
3091 dirserv_get_directory(); /* rebuild and write to disk */
3093 if (r == ROUTER_ADDED_NOTIFY_GENERATOR) {
3094 /* Accepted with a message. */
3095 log_info(LD_DIRSERV,
3096 "Problematic router descriptor or extra-info from %s "
3097 "(\"%s\").",
3098 conn->_base.address, msg);
3099 write_http_status_line(conn, 400, msg);
3100 } else if (r == ROUTER_ADDED_SUCCESSFULLY) {
3101 write_http_status_line(conn, 200, msg);
3102 } else if (WRA_WAS_OUTDATED(r)) {
3103 write_http_response_header_impl(conn, -1, NULL, NULL,
3104 "X-Descriptor-Not-New: Yes\r\n", -1);
3105 } else {
3106 log_info(LD_DIRSERV,
3107 "Rejected router descriptor or extra-info from %s "
3108 "(\"%s\").",
3109 conn->_base.address, msg);
3110 write_http_status_line(conn, 400, msg);
3112 goto done;
3115 if (options->HSAuthoritativeDir &&
3116 !strcmpstart(url,"/tor/rendezvous/publish")) {
3117 /* rendezvous descriptor post */
3118 log_info(LD_REND, "Handling rendezvous descriptor post.");
3119 if (rend_cache_store(body, body_len, 1) < 0) {
3120 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
3121 "Rejected rend descriptor (length %d) from %s.",
3122 (int)body_len, conn->_base.address);
3123 write_http_status_line(conn, 400,
3124 "Invalid v0 service descriptor rejected");
3125 } else {
3126 write_http_status_line(conn, 200, "Service descriptor (v0) stored");
3128 goto done;
3131 if (authdir_mode_v3(options) &&
3132 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
3133 const char *msg = "OK";
3134 int status;
3135 if (dirvote_add_vote(body, &msg, &status)) {
3136 write_http_status_line(conn, status, "Vote stored");
3137 } else {
3138 tor_assert(msg);
3139 write_http_status_line(conn, status, msg);
3141 goto done;
3144 if (authdir_mode_v3(options) &&
3145 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
3146 const char *msg = NULL;
3147 if (dirvote_add_signatures(body, conn->_base.address, &msg)>=0) {
3148 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
3149 } else {
3150 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
3151 conn->_base.address, msg?msg:"???");
3152 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
3154 goto done;
3157 /* we didn't recognize the url */
3158 write_http_status_line(conn, 404, "Not found");
3160 done:
3161 tor_free(url);
3162 return 0;
3165 /** Called when a dirserver receives data on a directory connection;
3166 * looks for an HTTP request. If the request is complete, remove it
3167 * from the inbuf, try to process it; otherwise, leave it on the
3168 * buffer. Return a 0 on success, or -1 on error.
3170 static int
3171 directory_handle_command(dir_connection_t *conn)
3173 char *headers=NULL, *body=NULL;
3174 size_t body_len=0;
3175 int r;
3177 tor_assert(conn);
3178 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3180 switch (fetch_from_buf_http(conn->_base.inbuf,
3181 &headers, MAX_HEADERS_SIZE,
3182 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
3183 case -1: /* overflow */
3184 log_warn(LD_DIRSERV,
3185 "Invalid input from address '%s'. Closing.",
3186 conn->_base.address);
3187 return -1;
3188 case 0:
3189 log_debug(LD_DIRSERV,"command not all here yet.");
3190 return 0;
3191 /* case 1, fall through */
3194 http_set_address_origin(headers, TO_CONN(conn));
3195 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
3197 if (!strncasecmp(headers,"GET",3))
3198 r = directory_handle_command_get(conn, headers, body, body_len);
3199 else if (!strncasecmp(headers,"POST",4))
3200 r = directory_handle_command_post(conn, headers, body, body_len);
3201 else {
3202 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
3203 "Got headers %s with unknown command. Closing.",
3204 escaped(headers));
3205 r = -1;
3208 tor_free(headers); tor_free(body);
3209 return r;
3212 /** Write handler for directory connections; called when all data has
3213 * been flushed. Close the connection or wait for a response as
3214 * appropriate.
3217 connection_dir_finished_flushing(dir_connection_t *conn)
3219 tor_assert(conn);
3220 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3222 switch (conn->_base.state) {
3223 case DIR_CONN_STATE_CLIENT_SENDING:
3224 log_debug(LD_DIR,"client finished sending command.");
3225 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
3226 connection_stop_writing(TO_CONN(conn));
3227 return 0;
3228 case DIR_CONN_STATE_SERVER_WRITING:
3229 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
3230 connection_mark_for_close(TO_CONN(conn));
3231 return 0;
3232 default:
3233 log_warn(LD_BUG,"called in unexpected state %d.",
3234 conn->_base.state);
3235 tor_fragile_assert();
3236 return -1;
3238 return 0;
3241 /** Connected handler for directory connections: begin sending data to the
3242 * server */
3244 connection_dir_finished_connecting(dir_connection_t *conn)
3246 tor_assert(conn);
3247 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3248 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
3250 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
3251 conn->_base.address,conn->_base.port);
3253 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
3254 return 0;
3257 /** Called when one or more networkstatus fetches have failed (with uppercase
3258 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
3259 * failed once, unless they failed with status code 503. */
3260 static void
3261 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
3263 if (status_code == 503)
3264 return;
3265 SMARTLIST_FOREACH(failed, const char *, fp,
3267 char digest[DIGEST_LEN];
3268 trusted_dir_server_t *dir;
3269 if (base16_decode(digest, DIGEST_LEN, fp, strlen(fp))<0) {
3270 log_warn(LD_BUG, "Called with bad fingerprint in list: %s",
3271 escaped(fp));
3272 continue;
3274 dir = router_get_trusteddirserver_by_digest(digest);
3276 if (dir)
3277 download_status_failed(&dir->v2_ns_dl_status, status_code);
3281 /** Schedule for when servers should download things in general. */
3282 static const int server_dl_schedule[] = {
3283 0, 0, 0, 60, 60, 60*2, 60*5, 60*15, INT_MAX
3285 /** Schedule for when clients should download things in general. */
3286 static const int client_dl_schedule[] = {
3287 0, 0, 60, 60*5, 60*10, INT_MAX
3289 /** Schedule for when servers should download consensuses. */
3290 static const int server_consensus_dl_schedule[] = {
3291 0, 0, 60, 60*5, 60*10, 60*30, 60*30, 60*30, 60*30, 60*30, 60*60, 60*60*2
3293 /** Schedule for when clients should download consensuses. */
3294 static const int client_consensus_dl_schedule[] = {
3295 0, 0, 60, 60*5, 60*10, 60*30, 60*60, 60*60, 60*60, 60*60*3, 60*60*6, 60*60*12
3297 /** Schedule for when clients should download bridge descriptors. */
3298 static const int bridge_dl_schedule[] = {
3299 60*60, 15*60, 15*60, 60*60
3302 /** Decide which download schedule we want to use, and then return a
3303 * pointer to it along with a pointer to its length. Helper function for
3304 * download_status_increment_failure() and download_status_reset(). */
3305 static void
3306 find_dl_schedule_and_len(download_status_t *dls, int server,
3307 const int **schedule, size_t *schedule_len)
3309 switch (dls->schedule) {
3310 case DL_SCHED_GENERIC:
3311 if (server) {
3312 *schedule = server_dl_schedule;
3313 *schedule_len = sizeof(server_dl_schedule)/sizeof(int);
3314 } else {
3315 *schedule = client_dl_schedule;
3316 *schedule_len = sizeof(client_dl_schedule)/sizeof(int);
3318 break;
3319 case DL_SCHED_CONSENSUS:
3320 if (server) {
3321 *schedule = server_consensus_dl_schedule;
3322 *schedule_len = sizeof(server_consensus_dl_schedule)/sizeof(int);
3323 } else {
3324 *schedule = client_consensus_dl_schedule;
3325 *schedule_len = sizeof(client_consensus_dl_schedule)/sizeof(int);
3327 break;
3328 case DL_SCHED_BRIDGE:
3329 *schedule = bridge_dl_schedule;
3330 *schedule_len = sizeof(bridge_dl_schedule)/sizeof(int);
3331 break;
3332 default:
3333 tor_assert(0);
3337 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
3338 * <b>status_code</b>. Increment the failure count (if the code indicates a
3339 * real failure) and set <b>dls</b>-\>next_attempt_at to an appropriate time
3340 * in the future. */
3341 time_t
3342 download_status_increment_failure(download_status_t *dls, int status_code,
3343 const char *item, int server, time_t now)
3345 const int *schedule;
3346 size_t schedule_len;
3347 int increment;
3348 tor_assert(dls);
3349 if (status_code != 503 || server) {
3350 if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1)
3351 ++dls->n_download_failures;
3354 find_dl_schedule_and_len(dls, server, &schedule, &schedule_len);
3356 if (dls->n_download_failures < schedule_len)
3357 increment = schedule[dls->n_download_failures];
3358 else if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
3359 increment = INT_MAX;
3360 else
3361 increment = schedule[schedule_len-1];
3363 if (increment < INT_MAX)
3364 dls->next_attempt_at = now+increment;
3365 else
3366 dls->next_attempt_at = TIME_MAX;
3368 if (item) {
3369 if (increment == 0)
3370 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
3371 item, (int)dls->n_download_failures);
3372 else if (dls->next_attempt_at < TIME_MAX)
3373 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
3374 item, (int)dls->n_download_failures,
3375 (int)(dls->next_attempt_at-now));
3376 else
3377 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
3378 item, (int)dls->n_download_failures);
3380 return dls->next_attempt_at;
3383 /** Reset <b>dls</b> so that it will be considered downloadable
3384 * immediately, and/or to show that we don't need it anymore.
3386 * (We find the zeroth element of the download schedule, and set
3387 * next_attempt_at to be the appropriate offset from 'now'. In most
3388 * cases this means setting it to 'now', so the item will be immediately
3389 * downloadable; in the case of bridge descriptors, the zeroth element
3390 * is an hour from now.) */
3391 void
3392 download_status_reset(download_status_t *dls)
3394 const int *schedule;
3395 size_t schedule_len;
3397 find_dl_schedule_and_len(dls, get_options()->DirPort,
3398 &schedule, &schedule_len);
3400 dls->n_download_failures = 0;
3401 dls->next_attempt_at = time(NULL) + schedule[0];
3404 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
3405 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
3406 * either as descriptor digests or as identity digests based on
3407 * <b>was_descriptor_digests</b>).
3409 static void
3410 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
3411 int router_purpose,
3412 int was_extrainfo, int was_descriptor_digests)
3414 char digest[DIGEST_LEN];
3415 time_t now = time(NULL);
3416 int server = directory_fetches_from_authorities(get_options());
3417 if (!was_descriptor_digests) {
3418 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
3419 tor_assert(!was_extrainfo); /* not supported yet */
3420 SMARTLIST_FOREACH(failed, const char *, cp,
3422 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
3423 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
3424 escaped(cp));
3425 continue;
3427 retry_bridge_descriptor_fetch_directly(digest);
3430 return; /* FFFF should implement for other-than-router-purpose someday */
3432 SMARTLIST_FOREACH(failed, const char *, cp,
3434 download_status_t *dls = NULL;
3435 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) {
3436 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
3437 continue;
3439 if (was_extrainfo) {
3440 signed_descriptor_t *sd =
3441 router_get_by_extrainfo_digest(digest);
3442 if (sd)
3443 dls = &sd->ei_dl_status;
3444 } else {
3445 dls = router_get_dl_status_by_descriptor_digest(digest);
3447 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
3448 continue;
3449 download_status_increment_failure(dls, status_code, cp, server, now);
3452 /* No need to relaunch descriptor downloads here: we already do it
3453 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3456 /** Helper. Compare two fp_pair_t objects, and return -1, 0, or 1 as
3457 * appropriate. */
3458 static int
3459 _compare_pairs(const void **a, const void **b)
3461 const fp_pair_t *fp1 = *a, *fp2 = *b;
3462 int r;
3463 if ((r = memcmp(fp1->first, fp2->first, DIGEST_LEN)))
3464 return r;
3465 else
3466 return memcmp(fp1->second, fp2->second, DIGEST_LEN);
3469 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
3470 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
3471 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
3472 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
3474 dir_split_resource_into_fingerprint_pairs(const char *res,
3475 smartlist_t *pairs_out)
3477 smartlist_t *pairs_tmp = smartlist_create();
3478 smartlist_t *pairs_result = smartlist_create();
3480 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
3481 if (smartlist_len(pairs_tmp)) {
3482 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
3483 size_t last_len = strlen(last);
3484 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3485 last[last_len-2] = '\0';
3488 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
3489 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
3490 log_info(LD_DIR,
3491 "Skipping digest pair %s with non-standard length.", escaped(cp));
3492 } else if (cp[HEX_DIGEST_LEN] != '-') {
3493 log_info(LD_DIR,
3494 "Skipping digest pair %s with missing dash.", escaped(cp));
3495 } else {
3496 fp_pair_t pair;
3497 if (base16_decode(pair.first, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0 ||
3498 base16_decode(pair.second,
3499 DIGEST_LEN, cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN)<0) {
3500 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
3501 } else {
3502 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
3505 tor_free(cp);
3506 } SMARTLIST_FOREACH_END(cp);
3507 smartlist_free(pairs_tmp);
3509 /* Uniq-and-sort */
3510 smartlist_sort(pairs_result, _compare_pairs);
3511 smartlist_uniq(pairs_result, _compare_pairs, _tor_free);
3513 smartlist_add_all(pairs_out, pairs_result);
3514 smartlist_free(pairs_result);
3515 return 0;
3518 /** Given a directory <b>resource</b> request, containing zero
3519 * or more strings separated by plus signs, followed optionally by ".z", store
3520 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3521 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
3522 * decode_hex is true, then delete all elements that aren't hex digests, and
3523 * decode the rest. If sort_uniq is true, then sort the list and remove
3524 * all duplicates.
3527 dir_split_resource_into_fingerprints(const char *resource,
3528 smartlist_t *fp_out, int *compressed_out,
3529 int decode_hex, int sort_uniq)
3531 smartlist_t *fp_tmp = smartlist_create();
3532 tor_assert(fp_out);
3533 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
3534 if (compressed_out)
3535 *compressed_out = 0;
3536 if (smartlist_len(fp_tmp)) {
3537 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3538 size_t last_len = strlen(last);
3539 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3540 last[last_len-2] = '\0';
3541 if (compressed_out)
3542 *compressed_out = 1;
3545 if (decode_hex) {
3546 int i;
3547 char *cp, *d = NULL;
3548 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3549 cp = smartlist_get(fp_tmp, i);
3550 if (strlen(cp) != HEX_DIGEST_LEN) {
3551 log_info(LD_DIR,
3552 "Skipping digest %s with non-standard length.", escaped(cp));
3553 smartlist_del_keeporder(fp_tmp, i--);
3554 goto again;
3556 d = tor_malloc_zero(DIGEST_LEN);
3557 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
3558 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3559 smartlist_del_keeporder(fp_tmp, i--);
3560 goto again;
3562 smartlist_set(fp_tmp, i, d);
3563 d = NULL;
3564 again:
3565 tor_free(cp);
3566 tor_free(d);
3569 if (sort_uniq) {
3570 smartlist_t *fp_tmp2 = smartlist_create();
3571 int i;
3572 if (decode_hex)
3573 smartlist_sort_digests(fp_tmp);
3574 else
3575 smartlist_sort_strings(fp_tmp);
3576 if (smartlist_len(fp_tmp))
3577 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
3578 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
3579 char *cp = smartlist_get(fp_tmp, i);
3580 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
3582 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
3583 || (!decode_hex && strcasecmp(cp, last)))
3584 smartlist_add(fp_tmp2, cp);
3585 else
3586 tor_free(cp);
3588 smartlist_free(fp_tmp);
3589 fp_tmp = fp_tmp2;
3591 smartlist_add_all(fp_out, fp_tmp);
3592 smartlist_free(fp_tmp);
3593 return 0;