Revert "Backport fix for bug 997."
[tor/rransom.git] / src / or / directory.c
blobd783772eac691ea37955c0d43e37a42507668127
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2009, 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 (server_mode(options) && !options->Address))
686 return 0; /* We're firewalled or are acting like a relay -- also no. */
687 if (!options->TunnelDirConns &&
688 router_purpose != ROUTER_PURPOSE_BRIDGE)
689 return 0; /* We prefer to avoid using begindir conns. Fine. */
690 return 1;
693 /** Helper for directory_initiate_command_routerstatus: send the
694 * command to a server whose address is <b>address</b>, whose IP is
695 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
696 * <b>supports_begindir</b>, and whose identity key digest is
697 * <b>digest</b>. */
698 void
699 directory_initiate_command(const char *address, const tor_addr_t *_addr,
700 uint16_t or_port, uint16_t dir_port,
701 int supports_conditional_consensus,
702 int supports_begindir, const char *digest,
703 uint8_t dir_purpose, uint8_t router_purpose,
704 int anonymized_connection, const char *resource,
705 const char *payload, size_t payload_len,
706 time_t if_modified_since)
708 directory_initiate_command_rend(address, _addr, or_port, dir_port,
709 supports_conditional_consensus,
710 supports_begindir, digest, dir_purpose,
711 router_purpose, anonymized_connection,
712 resource, payload, payload_len,
713 if_modified_since, NULL);
716 /** Same as directory_initiate_command(), but accepts rendezvous data to
717 * fetch a hidden service descriptor. */
718 static void
719 directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
720 uint16_t or_port, uint16_t dir_port,
721 int supports_conditional_consensus,
722 int supports_begindir, const char *digest,
723 uint8_t dir_purpose, uint8_t router_purpose,
724 int anonymized_connection,
725 const char *resource,
726 const char *payload, size_t payload_len,
727 time_t if_modified_since,
728 const rend_data_t *rend_query)
730 dir_connection_t *conn;
731 or_options_t *options = get_options();
732 int socket_error = 0;
733 int use_begindir = supports_begindir &&
734 directory_command_should_use_begindir(options, _addr,
735 or_port, router_purpose, anonymized_connection);
736 tor_addr_t addr;
738 tor_assert(address);
739 tor_assert(_addr);
740 tor_assert(or_port || dir_port);
741 tor_assert(digest);
743 tor_addr_copy(&addr, _addr);
745 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
746 anonymized_connection, use_begindir);
748 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
750 conn = dir_connection_new(AF_INET);
752 /* set up conn so it's got all the data we need to remember */
753 tor_addr_copy(&conn->_base.addr, &addr);
754 conn->_base.port = use_begindir ? or_port : dir_port;
755 conn->_base.address = tor_strdup(address);
756 memcpy(conn->identity_digest, digest, DIGEST_LEN);
758 conn->_base.purpose = dir_purpose;
759 conn->router_purpose = router_purpose;
761 /* give it an initial state */
762 conn->_base.state = DIR_CONN_STATE_CONNECTING;
764 /* decide whether we can learn our IP address from this conn */
765 conn->dirconn_direct = !anonymized_connection;
767 /* copy rendezvous data, if any */
768 if (rend_query)
769 conn->rend_data = rend_data_dup(rend_query);
771 if (!anonymized_connection && !use_begindir) {
772 /* then we want to connect to dirport directly */
774 if (options->HttpProxy) {
775 tor_addr_from_ipv4h(&addr, options->HttpProxyAddr);
776 dir_port = options->HttpProxyPort;
779 switch (connection_connect(TO_CONN(conn), conn->_base.address, &addr,
780 dir_port, &socket_error)) {
781 case -1:
782 connection_dir_request_failed(conn); /* retry if we want */
783 /* XXX we only pass 'conn' above, not 'resource', 'payload',
784 * etc. So in many situations it can't retry! -RD */
785 connection_free(TO_CONN(conn));
786 return;
787 case 1:
788 /* start flushing conn */
789 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
790 /* fall through */
791 case 0:
792 /* queue the command on the outbuf */
793 directory_send_command(conn, dir_purpose, 1, resource,
794 payload, payload_len,
795 supports_conditional_consensus,
796 if_modified_since);
797 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
798 /* writable indicates finish, readable indicates broken link,
799 error indicates broken link in windowsland. */
801 } else { /* we want to connect via a tor connection */
802 edge_connection_t *linked_conn;
804 /* If it's an anonymized connection, remember the fact that we
805 * wanted it for later: maybe we'll want it again soon. */
806 if (anonymized_connection && use_begindir)
807 rep_hist_note_used_internal(time(NULL), 0, 1);
808 else if (anonymized_connection && !use_begindir)
809 rep_hist_note_used_port(time(NULL), conn->_base.port);
811 /* make an AP connection
812 * populate it and add it at the right state
813 * hook up both sides
815 linked_conn =
816 connection_ap_make_link(conn->_base.address, conn->_base.port,
817 digest, use_begindir, conn->dirconn_direct);
818 if (!linked_conn) {
819 log_warn(LD_NET,"Making tunnel to dirserver failed.");
820 connection_mark_for_close(TO_CONN(conn));
821 return;
823 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
825 if (connection_add(TO_CONN(conn)) < 0) {
826 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
827 connection_mark_for_close(TO_CONN(conn));
828 return;
830 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
831 /* queue the command on the outbuf */
832 directory_send_command(conn, dir_purpose, 0, resource,
833 payload, payload_len,
834 supports_conditional_consensus,
835 if_modified_since);
836 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
837 connection_start_reading(TO_CONN(linked_conn));
841 /** Return true iff anything we say on <b>conn</b> is being encrypted before
842 * we send it to the client/server. */
844 connection_dir_is_encrypted(dir_connection_t *conn)
846 /* Right now it's sufficient to see if conn is or has been linked, since
847 * the only thing it could be linked to is an edge connection on a
848 * circuit, and the only way it could have been unlinked is at the edge
849 * connection getting closed.
851 return TO_CONN(conn)->linked;
854 /** Helper for sorting
856 * sort strings alphabetically
858 static int
859 _compare_strs(const void **a, const void **b)
861 const char *s1 = *a, *s2 = *b;
862 return strcmp(s1, s2);
865 #define CONDITIONAL_CONSENSUS_FPR_LEN 3
866 #if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
867 #error "conditional consensus fingerprint length is larger than digest length"
868 #endif
870 /** Return the URL we should use for a consensus download.
872 * This url depends on whether or not the server we go to
873 * is sufficiently new to support conditional consensus downloading,
874 * i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
876 static char *
877 directory_get_consensus_url(int supports_conditional_consensus)
879 char *url;
880 int len;
882 if (supports_conditional_consensus) {
883 char *authority_id_list;
884 smartlist_t *authority_digets = smartlist_create();
886 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
887 trusted_dir_server_t *, ds,
889 char *hex;
890 if (!(ds->type & V3_AUTHORITY))
891 continue;
893 hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
894 base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
895 ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN);
896 smartlist_add(authority_digets, hex);
898 smartlist_sort(authority_digets, _compare_strs);
899 authority_id_list = smartlist_join_strings(authority_digets,
900 "+", 0, NULL);
902 len = strlen(authority_id_list)+64;
903 url = tor_malloc(len);
904 tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z",
905 authority_id_list);
907 SMARTLIST_FOREACH(authority_digets, char *, cp, tor_free(cp));
908 smartlist_free(authority_digets);
909 tor_free(authority_id_list);
910 } else {
911 url = tor_strdup("/tor/status-vote/current/consensus.z");
913 return url;
916 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
917 * are as in directory_initiate_command.
919 static void
920 directory_send_command(dir_connection_t *conn,
921 int purpose, int direct, const char *resource,
922 const char *payload, size_t payload_len,
923 int supports_conditional_consensus,
924 time_t if_modified_since)
926 char proxystring[256];
927 char proxyauthstring[256];
928 char hoststring[128];
929 char imsstring[RFC1123_TIME_LEN+32];
930 char *url;
931 char request[8192];
932 const char *httpcommand = NULL;
933 size_t len;
935 tor_assert(conn);
936 tor_assert(conn->_base.type == CONN_TYPE_DIR);
938 tor_free(conn->requested_resource);
939 if (resource)
940 conn->requested_resource = tor_strdup(resource);
942 /* come up with a string for which Host: we want */
943 if (conn->_base.port == 80) {
944 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
945 } else {
946 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
947 conn->_base.address, conn->_base.port);
950 /* Format if-modified-since */
951 if (!if_modified_since) {
952 imsstring[0] = '\0';
953 } else {
954 char b[RFC1123_TIME_LEN+1];
955 format_rfc1123_time(b, if_modified_since);
956 tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
959 /* come up with some proxy lines, if we're using one. */
960 if (direct && get_options()->HttpProxy) {
961 char *base64_authenticator=NULL;
962 const char *authenticator = get_options()->HttpProxyAuthenticator;
964 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
965 if (authenticator) {
966 base64_authenticator = alloc_http_authenticator(authenticator);
967 if (!base64_authenticator)
968 log_warn(LD_BUG, "Encoding http authenticator failed");
970 if (base64_authenticator) {
971 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
972 "\r\nProxy-Authorization: Basic %s",
973 base64_authenticator);
974 tor_free(base64_authenticator);
975 } else {
976 proxyauthstring[0] = 0;
978 } else {
979 proxystring[0] = 0;
980 proxyauthstring[0] = 0;
983 switch (purpose) {
984 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
985 tor_assert(resource);
986 httpcommand = "GET";
987 len = strlen(resource)+32;
988 url = tor_malloc(len);
989 tor_snprintf(url, len, "/tor/status/%s", resource);
990 break;
991 case DIR_PURPOSE_FETCH_CONSENSUS:
992 tor_assert(!resource);
993 tor_assert(!payload);
994 httpcommand = "GET";
995 url = directory_get_consensus_url(supports_conditional_consensus);
996 log_info(LD_DIR, "Downloading consensus from %s using %s",
997 hoststring, url);
998 break;
999 case DIR_PURPOSE_FETCH_CERTIFICATE:
1000 tor_assert(resource);
1001 tor_assert(!payload);
1002 httpcommand = "GET";
1003 len = strlen(resource)+32;
1004 url = tor_malloc(len);
1005 tor_snprintf(url, len, "/tor/keys/%s", resource);
1006 break;
1007 case DIR_PURPOSE_FETCH_STATUS_VOTE:
1008 tor_assert(resource);
1009 tor_assert(!payload);
1010 httpcommand = "GET";
1011 len = strlen(resource)+32;
1012 url = tor_malloc(len);
1013 tor_snprintf(url, len, "/tor/status-vote/next/%s.z", resource);
1014 break;
1015 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
1016 tor_assert(!resource);
1017 tor_assert(!payload);
1018 httpcommand = "GET";
1019 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
1020 break;
1021 case DIR_PURPOSE_FETCH_SERVERDESC:
1022 tor_assert(resource);
1023 httpcommand = "GET";
1024 len = strlen(resource)+32;
1025 url = tor_malloc(len);
1026 tor_snprintf(url, len, "/tor/server/%s", resource);
1027 break;
1028 case DIR_PURPOSE_FETCH_EXTRAINFO:
1029 tor_assert(resource);
1030 httpcommand = "GET";
1031 len = strlen(resource)+32;
1032 url = tor_malloc(len);
1033 tor_snprintf(url, len, "/tor/extra/%s", resource);
1034 break;
1035 case DIR_PURPOSE_UPLOAD_DIR:
1036 tor_assert(!resource);
1037 tor_assert(payload);
1038 httpcommand = "POST";
1039 url = tor_strdup("/tor/");
1040 break;
1041 case DIR_PURPOSE_UPLOAD_VOTE:
1042 tor_assert(!resource);
1043 tor_assert(payload);
1044 httpcommand = "POST";
1045 url = tor_strdup("/tor/post/vote");
1046 break;
1047 case DIR_PURPOSE_UPLOAD_SIGNATURES:
1048 tor_assert(!resource);
1049 tor_assert(payload);
1050 httpcommand = "POST";
1051 url = tor_strdup("/tor/post/consensus-signature");
1052 break;
1053 case DIR_PURPOSE_FETCH_RENDDESC:
1054 tor_assert(resource);
1055 tor_assert(!payload);
1057 /* this must be true or we wouldn't be doing the lookup */
1058 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN_BASE32);
1059 /* This breaks the function abstraction. */
1060 conn->rend_data = tor_malloc_zero(sizeof(rend_data_t));
1061 strlcpy(conn->rend_data->onion_address, resource,
1062 sizeof(conn->rend_data->onion_address));
1063 conn->rend_data->rend_desc_version = 0;
1065 httpcommand = "GET";
1066 /* Request the most recent versioned descriptor. */
1067 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
1068 // but that never got testing, and it wasn't a good design.)
1069 len = strlen(resource)+32;
1070 url = tor_malloc(len);
1071 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
1072 break;
1073 case DIR_PURPOSE_FETCH_RENDDESC_V2:
1074 tor_assert(resource);
1075 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
1076 tor_assert(!payload);
1077 conn->rend_data->rend_desc_version = 2;
1078 httpcommand = "GET";
1079 len = strlen(resource) + 32;
1080 url = tor_malloc(len);
1081 tor_snprintf(url, len, "/tor/rendezvous2/%s", resource);
1082 break;
1083 case DIR_PURPOSE_UPLOAD_RENDDESC:
1084 tor_assert(!resource);
1085 tor_assert(payload);
1086 httpcommand = "POST";
1087 url = tor_strdup("/tor/rendezvous/publish");
1088 break;
1089 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
1090 tor_assert(!resource);
1091 tor_assert(payload);
1092 httpcommand = "POST";
1093 url = tor_strdup("/tor/rendezvous2/publish");
1094 break;
1095 default:
1096 tor_assert(0);
1097 return;
1100 if (strlen(proxystring) + strlen(url) >= 4096) {
1101 log_warn(LD_BUG,
1102 "Squid does not like URLs longer than 4095 bytes, and this "
1103 "one is %d bytes long: %s%s",
1104 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
1107 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
1108 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1109 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
1110 tor_free(url);
1112 if (!strcmp(httpcommand, "GET") && !payload) {
1113 tor_snprintf(request, sizeof(request),
1114 " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
1115 hoststring,
1116 imsstring,
1117 proxyauthstring);
1118 } else {
1119 tor_snprintf(request, sizeof(request),
1120 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
1121 payload ? (unsigned long)payload_len : 0,
1122 hoststring,
1123 imsstring,
1124 proxyauthstring);
1126 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1128 if (payload) {
1129 /* then send the payload afterwards too */
1130 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
1134 /** Parse an HTTP request string <b>headers</b> of the form
1135 * \verbatim
1136 * "\%s [http[s]://]\%s HTTP/1..."
1137 * \endverbatim
1138 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
1139 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
1140 * so it does. Return 0.
1141 * Otherwise, return -1.
1143 static int
1144 parse_http_url(const char *headers, char **url)
1146 char *s, *start, *tmp;
1148 s = (char *)eat_whitespace_no_nl(headers);
1149 if (!*s) return -1;
1150 s = (char *)find_whitespace(s); /* get past GET/POST */
1151 if (!*s) return -1;
1152 s = (char *)eat_whitespace_no_nl(s);
1153 if (!*s) return -1;
1154 start = s; /* this is it, assuming it's valid */
1155 s = (char *)find_whitespace(start);
1156 if (!*s) return -1;
1158 /* tolerate the http[s] proxy style of putting the hostname in the url */
1159 if (s-start >= 4 && !strcmpstart(start,"http")) {
1160 tmp = start + 4;
1161 if (*tmp == 's')
1162 tmp++;
1163 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
1164 tmp = strchr(tmp+3, '/');
1165 if (tmp && tmp < s) {
1166 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
1167 start = tmp;
1172 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
1173 *url = tor_malloc(s - start + 5);
1174 strlcpy(*url,"/tor", s-start+5);
1175 strlcat((*url)+4, start, s-start+1);
1176 } else {
1177 *url = tor_strndup(start, s-start);
1179 return 0;
1182 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1183 * <b>which</b>. The key should be given with a terminating colon and space;
1184 * this function copies everything after, up to but not including the
1185 * following \\r\\n. */
1186 static char *
1187 http_get_header(const char *headers, const char *which)
1189 const char *cp = headers;
1190 while (cp) {
1191 if (!strcasecmpstart(cp, which)) {
1192 char *eos;
1193 cp += strlen(which);
1194 if ((eos = strchr(cp,'\r')))
1195 return tor_strndup(cp, eos-cp);
1196 else
1197 return tor_strdup(cp);
1199 cp = strchr(cp, '\n');
1200 if (cp)
1201 ++cp;
1203 return NULL;
1206 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1207 * <b>conn</b>-\>address to describe our best guess of the address that
1208 * originated this HTTP request. */
1209 static void
1210 http_set_address_origin(const char *headers, connection_t *conn)
1212 char *fwd;
1214 fwd = http_get_header(headers, "Forwarded-For: ");
1215 if (!fwd)
1216 fwd = http_get_header(headers, "X-Forwarded-For: ");
1217 if (fwd) {
1218 struct in_addr in;
1219 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
1220 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
1221 escaped(fwd));
1222 tor_free(fwd);
1223 return;
1225 tor_free(conn->address);
1226 conn->address = tor_strdup(fwd);
1227 tor_free(fwd);
1231 /** Parse an HTTP response string <b>headers</b> of the form
1232 * \verbatim
1233 * "HTTP/1.\%d \%d\%s\r\n...".
1234 * \endverbatim
1236 * If it's well-formed, assign the status code to *<b>code</b> and
1237 * return 0. Otherwise, return -1.
1239 * On success: If <b>date</b> is provided, set *date to the Date
1240 * header in the http headers, or 0 if no such header is found. If
1241 * <b>compression</b> is provided, set *<b>compression</b> to the
1242 * compression method given in the Content-Encoding header, or 0 if no
1243 * such header is found, or -1 if the value of the header is not
1244 * recognized. If <b>reason</b> is provided, strdup the reason string
1245 * into it.
1248 parse_http_response(const char *headers, int *code, time_t *date,
1249 compress_method_t *compression, char **reason)
1251 unsigned n1, n2;
1252 char datestr[RFC1123_TIME_LEN+1];
1253 smartlist_t *parsed_headers;
1254 tor_assert(headers);
1255 tor_assert(code);
1257 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1259 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
1260 (n1 != 0 && n1 != 1) ||
1261 (n2 < 100 || n2 >= 600)) {
1262 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1263 return -1;
1265 *code = n2;
1267 parsed_headers = smartlist_create();
1268 smartlist_split_string(parsed_headers, headers, "\n",
1269 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1270 if (reason) {
1271 smartlist_t *status_line_elements = smartlist_create();
1272 tor_assert(smartlist_len(parsed_headers));
1273 smartlist_split_string(status_line_elements,
1274 smartlist_get(parsed_headers, 0),
1275 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1276 tor_assert(smartlist_len(status_line_elements) <= 3);
1277 if (smartlist_len(status_line_elements) == 3) {
1278 *reason = smartlist_get(status_line_elements, 2);
1279 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1281 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1282 smartlist_free(status_line_elements);
1284 if (date) {
1285 *date = 0;
1286 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1287 if (!strcmpstart(s, "Date: ")) {
1288 strlcpy(datestr, s+6, sizeof(datestr));
1289 /* This will do nothing on failure, so we don't need to check
1290 the result. We shouldn't warn, since there are many other valid
1291 date formats besides the one we use. */
1292 parse_rfc1123_time(datestr, date);
1293 break;
1296 if (compression) {
1297 const char *enc = NULL;
1298 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1299 if (!strcmpstart(s, "Content-Encoding: ")) {
1300 enc = s+18; break;
1302 if (!enc || !strcmp(enc, "identity")) {
1303 *compression = NO_METHOD;
1304 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1305 *compression = ZLIB_METHOD;
1306 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1307 *compression = GZIP_METHOD;
1308 } else {
1309 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1310 escaped(enc));
1311 *compression = UNKNOWN_METHOD;
1314 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1315 smartlist_free(parsed_headers);
1317 return 0;
1320 /** Return true iff <b>body</b> doesn't start with a plausible router or
1321 * running-list or directory opening. This is a sign of possible compression.
1323 static int
1324 body_is_plausible(const char *body, size_t len, int purpose)
1326 int i;
1327 if (len == 0)
1328 return 1; /* empty bodies don't need decompression */
1329 if (len < 32)
1330 return 0;
1331 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
1332 if (!strcmpstart(body,"router") ||
1333 !strcmpstart(body,"signed-directory") ||
1334 !strcmpstart(body,"network-status") ||
1335 !strcmpstart(body,"running-routers"))
1336 return 1;
1337 for (i=0;i<32;++i) {
1338 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1339 return 0;
1341 return 1;
1342 } else {
1343 return 1;
1347 /** Called when we've just fetched a bunch of router descriptors in
1348 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1349 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1350 * is true, or identity digests otherwise. Parse the descriptors, validate
1351 * them, and annotate them as having purpose <b>purpose</b> and as having been
1352 * downloaded from <b>source</b>.
1354 * Return the number of routers actually added. */
1355 static int
1356 load_downloaded_routers(const char *body, smartlist_t *which,
1357 int descriptor_digests,
1358 int router_purpose,
1359 const char *source)
1361 char buf[256];
1362 char time_buf[ISO_TIME_LEN+1];
1363 int added = 0;
1364 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1365 format_iso_time(time_buf, time(NULL));
1366 tor_assert(source);
1368 if (tor_snprintf(buf, sizeof(buf),
1369 "@downloaded-at %s\n"
1370 "@source %s\n"
1371 "%s%s%s", time_buf, escaped(source),
1372 !general ? "@purpose " : "",
1373 !general ? router_purpose_to_string(router_purpose) : "",
1374 !general ? "\n" : "")<0)
1375 return added;
1377 added = router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1378 descriptor_digests, buf);
1379 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
1380 count_loading_descriptors_progress());
1381 return added;
1384 /** We are a client, and we've finished reading the server's
1385 * response. Parse it and act appropriately.
1387 * If we're still happy with using this directory server in the future, return
1388 * 0. Otherwise return -1; and the caller should consider trying the request
1389 * again.
1391 * The caller will take care of marking the connection for close.
1393 static int
1394 connection_dir_client_reached_eof(dir_connection_t *conn)
1396 char *body;
1397 char *headers;
1398 char *reason = NULL;
1399 size_t body_len=0, orig_len=0;
1400 int status_code;
1401 time_t date_header=0;
1402 long delta;
1403 compress_method_t compression;
1404 int plausible;
1405 int skewed=0;
1406 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1407 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
1408 int was_compressed=0;
1409 time_t now = time(NULL);
1411 switch (fetch_from_buf_http(conn->_base.inbuf,
1412 &headers, MAX_HEADERS_SIZE,
1413 &body, &body_len, MAX_DIR_DL_SIZE,
1414 allow_partial)) {
1415 case -1: /* overflow */
1416 log_warn(LD_PROTOCOL,
1417 "'fetch' response too large (server '%s:%d'). Closing.",
1418 conn->_base.address, conn->_base.port);
1419 return -1;
1420 case 0:
1421 log_info(LD_HTTP,
1422 "'fetch' response not all here, but we're at eof. Closing.");
1423 return -1;
1424 /* case 1, fall through */
1426 orig_len = body_len;
1428 if (parse_http_response(headers, &status_code, &date_header,
1429 &compression, &reason) < 0) {
1430 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1431 conn->_base.address, conn->_base.port);
1432 tor_free(body); tor_free(headers);
1433 return -1;
1435 if (!reason) reason = tor_strdup("[no reason given]");
1437 log_debug(LD_DIR,
1438 "Received response from directory server '%s:%d': %d %s",
1439 conn->_base.address, conn->_base.port, status_code,
1440 escaped(reason));
1442 /* now check if it's got any hints for us about our IP address. */
1443 if (conn->dirconn_direct) {
1444 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1445 if (guess) {
1446 router_new_address_suggestion(guess, conn);
1447 tor_free(guess);
1451 if (date_header > 0) {
1452 /* The date header was written very soon after we sent our request,
1453 * so compute the skew as the difference between sending the request
1454 * and the date header. (We used to check now-date_header, but that's
1455 * inaccurate if we spend a lot of time downloading.)
1457 delta = conn->_base.timestamp_lastwritten - date_header;
1458 if (labs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1459 char dbuf[64];
1460 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1461 format_time_interval(dbuf, sizeof(dbuf), delta);
1462 log_fn(trusted ? LOG_WARN : LOG_INFO,
1463 LD_HTTP,
1464 "Received directory with skewed time (server '%s:%d'): "
1465 "It seems that our clock is %s by %s, or that theirs is %s. "
1466 "Tor requires an accurate clock to work: please check your time, "
1467 "timezone, and date settings.",
1468 conn->_base.address, conn->_base.port,
1469 delta>0 ? "ahead" : "behind", dbuf,
1470 delta>0 ? "behind" : "ahead");
1471 skewed = 1; /* don't check the recommended-versions line */
1472 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1473 "CLOCK_SKEW SKEW=%ld SOURCE=DIRSERV:%s:%d",
1474 delta, conn->_base.address, conn->_base.port);
1475 } else {
1476 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1477 "we are %ld seconds skewed. (That's okay.)", delta);
1480 (void) skewed; /* skewed isn't used yet. */
1482 if (status_code == 503 && body_len < 16) {
1483 routerstatus_t *rs;
1484 trusted_dir_server_t *ds;
1485 log_info(LD_DIR,"Received http status code %d (%s) from server "
1486 "'%s:%d'. I'll try again soon.",
1487 status_code, escaped(reason), conn->_base.address,
1488 conn->_base.port);
1489 if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
1490 rs->last_dir_503_at = now;
1491 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1492 ds->fake_status.last_dir_503_at = now;
1494 tor_free(body); tor_free(headers); tor_free(reason);
1495 return -1;
1496 } else if (status_code == 503) {
1497 /* XXXX022 Remove this once every server with bug 539 is obsolete. */
1498 log_info(LD_DIR, "Server at '%s:%d' sent us a 503 response, but included "
1499 "a body anyway. We'll pretend it gave us a 200.",
1500 conn->_base.address, conn->_base.port);
1501 status_code = 200;
1504 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1505 if (compression != NO_METHOD || !plausible) {
1506 char *new_body = NULL;
1507 size_t new_len = 0;
1508 compress_method_t guessed = detect_compression_method(body, body_len);
1509 if (compression == UNKNOWN_METHOD || guessed != compression) {
1510 /* Tell the user if we don't believe what we're told about compression.*/
1511 const char *description1, *description2;
1512 if (compression == ZLIB_METHOD)
1513 description1 = "as deflated";
1514 else if (compression == GZIP_METHOD)
1515 description1 = "as gzipped";
1516 else if (compression == NO_METHOD)
1517 description1 = "as uncompressed";
1518 else
1519 description1 = "with an unknown Content-Encoding";
1520 if (guessed == ZLIB_METHOD)
1521 description2 = "deflated";
1522 else if (guessed == GZIP_METHOD)
1523 description2 = "gzipped";
1524 else if (!plausible)
1525 description2 = "confusing binary junk";
1526 else
1527 description2 = "uncompressed";
1529 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1530 "but it seems to be %s.%s",
1531 conn->_base.address, conn->_base.port, description1,
1532 description2,
1533 (compression>0 && guessed>0)?" Trying both.":"");
1535 /* Try declared compression first if we can. */
1536 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1537 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1538 !allow_partial, LOG_PROTOCOL_WARN);
1539 /* Okay, if that didn't work, and we think that it was compressed
1540 * differently, try that. */
1541 if (!new_body &&
1542 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1543 compression != guessed)
1544 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1545 !allow_partial, LOG_PROTOCOL_WARN);
1546 /* If we're pretty sure that we have a compressed directory, and
1547 * we didn't manage to uncompress it, then warn and bail. */
1548 if (!plausible && !new_body) {
1549 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1550 "Unable to decompress HTTP body (server '%s:%d').",
1551 conn->_base.address, conn->_base.port);
1552 tor_free(body); tor_free(headers); tor_free(reason);
1553 return -1;
1555 if (new_body) {
1556 tor_free(body);
1557 body = new_body;
1558 body_len = new_len;
1559 was_compressed = 1;
1563 if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
1564 smartlist_t *which = NULL;
1565 v2_networkstatus_source_t source;
1566 char *cp;
1567 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1568 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1569 if (status_code != 200) {
1570 log_warn(LD_DIR,
1571 "Received http status code %d (%s) from server "
1572 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1573 status_code, escaped(reason), conn->_base.address,
1574 conn->_base.port, conn->requested_resource);
1575 tor_free(body); tor_free(headers); tor_free(reason);
1576 connection_dir_download_networkstatus_failed(conn, status_code);
1577 return -1;
1579 if (conn->requested_resource &&
1580 !strcmpstart(conn->requested_resource,"fp/")) {
1581 source = NS_FROM_DIR_BY_FP;
1582 which = smartlist_create();
1583 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1584 which, NULL, 0, 0);
1585 } else if (conn->requested_resource &&
1586 !strcmpstart(conn->requested_resource, "all")) {
1587 source = NS_FROM_DIR_ALL;
1588 which = smartlist_create();
1589 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1590 trusted_dir_server_t *, ds,
1592 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1593 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1594 smartlist_add(which, hex);
1596 } else {
1597 /* XXXX Can we even end up here? -- weasel*/
1598 source = NS_FROM_DIR_BY_FP;
1599 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1600 "for it by fp, nor did we ask for all.");
1602 cp = body;
1603 while (*cp) {
1604 char *next = strstr(cp, "\nnetwork-status-version");
1605 if (next)
1606 next[1] = '\0';
1607 /* learn from it, and then remove it from 'which' */
1608 if (router_set_networkstatus_v2(cp, now, source, which)<0)
1609 break;
1610 if (next) {
1611 next[1] = 'n';
1612 cp = next+1;
1613 } else
1614 break;
1616 /* launches router downloads as needed */
1617 routers_update_all_from_networkstatus(now, 2);
1618 directory_info_has_arrived(now, 0);
1619 if (which) {
1620 if (smartlist_len(which)) {
1621 dir_networkstatus_download_failed(which, status_code);
1623 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1624 smartlist_free(which);
1628 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1629 int r;
1630 if (status_code != 200) {
1631 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1632 log(severity, LD_DIR,
1633 "Received http status code %d (%s) from server "
1634 "'%s:%d' while fetching consensus directory.",
1635 status_code, escaped(reason), conn->_base.address,
1636 conn->_base.port);
1637 tor_free(body); tor_free(headers); tor_free(reason);
1638 networkstatus_consensus_download_failed(status_code);
1639 return -1;
1641 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1642 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1643 if ((r=networkstatus_set_current_consensus(body, 0))<0) {
1644 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1645 "Unable to load consensus directory downloaded from "
1646 "server '%s:%d'. I'll try again soon.",
1647 conn->_base.address, conn->_base.port);
1648 tor_free(body); tor_free(headers); tor_free(reason);
1649 networkstatus_consensus_download_failed(0);
1650 return -1;
1652 /* launches router downloads as needed */
1653 routers_update_all_from_networkstatus(now, 3);
1654 directory_info_has_arrived(now, 0);
1655 log_info(LD_DIR, "Successfully loaded consensus.");
1658 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1659 if (status_code != 200) {
1660 log_warn(LD_DIR,
1661 "Received http status code %d (%s) from server "
1662 "'%s:%d' while fetching \"/tor/keys/%s\".",
1663 status_code, escaped(reason), conn->_base.address,
1664 conn->_base.port, conn->requested_resource);
1665 connection_dir_download_cert_failed(conn, status_code);
1666 tor_free(body); tor_free(headers); tor_free(reason);
1667 return -1;
1669 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1670 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1671 if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) {
1672 log_warn(LD_DIR, "Unable to parse fetched certificates");
1673 connection_dir_download_cert_failed(conn, status_code);
1674 } else {
1675 directory_info_has_arrived(now, 0);
1676 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1679 if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1680 const char *msg;
1681 int st;
1682 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1683 (int) body_len, conn->_base.address, conn->_base.port);
1684 if (status_code != 200) {
1685 log_warn(LD_DIR,
1686 "Received http status code %d (%s) from server "
1687 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1688 status_code, escaped(reason), conn->_base.address,
1689 conn->_base.port, conn->requested_resource);
1690 tor_free(body); tor_free(headers); tor_free(reason);
1691 return -1;
1693 dirvote_add_vote(body, &msg, &st);
1694 if (st > 299) {
1695 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1696 } else {
1697 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1700 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1701 const char *msg = NULL;
1702 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1703 (int) body_len, conn->_base.address, conn->_base.port);
1704 if (status_code != 200) {
1705 log_warn(LD_DIR,
1706 "Received http status code %d (%s) from server "
1707 "'%s:%d' while fetching \"/tor/status-vote/consensus-signatures.z\".",
1708 status_code, escaped(reason), conn->_base.address,
1709 conn->_base.port);
1710 tor_free(body); tor_free(headers); tor_free(reason);
1711 return -1;
1713 if (dirvote_add_signatures(body, conn->_base.address, &msg)<0) {
1714 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1715 conn->_base.address, conn->_base.port, msg?msg:"???");
1719 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1720 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1721 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1722 smartlist_t *which = NULL;
1723 int n_asked_for = 0;
1724 int descriptor_digests = conn->requested_resource &&
1725 !strcmpstart(conn->requested_resource,"d/");
1726 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1727 was_ei ? "extra server info" : "server info",
1728 (int)body_len, conn->_base.address, conn->_base.port);
1729 if (conn->requested_resource &&
1730 (!strcmpstart(conn->requested_resource,"d/") ||
1731 !strcmpstart(conn->requested_resource,"fp/"))) {
1732 which = smartlist_create();
1733 dir_split_resource_into_fingerprints(conn->requested_resource +
1734 (descriptor_digests ? 2 : 3),
1735 which, NULL, 0, 0);
1736 n_asked_for = smartlist_len(which);
1738 if (status_code != 200) {
1739 int dir_okay = status_code == 404 ||
1740 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1741 /* 404 means that it didn't have them; no big deal.
1742 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1743 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1744 "Received http status code %d (%s) from server '%s:%d' "
1745 "while fetching \"/tor/server/%s\". I'll try again soon.",
1746 status_code, escaped(reason), conn->_base.address,
1747 conn->_base.port, conn->requested_resource);
1748 if (!which) {
1749 connection_dir_download_routerdesc_failed(conn);
1750 } else {
1751 dir_routerdesc_download_failed(which, status_code,
1752 conn->router_purpose,
1753 was_ei, descriptor_digests);
1754 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1755 smartlist_free(which);
1757 tor_free(body); tor_free(headers); tor_free(reason);
1758 return dir_okay ? 0 : -1;
1760 /* Learn the routers, assuming we requested by fingerprint or "all"
1761 * or "authority".
1763 * We use "authority" to fetch our own descriptor for
1764 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1765 * the output of "authority" requests unless we are using bridges,
1766 * since otherwise they'll be the response from reachability tests,
1767 * and we don't really want to add that to our routerlist. */
1768 if (which || (conn->requested_resource &&
1769 (!strcmpstart(conn->requested_resource, "all") ||
1770 (!strcmpstart(conn->requested_resource, "authority") &&
1771 get_options()->UseBridges)))) {
1772 /* as we learn from them, we remove them from 'which' */
1773 if (was_ei) {
1774 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1775 descriptor_digests);
1776 } else {
1777 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1778 // descriptor_digests, conn->router_purpose);
1779 if (load_downloaded_routers(body, which, descriptor_digests,
1780 conn->router_purpose,
1781 conn->_base.address))
1782 directory_info_has_arrived(now, 0);
1785 if (which) { /* mark remaining ones as failed */
1786 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1787 n_asked_for-smartlist_len(which), n_asked_for,
1788 was_ei ? "extra-info documents" : "router descriptors",
1789 conn->_base.address, (int)conn->_base.port);
1790 if (smartlist_len(which)) {
1791 dir_routerdesc_download_failed(which, status_code,
1792 conn->router_purpose,
1793 was_ei, descriptor_digests);
1795 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1796 smartlist_free(which);
1798 if (directory_conn_is_self_reachability_test(conn))
1799 router_dirport_found_reachable();
1802 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1803 switch (status_code) {
1804 case 200: {
1805 trusted_dir_server_t *ds =
1806 router_get_trusteddirserver_by_digest(conn->identity_digest);
1807 char *rejected_hdr = http_get_header(headers,
1808 "X-Descriptor-Not-New: ");
1809 int rejected = 0;
1810 if (rejected_hdr) {
1811 if (!strcmp(rejected_hdr, "Yes")) {
1812 log_info(LD_GENERAL,
1813 "Authority '%s' declined our descriptor (not new)",
1814 ds->nickname);
1815 /* XXXX use this information; be sure to upload next one
1816 * sooner. -NM */
1817 /* XXXX021 On further thought, the task above implies that we're
1818 * basing our regenerate-descriptor time on when we uploaded the
1819 * last descriptor, not on the published time of the last
1820 * descriptor. If those are different, that's a bad thing to
1821 * do. -NM */
1822 rejected = 1;
1824 tor_free(rejected_hdr);
1826 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1827 "descriptor: finished.");
1828 control_event_server_status(
1829 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1830 conn->_base.address, conn->_base.port);
1832 ds->has_accepted_serverdesc = 1;
1833 if (directories_have_accepted_server_descriptor())
1834 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1836 break;
1837 case 400:
1838 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1839 "dirserver '%s:%d'. Please correct.",
1840 escaped(reason), conn->_base.address, conn->_base.port);
1841 control_event_server_status(LOG_WARN,
1842 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1843 conn->_base.address, conn->_base.port, escaped(reason));
1844 break;
1845 default:
1846 log_warn(LD_GENERAL,
1847 "http status %d (%s) reason unexpected while uploading "
1848 "descriptor to server '%s:%d').",
1849 status_code, escaped(reason), conn->_base.address,
1850 conn->_base.port);
1851 break;
1853 /* return 0 in all cases, since we don't want to mark any
1854 * dirservers down just because they don't like us. */
1857 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
1858 switch (status_code) {
1859 case 200: {
1860 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
1861 conn->_base.address, conn->_base.port);
1863 break;
1864 case 400:
1865 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1866 "vote to dirserver '%s:%d'. Please correct.",
1867 escaped(reason), conn->_base.address, conn->_base.port);
1868 break;
1869 default:
1870 log_warn(LD_GENERAL,
1871 "http status %d (%s) reason unexpected while uploading "
1872 "vote to server '%s:%d').",
1873 status_code, escaped(reason), conn->_base.address,
1874 conn->_base.port);
1875 break;
1877 /* return 0 in all cases, since we don't want to mark any
1878 * dirservers down just because they don't like us. */
1881 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
1882 switch (status_code) {
1883 case 200: {
1884 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
1885 conn->_base.address, conn->_base.port);
1887 break;
1888 case 400:
1889 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1890 "signatures to dirserver '%s:%d'. Please correct.",
1891 escaped(reason), conn->_base.address, conn->_base.port);
1892 break;
1893 default:
1894 log_warn(LD_GENERAL,
1895 "http status %d (%s) reason unexpected while uploading "
1896 "signatures to server '%s:%d').",
1897 status_code, escaped(reason), conn->_base.address,
1898 conn->_base.port);
1899 break;
1901 /* return 0 in all cases, since we don't want to mark any
1902 * dirservers down just because they don't like us. */
1905 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1906 tor_assert(conn->rend_data);
1907 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1908 "(%s))",
1909 (int)body_len, status_code, escaped(reason));
1910 switch (status_code) {
1911 case 200:
1912 if (rend_cache_store(body, body_len, 0) < -1) {
1913 log_warn(LD_REND,"Failed to parse rendezvous descriptor.");
1914 /* Any pending rendezvous attempts will notice when
1915 * connection_about_to_close_connection()
1916 * cleans this dir conn up. */
1917 /* We could retry. But since v0 descriptors are going out of
1918 * style, it isn't worth the hassle. We'll do better in v2. */
1919 } else {
1920 /* Success, or at least there's a v2 descriptor already
1921 * present. Notify pending connections about this. */
1922 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1923 rend_client_desc_trynow(conn->rend_data->onion_address, -1);
1925 break;
1926 case 404:
1927 /* Not there. Pending connections will be notified when
1928 * connection_about_to_close_connection() cleans this conn up. */
1929 break;
1930 case 400:
1931 log_warn(LD_REND,
1932 "http status 400 (%s). Dirserver didn't like our "
1933 "rendezvous query?", escaped(reason));
1934 break;
1935 default:
1936 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1937 "fetching hidden service descriptor (server '%s:%d').",
1938 status_code, escaped(reason), conn->_base.address,
1939 conn->_base.port);
1940 break;
1944 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
1945 tor_assert(conn->rend_data);
1946 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1947 "(%s))",
1948 (int)body_len, status_code, escaped(reason));
1949 switch (status_code) {
1950 case 200:
1951 switch (rend_cache_store_v2_desc_as_client(body, conn->rend_data)) {
1952 case -2:
1953 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
1954 "Retrying at another directory.");
1955 /* We'll retry when connection_about_to_close_connection()
1956 * cleans this dir conn up. */
1957 break;
1958 case -1:
1959 /* We already have a v0 descriptor here. Ignoring this one
1960 * and _not_ performing another request. */
1961 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1962 "descriptor, but we already have a v0 descriptor.");
1963 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1964 break;
1965 default:
1966 /* success. notify pending connections about this. */
1967 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1968 "descriptor.");
1969 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1970 rend_client_desc_trynow(conn->rend_data->onion_address, -1);
1971 break;
1973 break;
1974 case 404:
1975 /* Not there. We'll retry when
1976 * connection_about_to_close_connection() cleans this conn up. */
1977 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
1978 "Retrying at another directory.");
1979 break;
1980 case 400:
1981 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1982 "http status 400 (%s). Dirserver didn't like our "
1983 "v2 rendezvous query? Retrying at another directory.",
1984 escaped(reason));
1985 break;
1986 default:
1987 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1988 "http status %d (%s) response unexpected while "
1989 "fetching v2 hidden service descriptor (server '%s:%d'). "
1990 "Retrying at another directory.",
1991 status_code, escaped(reason), conn->_base.address,
1992 conn->_base.port);
1993 break;
1997 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
1998 conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
1999 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
2000 "(%s))",
2001 status_code, escaped(reason));
2002 switch (status_code) {
2003 case 200:
2004 log_info(LD_REND,
2005 "Uploading rendezvous descriptor: finished with status "
2006 "200 (%s)", escaped(reason));
2007 break;
2008 case 400:
2009 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
2010 "'%s:%d'. Malformed rendezvous descriptor?",
2011 escaped(reason), conn->_base.address, conn->_base.port);
2012 break;
2013 case 503:
2014 log_info(LD_REND,"http status 503 (%s) response from dirserver "
2015 "'%s:%d'. Node is (currently) not acting as v2 hidden "
2016 "service directory.",
2017 escaped(reason), conn->_base.address, conn->_base.port);
2018 break;
2019 default:
2020 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
2021 "'%s:%d').",
2022 status_code, escaped(reason), conn->_base.address,
2023 conn->_base.port);
2024 break;
2027 note_client_request(conn->_base.purpose, was_compressed, orig_len);
2028 tor_free(body); tor_free(headers); tor_free(reason);
2029 return 0;
2032 /** Called when a directory connection reaches EOF. */
2034 connection_dir_reached_eof(dir_connection_t *conn)
2036 int retval;
2037 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
2038 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
2039 conn->_base.state);
2040 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
2041 connection_mark_for_close(TO_CONN(conn));
2042 return -1;
2045 retval = connection_dir_client_reached_eof(conn);
2046 if (retval == 0) /* success */
2047 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
2048 connection_mark_for_close(TO_CONN(conn));
2049 return retval;
2052 /** If any directory object is arriving, and it's over 10MB large, we're
2053 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
2054 * ask for more than 96 router descriptors at a time.)
2056 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
2058 /** Read handler for directory connections. (That's connections <em>to</em>
2059 * directory servers and connections <em>at</em> directory servers.)
2062 connection_dir_process_inbuf(dir_connection_t *conn)
2064 tor_assert(conn);
2065 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2067 /* Directory clients write, then read data until they receive EOF;
2068 * directory servers read data until they get an HTTP command, then
2069 * write their response (when it's finished flushing, they mark for
2070 * close).
2073 /* If we're on the dirserver side, look for a command. */
2074 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
2075 if (directory_handle_command(conn) < 0) {
2076 connection_mark_for_close(TO_CONN(conn));
2077 return -1;
2079 return 0;
2082 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
2083 log_warn(LD_HTTP, "Too much data received from directory connection: "
2084 "denial of service attempt, or you need to upgrade?");
2085 connection_mark_for_close(TO_CONN(conn));
2086 return -1;
2089 if (!conn->_base.inbuf_reached_eof)
2090 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
2091 return 0;
2094 /** Create an http response for the client <b>conn</b> out of
2095 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
2097 static void
2098 write_http_status_line(dir_connection_t *conn, int status,
2099 const char *reason_phrase)
2101 char buf[256];
2102 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
2103 status, reason_phrase ? reason_phrase : "OK") < 0) {
2104 log_warn(LD_BUG,"status line too long.");
2105 return;
2107 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
2110 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
2111 * with <b>type</b> as the Content-Type.
2113 * If <b>length</b> is nonnegative, it is the Content-Length.
2114 * If <b>encoding</b> is provided, it is the Content-Encoding.
2115 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
2116 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
2117 static void
2118 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
2119 const char *type, const char *encoding,
2120 const char *extra_headers,
2121 long cache_lifetime)
2123 char date[RFC1123_TIME_LEN+1];
2124 char tmp[1024];
2125 char *cp;
2126 time_t now = time(NULL);
2128 tor_assert(conn);
2130 format_rfc1123_time(date, now);
2131 cp = tmp;
2132 tor_snprintf(cp, sizeof(tmp),
2133 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
2134 date);
2135 cp += strlen(tmp);
2136 if (type) {
2137 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
2138 cp += strlen(cp);
2140 if (!is_local_addr(&conn->_base.addr)) {
2141 /* Don't report the source address for a nearby/private connection.
2142 * Otherwise we tend to mis-report in cases where incoming ports are
2143 * being forwarded to a Tor server running behind the firewall. */
2144 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2145 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
2146 cp += strlen(cp);
2148 if (encoding) {
2149 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2150 "Content-Encoding: %s\r\n", encoding);
2151 cp += strlen(cp);
2153 if (length >= 0) {
2154 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2155 "Content-Length: %ld\r\n", (long)length);
2156 cp += strlen(cp);
2158 if (cache_lifetime > 0) {
2159 char expbuf[RFC1123_TIME_LEN+1];
2160 format_rfc1123_time(expbuf, now + cache_lifetime);
2161 /* We could say 'Cache-control: max-age=%d' here if we start doing
2162 * http/1.1 */
2163 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2164 "Expires: %s\r\n", expbuf);
2165 cp += strlen(cp);
2166 } else if (cache_lifetime == 0) {
2167 /* We could say 'Cache-control: no-cache' here if we start doing
2168 * http/1.1 */
2169 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2170 cp += strlen(cp);
2172 if (extra_headers) {
2173 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2174 cp += strlen(cp);
2176 if (sizeof(tmp)-(cp-tmp) > 3)
2177 memcpy(cp, "\r\n", 3);
2178 else
2179 tor_assert(0);
2180 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2183 /** As write_http_response_header_impl, but sets encoding and content-typed
2184 * based on whether the response will be <b>compressed</b> or not. */
2185 static void
2186 write_http_response_header(dir_connection_t *conn, ssize_t length,
2187 int compressed, long cache_lifetime)
2189 write_http_response_header_impl(conn, length,
2190 compressed?"application/octet-stream":"text/plain",
2191 compressed?"deflate":"identity",
2192 NULL,
2193 cache_lifetime);
2196 #ifdef INSTRUMENT_DOWNLOADS
2197 typedef struct request_t {
2198 uint64_t bytes; /**< How many bytes have we transferred? */
2199 uint64_t count; /**< How many requests have we made? */
2200 } request_t;
2202 /** Map used to keep track of how much data we've up/downloaded in what kind
2203 * of request. Maps from request type to pointer to request_t. */
2204 static strmap_t *request_map = NULL;
2206 /** Record that a client request of <b>purpose</b> was made, and that
2207 * <b>bytes</b> bytes of possibly <b>compressed</b> data were sent/received.
2208 * Used to keep track of how much we've up/downloaded in what kind of
2209 * request. */
2210 static void
2211 note_client_request(int purpose, int compressed, size_t bytes)
2213 char *key;
2214 const char *kind = NULL;
2215 switch (purpose) {
2216 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS: kind = "dl/status"; break;
2217 case DIR_PURPOSE_FETCH_CONSENSUS: kind = "dl/consensus"; break;
2218 case DIR_PURPOSE_FETCH_CERTIFICATE: kind = "dl/cert"; break;
2219 case DIR_PURPOSE_FETCH_STATUS_VOTE: kind = "dl/vote"; break;
2220 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: kind = "dl/detached_sig";
2221 break;
2222 case DIR_PURPOSE_FETCH_SERVERDESC: kind = "dl/server"; break;
2223 case DIR_PURPOSE_FETCH_EXTRAINFO: kind = "dl/extra"; break;
2224 case DIR_PURPOSE_UPLOAD_DIR: kind = "dl/ul-dir"; break;
2225 case DIR_PURPOSE_UPLOAD_VOTE: kind = "dl/ul-vote"; break;
2226 case DIR_PURPOSE_UPLOAD_SIGNATURES: kind = "dl/ul-sig"; break;
2227 case DIR_PURPOSE_FETCH_RENDDESC: kind = "dl/rend"; break;
2228 case DIR_PURPOSE_FETCH_RENDDESC_V2: kind = "dl/rend2"; break;
2229 case DIR_PURPOSE_UPLOAD_RENDDESC: kind = "dl/ul-rend"; break;
2230 case DIR_PURPOSE_UPLOAD_RENDDESC_V2: kind = "dl/ul-rend2"; break;
2232 if (kind) {
2233 key = tor_malloc(256);
2234 tor_snprintf(key, 256, "%s%s", kind, compressed?".z":"");
2235 } else {
2236 key = tor_malloc(256);
2237 tor_snprintf(key, 256, "unknown purpose (%d)%s",
2238 purpose, compressed?".z":"");
2240 note_request(key, bytes);
2241 tor_free(key);
2244 /** Helper: initialize the request map to instrument downloads. */
2245 static void
2246 ensure_request_map_initialized(void)
2248 if (!request_map)
2249 request_map = strmap_new();
2252 /** Called when we just transmitted or received <b>bytes</b> worth of data
2253 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2254 * <b>bytes</b> to the total associated with key. */
2255 void
2256 note_request(const char *key, size_t bytes)
2258 request_t *r;
2259 ensure_request_map_initialized();
2261 r = strmap_get(request_map, key);
2262 if (!r) {
2263 r = tor_malloc_zero(sizeof(request_t));
2264 strmap_set(request_map, key, r);
2266 r->bytes += bytes;
2267 r->count++;
2270 /** Return a newly allocated string holding a summary of bytes used per
2271 * request type. */
2272 char *
2273 directory_dump_request_log(void)
2275 smartlist_t *lines;
2276 char tmp[256];
2277 char *result;
2278 strmap_iter_t *iter;
2280 ensure_request_map_initialized();
2282 lines = smartlist_create();
2284 for (iter = strmap_iter_init(request_map);
2285 !strmap_iter_done(iter);
2286 iter = strmap_iter_next(request_map, iter)) {
2287 const char *key;
2288 void *val;
2289 request_t *r;
2290 strmap_iter_get(iter, &key, &val);
2291 r = val;
2292 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT" "U64_FORMAT"\n",
2293 key, U64_PRINTF_ARG(r->bytes), U64_PRINTF_ARG(r->count));
2294 smartlist_add(lines, tor_strdup(tmp));
2296 smartlist_sort_strings(lines);
2297 result = smartlist_join_strings(lines, "", 0, NULL);
2298 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2299 smartlist_free(lines);
2300 return result;
2302 #else
2303 static void
2304 note_client_request(int purpose, int compressed, size_t bytes)
2306 (void)purpose;
2307 (void)compressed;
2308 (void)bytes;
2311 void
2312 note_request(const char *key, size_t bytes)
2314 (void)key;
2315 (void)bytes;
2318 char *
2319 directory_dump_request_log(void)
2321 return tor_strdup("Not supported.");
2323 #endif
2325 /** Decide whether a client would accept the consensus we have
2327 * Clients can say they only want a consensus if it's signed by more
2328 * than half the authorities in a list. They pass this list in
2329 * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
2331 * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
2332 * of the full authority identity digest. (Only strings of even length,
2333 * i.e. encodings of full bytes, are handled correctly. In the case
2334 * of an odd number of hex digits the last one is silently ignored.)
2336 * Returns 1 if more than half of the requested authorities signed the
2337 * consensus, 0 otherwise.
2340 client_likes_consensus(networkstatus_t *v, const char *want_url)
2342 smartlist_t *want_authorities = smartlist_create();
2343 int need_at_least;
2344 int have = 0;
2346 dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0, 0);
2347 need_at_least = smartlist_len(want_authorities)/2+1;
2348 SMARTLIST_FOREACH(want_authorities, const char *, d, {
2349 char want_digest[DIGEST_LEN];
2350 int want_len = strlen(d)/2;
2351 if (want_len > DIGEST_LEN)
2352 want_len = DIGEST_LEN;
2354 if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) {
2355 log_warn(LD_DIR,"Failed to decode requested authority digest %s.", d);
2356 continue;
2359 SMARTLIST_FOREACH(v->voters, networkstatus_voter_info_t *, vi, {
2360 if (vi->signature &&
2361 !memcmp(vi->identity_digest, want_digest, want_len)) {
2362 have++;
2363 break;
2367 /* early exit, if we already have enough */
2368 if (have >= need_at_least)
2369 break;
2372 SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
2373 smartlist_free(want_authorities);
2374 return (have >= need_at_least);
2377 /** Helper function: called when a dirserver gets a complete HTTP GET
2378 * request. Look for a request for a directory or for a rendezvous
2379 * service descriptor. On finding one, write a response into
2380 * conn-\>outbuf. If the request is unrecognized, send a 400.
2381 * Always return 0. */
2382 static int
2383 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2384 const char *body, size_t body_len)
2386 size_t dlen;
2387 char *url, *url_mem, *header;
2388 or_options_t *options = get_options();
2389 time_t if_modified_since = 0;
2390 int compressed;
2391 size_t url_len;
2393 /* We ignore the body of a GET request. */
2394 (void)body;
2395 (void)body_len;
2397 log_debug(LD_DIRSERV,"Received GET command.");
2399 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2401 if (parse_http_url(headers, &url) < 0) {
2402 write_http_status_line(conn, 400, "Bad request");
2403 return 0;
2405 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2406 struct tm tm;
2407 if (parse_http_time(header, &tm) == 0) {
2408 if_modified_since = tor_timegm(&tm);
2410 /* The correct behavior on a malformed If-Modified-Since header is to
2411 * act as if no If-Modified-Since header had been given. */
2412 tor_free(header);
2414 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2416 url_mem = url;
2417 url_len = strlen(url);
2418 compressed = url_len > 2 && !strcmp(url+url_len-2, ".z");
2419 if (compressed) {
2420 url[url_len-2] = '\0';
2421 url_len -= 2;
2424 if (!strcmp(url,"/tor/")) {
2425 const char *frontpage = get_dirportfrontpage();
2427 if (frontpage) {
2428 dlen = strlen(frontpage);
2429 /* Let's return a disclaimer page (users shouldn't use V1 anymore,
2430 and caches don't fetch '/', so this is safe). */
2431 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2432 log_info(LD_DIRSERV,
2433 "Client asked for DirPortFrontPage content, but we've been "
2434 "writing too many bytes lately. Sending 503 Dir busy.");
2435 write_http_status_line(conn, 503, "Directory busy, try again later");
2436 goto done;
2438 note_request(url, dlen);
2439 write_http_response_header_impl(conn, dlen, "text/html", "identity",
2440 NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
2441 connection_write_to_buf(frontpage, dlen, TO_CONN(conn));
2442 goto done;
2444 /* if no disclaimer file, fall through and continue */
2447 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* v1 dir fetch */
2448 cached_dir_t *d = dirserv_get_directory();
2450 if (!d) {
2451 log_info(LD_DIRSERV,"Client asked for the mirrored directory, but we "
2452 "don't have a good one yet. Sending 503 Dir not available.");
2453 write_http_status_line(conn, 503, "Directory unavailable");
2454 goto done;
2456 if (d->published < if_modified_since) {
2457 write_http_status_line(conn, 304, "Not modified");
2458 goto done;
2461 dlen = compressed ? d->dir_z_len : d->dir_len;
2463 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2464 log_debug(LD_DIRSERV,
2465 "Client asked for the mirrored directory, but we've been "
2466 "writing too many bytes lately. Sending 503 Dir busy.");
2467 write_http_status_line(conn, 503, "Directory busy, try again later");
2468 goto done;
2471 note_request(url, dlen);
2473 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
2474 compressed?"compressed ":"");
2475 write_http_response_header(conn, dlen, compressed,
2476 FULL_DIR_CACHE_LIFETIME);
2477 conn->cached_dir = d;
2478 conn->cached_dir_offset = 0;
2479 if (!compressed)
2480 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2481 ++d->refcnt;
2483 /* Prime the connection with some data. */
2484 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
2485 connection_dirserv_flushed_some(conn);
2486 goto done;
2489 if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
2490 cached_dir_t *d = dirserv_get_runningrouters();
2491 if (!d) {
2492 write_http_status_line(conn, 503, "Directory unavailable");
2493 goto done;
2495 if (d->published < if_modified_since) {
2496 write_http_status_line(conn, 304, "Not modified");
2497 goto done;
2499 dlen = compressed ? d->dir_z_len : d->dir_len;
2501 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2502 log_info(LD_DIRSERV,
2503 "Client asked for running-routers, but we've been "
2504 "writing too many bytes lately. Sending 503 Dir busy.");
2505 write_http_status_line(conn, 503, "Directory busy, try again later");
2506 goto done;
2508 note_request(url, dlen);
2509 write_http_response_header(conn, dlen, compressed,
2510 RUNNINGROUTERS_CACHE_LIFETIME);
2511 connection_write_to_buf(compressed ? d->dir_z : d->dir, dlen,
2512 TO_CONN(conn));
2513 goto done;
2516 if (!strcmpstart(url,"/tor/status/")
2517 || !strcmpstart(url, "/tor/status-vote/current/consensus")) {
2518 /* v2 or v3 network status fetch. */
2519 smartlist_t *dir_fps = smartlist_create();
2520 int is_v3 = !strcmpstart(url, "/tor/status-vote");
2521 const char *request_type = NULL;
2522 const char *key = url + strlen("/tor/status/");
2523 long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2524 if (!is_v3) {
2525 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
2526 if (!strcmpstart(key, "fp/"))
2527 request_type = compressed?"/tor/status/fp.z":"/tor/status/fp";
2528 else if (!strcmpstart(key, "authority"))
2529 request_type = compressed?"/tor/status/authority.z":
2530 "/tor/status/authority";
2531 else if (!strcmpstart(key, "all"))
2532 request_type = compressed?"/tor/status/all.z":"/tor/status/all";
2533 else
2534 request_type = "/tor/status/?";
2535 } else {
2536 networkstatus_t *v = networkstatus_get_latest_consensus();
2537 time_t now = time(NULL);
2538 #define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/"
2539 if (v &&
2540 !strcmpstart(url, CONSENSUS_URL_PREFIX) &&
2541 !client_likes_consensus(v, url + strlen(CONSENSUS_URL_PREFIX))) {
2542 write_http_status_line(conn, 404, "Consensus not signed by sufficient "
2543 "number of requested authorities");
2544 smartlist_free(dir_fps);
2545 goto done;
2548 smartlist_add(dir_fps, tor_memdup("\0\0\0\0\0\0\0\0\0\0"
2549 "\0\0\0\0\0\0\0\0\0\0", 20));
2550 request_type = compressed?"v3.z":"v3";
2551 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2554 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2555 write_http_status_line(conn, 503, "Network status object unavailable");
2556 smartlist_free(dir_fps);
2557 goto done;
2560 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2561 write_http_status_line(conn, 404, "Not found");
2562 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2563 smartlist_free(dir_fps);
2564 goto done;
2565 } else if (!smartlist_len(dir_fps)) {
2566 write_http_status_line(conn, 304, "Not modified");
2567 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2568 smartlist_free(dir_fps);
2569 goto done;
2572 dlen = dirserv_estimate_data_size(dir_fps, 0, compressed);
2573 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2574 log_debug(LD_DIRSERV,
2575 "Client asked for network status lists, but we've been "
2576 "writing too many bytes lately. Sending 503 Dir busy.");
2577 write_http_status_line(conn, 503, "Directory busy, try again later");
2578 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2579 smartlist_free(dir_fps);
2580 goto done;
2583 #ifdef ENABLE_GEOIP_STATS
2585 geoip_client_action_t act =
2586 is_v3 ? GEOIP_CLIENT_NETWORKSTATUS : GEOIP_CLIENT_NETWORKSTATUS_V2;
2587 struct in_addr in;
2588 if (tor_inet_aton((TO_CONN(conn))->address, &in))
2589 geoip_note_client_seen(act, ntohl(in.s_addr), time(NULL));
2591 #endif
2593 // note_request(request_type,dlen);
2594 (void) request_type;
2595 write_http_response_header(conn, -1, compressed,
2596 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2597 conn->fingerprint_stack = dir_fps;
2598 if (! compressed)
2599 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2601 /* Prime the connection with some data. */
2602 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2603 connection_dirserv_flushed_some(conn);
2604 goto done;
2607 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2608 !strcmpstart(url,"/tor/status-vote/next/")) {
2609 /* XXXX If-modified-since is only implemented for the current
2610 * consensus: that's probably fine, since it's the only vote document
2611 * people fetch much. */
2612 int current;
2613 ssize_t body_len = 0;
2614 ssize_t estimated_len = 0;
2615 smartlist_t *items = smartlist_create();
2616 smartlist_t *dir_items = smartlist_create();
2617 int lifetime = 60; /* XXXX022 should actually use vote intervals. */
2618 url += strlen("/tor/status-vote/");
2619 current = !strcmpstart(url, "current/");
2620 url = strchr(url, '/');
2621 tor_assert(url);
2622 ++url;
2623 if (!strcmp(url, "consensus")) {
2624 const char *item;
2625 tor_assert(!current); /* we handle current consensus specially above,
2626 * since it wants to be spooled. */
2627 if ((item = dirvote_get_pending_consensus()))
2628 smartlist_add(items, (char*)item);
2629 } else if (!current && !strcmp(url, "consensus-signatures")) {
2630 /* XXXX the spec says that we should implement
2631 * current/consensus-signatures too. It doesn't seem to be needed,
2632 * though. */
2633 const char *item;
2634 if ((item=dirvote_get_pending_detached_signatures()))
2635 smartlist_add(items, (char*)item);
2636 } else if (!strcmp(url, "authority")) {
2637 const cached_dir_t *d;
2638 int flags = DGV_BY_ID |
2639 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2640 if ((d=dirvote_get_vote(NULL, flags)))
2641 smartlist_add(dir_items, (cached_dir_t*)d);
2642 } else {
2643 const cached_dir_t *d;
2644 smartlist_t *fps = smartlist_create();
2645 int flags;
2646 if (!strcmpstart(url, "d/")) {
2647 url += 2;
2648 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2649 } else {
2650 flags = DGV_BY_ID |
2651 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2653 dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1);
2654 SMARTLIST_FOREACH(fps, char *, fp, {
2655 if ((d = dirvote_get_vote(fp, flags)))
2656 smartlist_add(dir_items, (cached_dir_t*)d);
2657 tor_free(fp);
2659 smartlist_free(fps);
2661 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2662 write_http_status_line(conn, 404, "Not found");
2663 goto vote_done;
2665 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2666 body_len += compressed ? d->dir_z_len : d->dir_len);
2667 estimated_len += body_len;
2668 SMARTLIST_FOREACH(items, const char *, item, {
2669 size_t ln = strlen(item);
2670 if (compressed) {
2671 estimated_len += ln/2;
2672 } else {
2673 body_len += ln; estimated_len += ln;
2677 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
2678 write_http_status_line(conn, 503, "Directory busy, try again later.");
2679 goto vote_done;
2681 write_http_response_header(conn, body_len ? body_len : -1, compressed,
2682 lifetime);
2684 if (smartlist_len(items)) {
2685 if (compressed) {
2686 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2687 SMARTLIST_FOREACH(items, const char *, c,
2688 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2689 connection_write_to_buf_zlib("", 0, conn, 1);
2690 } else {
2691 SMARTLIST_FOREACH(items, const char *, c,
2692 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2694 } else {
2695 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2696 connection_write_to_buf(compressed ? d->dir_z : d->dir,
2697 compressed ? d->dir_z_len : d->dir_len,
2698 TO_CONN(conn)));
2700 vote_done:
2701 smartlist_free(items);
2702 smartlist_free(dir_items);
2703 goto done;
2706 if (!strcmpstart(url,"/tor/server/") ||
2707 (!options->BridgeAuthoritativeDir &&
2708 !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
2709 int res;
2710 const char *msg;
2711 const char *request_type = NULL;
2712 int cache_lifetime = 0;
2713 int is_extra = !strcmpstart(url,"/tor/extra/");
2714 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2715 conn->fingerprint_stack = smartlist_create();
2716 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2717 &msg,
2718 !connection_dir_is_encrypted(conn),
2719 is_extra);
2721 if (!strcmpstart(url, "fp/")) {
2722 request_type = compressed?"/tor/server/fp.z":"/tor/server/fp";
2723 if (smartlist_len(conn->fingerprint_stack) == 1)
2724 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2725 } else if (!strcmpstart(url, "authority")) {
2726 request_type = compressed?"/tor/server/authority.z":
2727 "/tor/server/authority";
2728 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2729 } else if (!strcmpstart(url, "all")) {
2730 request_type = compressed?"/tor/server/all.z":"/tor/server/all";
2731 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2732 } else if (!strcmpstart(url, "d/")) {
2733 request_type = compressed?"/tor/server/d.z":"/tor/server/d";
2734 if (smartlist_len(conn->fingerprint_stack) == 1)
2735 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2736 } else {
2737 request_type = "/tor/server/?";
2739 (void) request_type; /* usable for note_request. */
2740 if (!strcmpstart(url, "d/"))
2741 conn->dir_spool_src =
2742 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2743 else
2744 conn->dir_spool_src =
2745 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2747 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2748 conn->dir_spool_src)) {
2749 res = -1;
2750 msg = "Not found";
2753 if (res < 0)
2754 write_http_status_line(conn, 404, msg);
2755 else {
2756 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2757 1, compressed);
2758 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2759 log_info(LD_DIRSERV,
2760 "Client asked for server descriptors, but we've been "
2761 "writing too many bytes lately. Sending 503 Dir busy.");
2762 write_http_status_line(conn, 503, "Directory busy, try again later");
2763 conn->dir_spool_src = DIR_SPOOL_NONE;
2764 goto done;
2766 write_http_response_header(conn, -1, compressed, cache_lifetime);
2767 if (compressed)
2768 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2769 /* Prime the connection with some data. */
2770 connection_dirserv_flushed_some(conn);
2772 goto done;
2775 if (!strcmpstart(url,"/tor/keys/")) {
2776 smartlist_t *certs = smartlist_create();
2777 ssize_t len = -1;
2778 if (!strcmp(url, "/tor/keys/all")) {
2779 authority_cert_get_all(certs);
2780 } else if (!strcmp(url, "/tor/keys/authority")) {
2781 authority_cert_t *cert = get_my_v3_authority_cert();
2782 if (cert)
2783 smartlist_add(certs, cert);
2784 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
2785 smartlist_t *fps = smartlist_create();
2786 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
2787 fps, NULL, 1, 1);
2788 SMARTLIST_FOREACH(fps, char *, d, {
2789 authority_cert_t *c = authority_cert_get_newest_by_id(d);
2790 if (c) smartlist_add(certs, c);
2791 tor_free(d);
2793 smartlist_free(fps);
2794 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
2795 smartlist_t *fps = smartlist_create();
2796 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
2797 fps, NULL, 1, 1);
2798 SMARTLIST_FOREACH(fps, char *, d, {
2799 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
2800 if (c) smartlist_add(certs, c);
2801 tor_free(d);
2803 smartlist_free(fps);
2804 } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
2805 smartlist_t *fp_sks = smartlist_create();
2806 dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
2807 fp_sks);
2808 SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
2809 authority_cert_t *c = authority_cert_get_by_digests(pair->first,
2810 pair->second);
2811 if (c) smartlist_add(certs, c);
2812 tor_free(pair);
2814 smartlist_free(fp_sks);
2815 } else {
2816 write_http_status_line(conn, 400, "Bad request");
2817 goto keys_done;
2819 if (!smartlist_len(certs)) {
2820 write_http_status_line(conn, 404, "Not found");
2821 goto keys_done;
2823 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2824 if (c->cache_info.published_on < if_modified_since)
2825 SMARTLIST_DEL_CURRENT(certs, c));
2826 if (!smartlist_len(certs)) {
2827 write_http_status_line(conn, 304, "Not modified");
2828 goto keys_done;
2830 len = 0;
2831 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2832 len += c->cache_info.signed_descriptor_len);
2834 if (global_write_bucket_low(TO_CONN(conn), compressed?len/2:len, 2)) {
2835 write_http_status_line(conn, 503, "Directory busy, try again later.");
2836 goto keys_done;
2839 write_http_response_header(conn, compressed?-1:len, compressed, 60*60);
2840 if (compressed) {
2841 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2842 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2843 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
2844 c->cache_info.signed_descriptor_len,
2845 conn, 0));
2846 connection_write_to_buf_zlib("", 0, conn, 1);
2847 } else {
2848 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2849 connection_write_to_buf(c->cache_info.signed_descriptor_body,
2850 c->cache_info.signed_descriptor_len,
2851 TO_CONN(conn)));
2853 keys_done:
2854 smartlist_free(certs);
2855 goto done;
2858 if (options->HidServDirectoryV2 &&
2859 !strcmpstart(url,"/tor/rendezvous2/")) {
2860 /* Handle v2 rendezvous descriptor fetch request. */
2861 const char *descp;
2862 const char *query = url + strlen("/tor/rendezvous2/");
2863 if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) {
2864 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
2865 safe_str(query));
2866 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
2867 case 1: /* valid */
2868 write_http_response_header(conn, strlen(descp), 0, 0);
2869 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
2870 break;
2871 case 0: /* well-formed but not present */
2872 write_http_status_line(conn, 404, "Not found");
2873 break;
2874 case -1: /* not well-formed */
2875 write_http_status_line(conn, 400, "Bad request");
2876 break;
2878 } else { /* not well-formed */
2879 write_http_status_line(conn, 400, "Bad request");
2881 goto done;
2884 if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) {
2885 /* rendezvous descriptor fetch */
2886 const char *descp;
2887 size_t desc_len;
2888 const char *query = url+strlen("/tor/rendezvous/");
2890 log_info(LD_REND, "Handling rendezvous descriptor get");
2891 switch (rend_cache_lookup_desc(query, 0, &descp, &desc_len)) {
2892 case 1: /* valid */
2893 write_http_response_header_impl(conn, desc_len,
2894 "application/octet-stream",
2895 NULL, NULL, 0);
2896 note_request("/tor/rendezvous?/", desc_len);
2897 /* need to send descp separately, because it may include NULs */
2898 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
2899 /* report successful fetch to statistic */
2900 if (options->HSAuthorityRecordStats) {
2901 hs_usage_note_fetch_total(query, time(NULL));
2902 hs_usage_note_fetch_successful(query, time(NULL));
2904 break;
2905 case 0: /* well-formed but not present */
2906 write_http_status_line(conn, 404, "Not found");
2907 /* report (unsuccessful) fetch to statistic */
2908 if (options->HSAuthorityRecordStats) {
2909 hs_usage_note_fetch_total(query, time(NULL));
2911 break;
2912 case -1: /* not well-formed */
2913 write_http_status_line(conn, 400, "Bad request");
2914 break;
2916 goto done;
2919 if (options->BridgeAuthoritativeDir &&
2920 options->BridgePassword &&
2921 connection_dir_is_encrypted(conn) &&
2922 !strcmp(url,"/tor/networkstatus-bridges")) {
2923 char *status;
2924 char *secret = alloc_http_authenticator(options->BridgePassword);
2926 header = http_get_header(headers, "Authorization: Basic ");
2928 /* now make sure the password is there and right */
2929 if (!header || strcmp(header, secret)) {
2930 write_http_status_line(conn, 404, "Not found");
2931 tor_free(secret);
2932 tor_free(header);
2933 goto done;
2935 tor_free(secret);
2936 tor_free(header);
2938 /* all happy now. send an answer. */
2939 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
2940 dlen = strlen(status);
2941 write_http_response_header(conn, dlen, 0, 0);
2942 connection_write_to_buf(status, dlen, TO_CONN(conn));
2943 tor_free(status);
2944 goto done;
2947 if (!strcmpstart(url,"/tor/bytes.txt")) {
2948 char *bytes = directory_dump_request_log();
2949 size_t len = strlen(bytes);
2950 write_http_response_header(conn, len, 0, 0);
2951 connection_write_to_buf(bytes, len, TO_CONN(conn));
2952 tor_free(bytes);
2953 goto done;
2956 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
2957 rewritten to /tor/robots.txt */
2958 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
2959 size_t len = strlen(robots);
2960 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
2961 connection_write_to_buf(robots, len, TO_CONN(conn));
2962 goto done;
2965 if (!strcmp(url,"/tor/dbg-stability.txt")) {
2966 const char *stability;
2967 size_t len;
2968 if (! authdir_mode_tests_reachability(options) ||
2969 ! (stability = rep_hist_get_router_stability_doc(time(NULL)))) {
2970 write_http_status_line(conn, 404, "Not found.");
2971 goto done;
2974 len = strlen(stability);
2975 write_http_response_header(conn, len, 0, 0);
2976 connection_write_to_buf(stability, len, TO_CONN(conn));
2977 goto done;
2980 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
2981 #define ADD_MALLINFO_LINE(x) do { \
2982 tor_snprintf(tmp, sizeof(tmp), "%s %d\n", #x, mi.x); \
2983 smartlist_add(lines, tor_strdup(tmp)); \
2984 }while(0);
2986 if (!strcmp(url,"/tor/mallinfo.txt") &&
2987 (tor_addr_eq_ipv4h(&conn->_base.addr, 0x7f000001ul))) {
2988 char *result;
2989 size_t len;
2990 struct mallinfo mi;
2991 smartlist_t *lines;
2992 char tmp[256];
2994 memset(&mi, 0, sizeof(mi));
2995 mi = mallinfo();
2996 lines = smartlist_create();
2998 ADD_MALLINFO_LINE(arena)
2999 ADD_MALLINFO_LINE(ordblks)
3000 ADD_MALLINFO_LINE(smblks)
3001 ADD_MALLINFO_LINE(hblks)
3002 ADD_MALLINFO_LINE(hblkhd)
3003 ADD_MALLINFO_LINE(usmblks)
3004 ADD_MALLINFO_LINE(fsmblks)
3005 ADD_MALLINFO_LINE(uordblks)
3006 ADD_MALLINFO_LINE(fordblks)
3007 ADD_MALLINFO_LINE(keepcost)
3009 result = smartlist_join_strings(lines, "", 0, NULL);
3010 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
3011 smartlist_free(lines);
3013 len = strlen(result);
3014 write_http_response_header(conn, len, 0, 0);
3015 connection_write_to_buf(result, len, TO_CONN(conn));
3016 tor_free(result);
3017 goto done;
3019 #endif
3021 /* we didn't recognize the url */
3022 write_http_status_line(conn, 404, "Not found");
3024 done:
3025 tor_free(url_mem);
3026 return 0;
3029 /** Helper function: called when a dirserver gets a complete HTTP POST
3030 * request. Look for an uploaded server descriptor or rendezvous
3031 * service descriptor. On finding one, process it and write a
3032 * response into conn-\>outbuf. If the request is unrecognized, send a
3033 * 400. Always return 0. */
3034 static int
3035 directory_handle_command_post(dir_connection_t *conn, const char *headers,
3036 const char *body, size_t body_len)
3038 char *url = NULL;
3039 or_options_t *options = get_options();
3041 log_debug(LD_DIRSERV,"Received POST command.");
3043 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
3045 if (parse_http_url(headers, &url) < 0) {
3046 write_http_status_line(conn, 400, "Bad request");
3047 return 0;
3049 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
3051 /* Handle v2 rendezvous service publish request. */
3052 if (options->HidServDirectoryV2 &&
3053 !strcmpstart(url,"/tor/rendezvous2/publish")) {
3054 switch (rend_cache_store_v2_desc_as_dir(body)) {
3055 case -2:
3056 log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
3057 "since we're not currently a hidden service directory.",
3058 (int)body_len, conn->_base.address);
3059 write_http_status_line(conn, 503, "Currently not acting as v2 "
3060 "hidden service directory");
3061 break;
3062 case -1:
3063 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
3064 (int)body_len, conn->_base.address);
3065 write_http_status_line(conn, 400,
3066 "Invalid v2 service descriptor rejected");
3067 break;
3068 default:
3069 write_http_status_line(conn, 200, "Service descriptor (v2) stored");
3070 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
3072 goto done;
3075 if (!authdir_mode(options)) {
3076 /* we just provide cached directories; we don't want to
3077 * receive anything. */
3078 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
3079 "accept posted server descriptors");
3080 goto done;
3083 if (authdir_mode_handles_descs(options, -1) &&
3084 !strcmp(url,"/tor/")) { /* server descriptor post */
3085 const char *msg = "[None]";
3086 uint8_t purpose = authdir_mode_bridge(options) ?
3087 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
3088 was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
3089 conn->_base.address, &msg);
3090 tor_assert(msg);
3091 if (WRA_WAS_ADDED(r))
3092 dirserv_get_directory(); /* rebuild and write to disk */
3094 if (r == ROUTER_ADDED_NOTIFY_GENERATOR) {
3095 /* Accepted with a message. */
3096 log_info(LD_DIRSERV,
3097 "Problematic router descriptor or extra-info from %s "
3098 "(\"%s\").",
3099 conn->_base.address, msg);
3100 write_http_status_line(conn, 400, msg);
3101 } else if (r == ROUTER_ADDED_SUCCESSFULLY) {
3102 write_http_status_line(conn, 200, msg);
3103 } else if (WRA_WAS_OUTDATED(r)) {
3104 write_http_response_header_impl(conn, -1, NULL, NULL,
3105 "X-Descriptor-Not-New: Yes\r\n", -1);
3106 } else {
3107 log_info(LD_DIRSERV,
3108 "Rejected router descriptor or extra-info from %s "
3109 "(\"%s\").",
3110 conn->_base.address, msg);
3111 write_http_status_line(conn, 400, msg);
3113 goto done;
3116 if (options->HSAuthoritativeDir &&
3117 !strcmpstart(url,"/tor/rendezvous/publish")) {
3118 /* rendezvous descriptor post */
3119 log_info(LD_REND, "Handling rendezvous descriptor post.");
3120 if (rend_cache_store(body, body_len, 1) < 0) {
3121 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
3122 "Rejected rend descriptor (length %d) from %s.",
3123 (int)body_len, conn->_base.address);
3124 write_http_status_line(conn, 400,
3125 "Invalid v0 service descriptor rejected");
3126 } else {
3127 write_http_status_line(conn, 200, "Service descriptor (v0) stored");
3129 goto done;
3132 if (authdir_mode_v3(options) &&
3133 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
3134 const char *msg = "OK";
3135 int status;
3136 if (dirvote_add_vote(body, &msg, &status)) {
3137 write_http_status_line(conn, status, "Vote stored");
3138 } else {
3139 tor_assert(msg);
3140 write_http_status_line(conn, status, msg);
3142 goto done;
3145 if (authdir_mode_v3(options) &&
3146 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
3147 const char *msg = NULL;
3148 if (dirvote_add_signatures(body, conn->_base.address, &msg)>=0) {
3149 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
3150 } else {
3151 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
3152 conn->_base.address, msg?msg:"???");
3153 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
3155 goto done;
3158 /* we didn't recognize the url */
3159 write_http_status_line(conn, 404, "Not found");
3161 done:
3162 tor_free(url);
3163 return 0;
3166 /** Called when a dirserver receives data on a directory connection;
3167 * looks for an HTTP request. If the request is complete, remove it
3168 * from the inbuf, try to process it; otherwise, leave it on the
3169 * buffer. Return a 0 on success, or -1 on error.
3171 static int
3172 directory_handle_command(dir_connection_t *conn)
3174 char *headers=NULL, *body=NULL;
3175 size_t body_len=0;
3176 int r;
3178 tor_assert(conn);
3179 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3181 switch (fetch_from_buf_http(conn->_base.inbuf,
3182 &headers, MAX_HEADERS_SIZE,
3183 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
3184 case -1: /* overflow */
3185 log_warn(LD_DIRSERV,
3186 "Invalid input from address '%s'. Closing.",
3187 conn->_base.address);
3188 return -1;
3189 case 0:
3190 log_debug(LD_DIRSERV,"command not all here yet.");
3191 return 0;
3192 /* case 1, fall through */
3195 http_set_address_origin(headers, TO_CONN(conn));
3196 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
3198 if (!strncasecmp(headers,"GET",3))
3199 r = directory_handle_command_get(conn, headers, body, body_len);
3200 else if (!strncasecmp(headers,"POST",4))
3201 r = directory_handle_command_post(conn, headers, body, body_len);
3202 else {
3203 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
3204 "Got headers %s with unknown command. Closing.",
3205 escaped(headers));
3206 r = -1;
3209 tor_free(headers); tor_free(body);
3210 return r;
3213 /** Write handler for directory connections; called when all data has
3214 * been flushed. Close the connection or wait for a response as
3215 * appropriate.
3218 connection_dir_finished_flushing(dir_connection_t *conn)
3220 tor_assert(conn);
3221 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3223 switch (conn->_base.state) {
3224 case DIR_CONN_STATE_CLIENT_SENDING:
3225 log_debug(LD_DIR,"client finished sending command.");
3226 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
3227 connection_stop_writing(TO_CONN(conn));
3228 return 0;
3229 case DIR_CONN_STATE_SERVER_WRITING:
3230 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
3231 connection_mark_for_close(TO_CONN(conn));
3232 return 0;
3233 default:
3234 log_warn(LD_BUG,"called in unexpected state %d.",
3235 conn->_base.state);
3236 tor_fragile_assert();
3237 return -1;
3239 return 0;
3242 /** Connected handler for directory connections: begin sending data to the
3243 * server */
3245 connection_dir_finished_connecting(dir_connection_t *conn)
3247 tor_assert(conn);
3248 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3249 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
3251 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
3252 conn->_base.address,conn->_base.port);
3254 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
3255 return 0;
3258 /** Called when one or more networkstatus fetches have failed (with uppercase
3259 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
3260 * failed once, unless they failed with status code 503. */
3261 static void
3262 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
3264 if (status_code == 503)
3265 return;
3266 SMARTLIST_FOREACH(failed, const char *, fp,
3268 char digest[DIGEST_LEN];
3269 trusted_dir_server_t *dir;
3270 if (base16_decode(digest, DIGEST_LEN, fp, strlen(fp))<0) {
3271 log_warn(LD_BUG, "Called with bad fingerprint in list: %s",
3272 escaped(fp));
3273 continue;
3275 dir = router_get_trusteddirserver_by_digest(digest);
3277 if (dir)
3278 download_status_failed(&dir->v2_ns_dl_status, status_code);
3282 /** Schedule for when servers should download things in general. */
3283 static const int server_dl_schedule[] = {
3284 0, 0, 0, 60, 60, 60*2, 60*5, 60*15, INT_MAX
3286 /** Schedule for when clients should download things in general. */
3287 static const int client_dl_schedule[] = {
3288 0, 0, 60, 60*5, 60*10, INT_MAX
3290 /** Schedule for when servers should download consensuses. */
3291 static const int server_consensus_dl_schedule[] = {
3292 0, 0, 60, 60*5, 60*10, 60*30, 60*30, 60*30, 60*30, 60*30, 60*60, 60*60*2
3294 /** Schedule for when clients should download consensuses. */
3295 static const int client_consensus_dl_schedule[] = {
3296 0, 0, 60, 60*5, 60*10, 60*30, 60*60, 60*60, 60*60, 60*60*3, 60*60*6, 60*60*12
3298 /** Schedule for when clients should download bridge descriptors. */
3299 static const int bridge_dl_schedule[] = {
3300 60*60, 15*60, 15*60, 60*60
3303 /** Decide which download schedule we want to use, and then return a
3304 * pointer to it along with a pointer to its length. Helper function for
3305 * download_status_increment_failure() and download_status_reset(). */
3306 static void
3307 find_dl_schedule_and_len(download_status_t *dls, int server,
3308 const int **schedule, size_t *schedule_len)
3310 switch (dls->schedule) {
3311 case DL_SCHED_GENERIC:
3312 if (server) {
3313 *schedule = server_dl_schedule;
3314 *schedule_len = sizeof(server_dl_schedule)/sizeof(int);
3315 } else {
3316 *schedule = client_dl_schedule;
3317 *schedule_len = sizeof(client_dl_schedule)/sizeof(int);
3319 break;
3320 case DL_SCHED_CONSENSUS:
3321 if (server) {
3322 *schedule = server_consensus_dl_schedule;
3323 *schedule_len = sizeof(server_consensus_dl_schedule)/sizeof(int);
3324 } else {
3325 *schedule = client_consensus_dl_schedule;
3326 *schedule_len = sizeof(client_consensus_dl_schedule)/sizeof(int);
3328 break;
3329 case DL_SCHED_BRIDGE:
3330 *schedule = bridge_dl_schedule;
3331 *schedule_len = sizeof(bridge_dl_schedule)/sizeof(int);
3332 break;
3333 default:
3334 tor_assert(0);
3338 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
3339 * <b>status_code</b>. Increment the failure count (if the code indicates a
3340 * real failure) and set <b>dls</b>-\>next_attempt_at to an appropriate time
3341 * in the future. */
3342 time_t
3343 download_status_increment_failure(download_status_t *dls, int status_code,
3344 const char *item, int server, time_t now)
3346 const int *schedule;
3347 size_t schedule_len;
3348 int increment;
3349 tor_assert(dls);
3350 if (status_code != 503 || server) {
3351 if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1)
3352 ++dls->n_download_failures;
3355 find_dl_schedule_and_len(dls, server, &schedule, &schedule_len);
3357 if (dls->n_download_failures < schedule_len)
3358 increment = schedule[dls->n_download_failures];
3359 else if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
3360 increment = INT_MAX;
3361 else
3362 increment = schedule[schedule_len-1];
3364 if (increment < INT_MAX)
3365 dls->next_attempt_at = now+increment;
3366 else
3367 dls->next_attempt_at = TIME_MAX;
3369 if (item) {
3370 if (increment == 0)
3371 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
3372 item, (int)dls->n_download_failures);
3373 else if (dls->next_attempt_at < TIME_MAX)
3374 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
3375 item, (int)dls->n_download_failures,
3376 (int)(dls->next_attempt_at-now));
3377 else
3378 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
3379 item, (int)dls->n_download_failures);
3381 return dls->next_attempt_at;
3384 /** Reset <b>dls</b> so that it will be considered downloadable
3385 * immediately, and/or to show that we don't need it anymore.
3387 * (We find the zeroth element of the download schedule, and set
3388 * next_attempt_at to be the appropriate offset from 'now'. In most
3389 * cases this means setting it to 'now', so the item will be immediately
3390 * downloadable; in the case of bridge descriptors, the zeroth element
3391 * is an hour from now.) */
3392 void
3393 download_status_reset(download_status_t *dls)
3395 const int *schedule;
3396 size_t schedule_len;
3398 find_dl_schedule_and_len(dls, get_options()->DirPort,
3399 &schedule, &schedule_len);
3401 dls->n_download_failures = 0;
3402 dls->next_attempt_at = time(NULL) + schedule[0];
3405 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
3406 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
3407 * either as descriptor digests or as identity digests based on
3408 * <b>was_descriptor_digests</b>).
3410 static void
3411 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
3412 int router_purpose,
3413 int was_extrainfo, int was_descriptor_digests)
3415 char digest[DIGEST_LEN];
3416 time_t now = time(NULL);
3417 int server = directory_fetches_from_authorities(get_options());
3418 if (!was_descriptor_digests) {
3419 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
3420 tor_assert(!was_extrainfo); /* not supported yet */
3421 SMARTLIST_FOREACH(failed, const char *, cp,
3423 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
3424 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
3425 escaped(cp));
3426 continue;
3428 retry_bridge_descriptor_fetch_directly(digest);
3431 return; /* FFFF should implement for other-than-router-purpose someday */
3433 SMARTLIST_FOREACH(failed, const char *, cp,
3435 download_status_t *dls = NULL;
3436 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) {
3437 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
3438 continue;
3440 if (was_extrainfo) {
3441 signed_descriptor_t *sd =
3442 router_get_by_extrainfo_digest(digest);
3443 if (sd)
3444 dls = &sd->ei_dl_status;
3445 } else {
3446 dls = router_get_dl_status_by_descriptor_digest(digest);
3448 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
3449 continue;
3450 download_status_increment_failure(dls, status_code, cp, server, now);
3453 /* No need to relaunch descriptor downloads here: we already do it
3454 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3457 /** Helper. Compare two fp_pair_t objects, and return -1, 0, or 1 as
3458 * appropriate. */
3459 static int
3460 _compare_pairs(const void **a, const void **b)
3462 const fp_pair_t *fp1 = *a, *fp2 = *b;
3463 int r;
3464 if ((r = memcmp(fp1->first, fp2->first, DIGEST_LEN)))
3465 return r;
3466 else
3467 return memcmp(fp1->second, fp2->second, DIGEST_LEN);
3470 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
3471 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
3472 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
3473 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
3475 dir_split_resource_into_fingerprint_pairs(const char *res,
3476 smartlist_t *pairs_out)
3478 smartlist_t *pairs_tmp = smartlist_create();
3479 smartlist_t *pairs_result = smartlist_create();
3481 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
3482 if (smartlist_len(pairs_tmp)) {
3483 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
3484 size_t last_len = strlen(last);
3485 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3486 last[last_len-2] = '\0';
3489 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
3490 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
3491 log_info(LD_DIR,
3492 "Skipping digest pair %s with non-standard length.", escaped(cp));
3493 } else if (cp[HEX_DIGEST_LEN] != '-') {
3494 log_info(LD_DIR,
3495 "Skipping digest pair %s with missing dash.", escaped(cp));
3496 } else {
3497 fp_pair_t pair;
3498 if (base16_decode(pair.first, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0 ||
3499 base16_decode(pair.second,
3500 DIGEST_LEN, cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN)<0) {
3501 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
3502 } else {
3503 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
3506 tor_free(cp);
3507 } SMARTLIST_FOREACH_END(cp);
3508 smartlist_free(pairs_tmp);
3510 /* Uniq-and-sort */
3511 smartlist_sort(pairs_result, _compare_pairs);
3512 smartlist_uniq(pairs_result, _compare_pairs, _tor_free);
3514 smartlist_add_all(pairs_out, pairs_result);
3515 smartlist_free(pairs_result);
3516 return 0;
3519 /** Given a directory <b>resource</b> request, containing zero
3520 * or more strings separated by plus signs, followed optionally by ".z", store
3521 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3522 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
3523 * decode_hex is true, then delete all elements that aren't hex digests, and
3524 * decode the rest. If sort_uniq is true, then sort the list and remove
3525 * all duplicates.
3528 dir_split_resource_into_fingerprints(const char *resource,
3529 smartlist_t *fp_out, int *compressed_out,
3530 int decode_hex, int sort_uniq)
3532 smartlist_t *fp_tmp = smartlist_create();
3533 tor_assert(fp_out);
3534 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
3535 if (compressed_out)
3536 *compressed_out = 0;
3537 if (smartlist_len(fp_tmp)) {
3538 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3539 size_t last_len = strlen(last);
3540 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3541 last[last_len-2] = '\0';
3542 if (compressed_out)
3543 *compressed_out = 1;
3546 if (decode_hex) {
3547 int i;
3548 char *cp, *d = NULL;
3549 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3550 cp = smartlist_get(fp_tmp, i);
3551 if (strlen(cp) != HEX_DIGEST_LEN) {
3552 log_info(LD_DIR,
3553 "Skipping digest %s with non-standard length.", escaped(cp));
3554 smartlist_del_keeporder(fp_tmp, i--);
3555 goto again;
3557 d = tor_malloc_zero(DIGEST_LEN);
3558 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
3559 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3560 smartlist_del_keeporder(fp_tmp, i--);
3561 goto again;
3563 smartlist_set(fp_tmp, i, d);
3564 d = NULL;
3565 again:
3566 tor_free(cp);
3567 tor_free(d);
3570 if (sort_uniq) {
3571 smartlist_t *fp_tmp2 = smartlist_create();
3572 int i;
3573 if (decode_hex)
3574 smartlist_sort_digests(fp_tmp);
3575 else
3576 smartlist_sort_strings(fp_tmp);
3577 if (smartlist_len(fp_tmp))
3578 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
3579 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
3580 char *cp = smartlist_get(fp_tmp, i);
3581 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
3583 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
3584 || (!decode_hex && strcasecmp(cp, last)))
3585 smartlist_add(fp_tmp2, cp);
3586 else
3587 tor_free(cp);
3589 smartlist_free(fp_tmp);
3590 fp_tmp = fp_tmp2;
3592 smartlist_add_all(fp_out, fp_tmp);
3593 smartlist_free(fp_tmp);
3594 return 0;