Merge remote-tracking branch 'public/bug3122_memcmp_022' into maint-0.2.2
[tor.git] / src / or / directory.c
blob4c26671c70b62a2190db84bbdfbf5ad0726ea108
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2011, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "or.h"
7 #include "buffers.h"
8 #include "circuitbuild.h"
9 #include "config.h"
10 #include "connection.h"
11 #include "connection_edge.h"
12 #include "control.h"
13 #include "directory.h"
14 #include "dirserv.h"
15 #include "dirvote.h"
16 #include "geoip.h"
17 #include "main.h"
18 #include "networkstatus.h"
19 #include "policies.h"
20 #include "rendclient.h"
21 #include "rendcommon.h"
22 #include "rephist.h"
23 #include "router.h"
24 #include "routerlist.h"
25 #include "routerparse.h"
27 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
28 #ifndef OPENBSD
29 #include <malloc.h>
30 #endif
31 #endif
33 /**
34 * \file directory.c
35 * \brief Code to send and fetch directories and router
36 * descriptors via HTTP. Directories use dirserv.c to generate the
37 * results; clients use routers.c to parse them.
38 **/
40 /* In-points to directory.c:
42 * - directory_post_to_dirservers(), called from
43 * router_upload_dir_desc_to_dirservers() in router.c
44 * upload_service_descriptor() in rendservice.c
45 * - directory_get_from_dirserver(), called from
46 * rend_client_refetch_renddesc() in rendclient.c
47 * run_scheduled_events() in main.c
48 * do_hup() in main.c
49 * - connection_dir_process_inbuf(), called from
50 * connection_process_inbuf() in connection.c
51 * - connection_dir_finished_flushing(), called from
52 * connection_finished_flushing() in connection.c
53 * - connection_dir_finished_connecting(), called from
54 * connection_finished_connecting() in connection.c
56 static void directory_send_command(dir_connection_t *conn,
57 int purpose, int direct, const char *resource,
58 const char *payload, size_t payload_len,
59 int supports_conditional_consensus,
60 time_t if_modified_since);
61 static int directory_handle_command(dir_connection_t *conn);
62 static int body_is_plausible(const char *body, size_t body_len, int purpose);
63 static int purpose_needs_anonymity(uint8_t dir_purpose,
64 uint8_t router_purpose);
65 static char *http_get_header(const char *headers, const char *which);
66 static void http_set_address_origin(const char *headers, connection_t *conn);
67 static void connection_dir_download_v2_networkstatus_failed(
68 dir_connection_t *conn, int status_code);
69 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
70 static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn);
71 static void connection_dir_download_cert_failed(
72 dir_connection_t *conn, int status_code);
73 static void connection_dir_retry_bridges(smartlist_t *descs);
74 static void dir_networkstatus_download_failed(smartlist_t *failed,
75 int status_code);
76 static void dir_routerdesc_download_failed(smartlist_t *failed,
77 int status_code,
78 int router_purpose,
79 int was_extrainfo,
80 int was_descriptor_digests);
81 static void note_client_request(int purpose, int compressed, size_t bytes);
82 static int client_likes_consensus(networkstatus_t *v, const char *want_url);
84 static void directory_initiate_command_rend(const char *address,
85 const tor_addr_t *addr,
86 uint16_t or_port,
87 uint16_t dir_port,
88 int supports_conditional_consensus,
89 int supports_begindir,
90 const char *digest,
91 uint8_t dir_purpose,
92 uint8_t router_purpose,
93 int anonymized_connection,
94 const char *resource,
95 const char *payload,
96 size_t payload_len,
97 time_t if_modified_since,
98 const rend_data_t *rend_query);
100 /********* START VARIABLES **********/
102 /** How far in the future do we allow a directory server to tell us it is
103 * before deciding that one of us has the wrong time? */
104 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
106 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
108 /** HTTP cache control: how long do we tell proxies they can cache each
109 * kind of document we serve? */
110 #define FULL_DIR_CACHE_LIFETIME (60*60)
111 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
112 #define DIRPORTFRONTPAGE_CACHE_LIFETIME (20*60)
113 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
114 #define ROUTERDESC_CACHE_LIFETIME (30*60)
115 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
116 #define ROBOTS_CACHE_LIFETIME (24*60*60)
117 #define MICRODESC_CACHE_LIFETIME (48*60*60)
119 /********* END VARIABLES ************/
121 /** Return true iff the directory purpose <b>dir_purpose</b> (and if it's
122 * fetching descriptors, it's fetching them for <b>router_purpose</b>)
123 * must use an anonymous connection to a directory. */
124 static int
125 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
127 if (get_options()->AllDirActionsPrivate)
128 return 1;
129 if (router_purpose == ROUTER_PURPOSE_BRIDGE && can_complete_circuit)
130 return 1; /* if no circuits yet, we may need this info to bootstrap. */
131 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
132 dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
133 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
134 dir_purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS ||
135 dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
136 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
137 dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
138 dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
139 dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
140 dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
141 return 0;
142 return 1;
145 /** Return a newly allocated string describing <b>auth</b>. */
146 char *
147 authority_type_to_string(authority_type_t auth)
149 char *result;
150 smartlist_t *lst = smartlist_create();
151 if (auth & V1_AUTHORITY)
152 smartlist_add(lst, (void*)"V1");
153 if (auth & V2_AUTHORITY)
154 smartlist_add(lst, (void*)"V2");
155 if (auth & V3_AUTHORITY)
156 smartlist_add(lst, (void*)"V3");
157 if (auth & BRIDGE_AUTHORITY)
158 smartlist_add(lst, (void*)"Bridge");
159 if (auth & HIDSERV_AUTHORITY)
160 smartlist_add(lst, (void*)"Hidden service");
161 if (smartlist_len(lst)) {
162 result = smartlist_join_strings(lst, ", ", 0, NULL);
163 } else {
164 result = tor_strdup("[Not an authority]");
166 smartlist_free(lst);
167 return result;
170 /** Return a string describing a given directory connection purpose. */
171 static const char *
172 dir_conn_purpose_to_string(int purpose)
174 switch (purpose)
176 case DIR_PURPOSE_FETCH_RENDDESC:
177 return "hidden-service descriptor fetch";
178 case DIR_PURPOSE_UPLOAD_DIR:
179 return "server descriptor upload";
180 case DIR_PURPOSE_UPLOAD_RENDDESC:
181 return "hidden-service descriptor upload";
182 case DIR_PURPOSE_UPLOAD_VOTE:
183 return "server vote upload";
184 case DIR_PURPOSE_UPLOAD_SIGNATURES:
185 return "consensus signature upload";
186 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
187 return "network-status fetch";
188 case DIR_PURPOSE_FETCH_SERVERDESC:
189 return "server descriptor fetch";
190 case DIR_PURPOSE_FETCH_EXTRAINFO:
191 return "extra-info fetch";
192 case DIR_PURPOSE_FETCH_CONSENSUS:
193 return "consensus network-status fetch";
194 case DIR_PURPOSE_FETCH_CERTIFICATE:
195 return "authority cert fetch";
196 case DIR_PURPOSE_FETCH_STATUS_VOTE:
197 return "status vote fetch";
198 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
199 return "consensus signature fetch";
200 case DIR_PURPOSE_FETCH_RENDDESC_V2:
201 return "hidden-service v2 descriptor fetch";
202 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
203 return "hidden-service v2 descriptor upload";
206 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
207 return "(unknown)";
210 /** Return true iff <b>identity_digest</b> is the digest of a router we
211 * believe to support extrainfo downloads. (If <b>is_authority</b> we do
212 * additional checking that's only valid for authorities.) */
214 router_supports_extrainfo(const char *identity_digest, int is_authority)
216 routerinfo_t *ri = router_get_by_digest(identity_digest);
218 if (ri) {
219 if (ri->caches_extra_info)
220 return 1;
221 if (is_authority && ri->platform &&
222 tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
223 return 1;
225 if (is_authority) {
226 routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
227 if (rs && rs->version_supports_extrainfo_upload)
228 return 1;
230 return 0;
233 /** Return true iff any trusted directory authority has accepted our
234 * server descriptor.
236 * We consider any authority sufficient because waiting for all of
237 * them means it never happens while any authority is down; we don't
238 * go for something more complex in the middle (like \>1/3 or \>1/2 or
239 * \>=1/2) because that doesn't seem necessary yet.
242 directories_have_accepted_server_descriptor(void)
244 smartlist_t *servers = router_get_trusted_dir_servers();
245 or_options_t *options = get_options();
246 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
247 if ((d->type & options->_PublishServerDescriptor) &&
248 d->has_accepted_serverdesc) {
249 return 1;
252 return 0;
255 /** Start a connection to every suitable directory authority, using
256 * connection purpose <b>dir_purpose</b> and uploading <b>payload</b>
257 * (of length <b>payload_len</b>). The dir_purpose should be one of
258 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
260 * <b>router_purpose</b> describes the type of descriptor we're
261 * publishing, if we're publishing a descriptor -- e.g. general or bridge.
263 * <b>type</b> specifies what sort of dir authorities (V1, V2,
264 * HIDSERV, BRIDGE) we should upload to.
266 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
267 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
268 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
269 * to all authorities, and the extra-info document to all authorities that
270 * support it.
272 void
273 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
274 authority_type_t type,
275 const char *payload,
276 size_t payload_len, size_t extrainfo_len)
278 or_options_t *options = get_options();
279 int post_via_tor;
280 smartlist_t *dirservers = router_get_trusted_dir_servers();
281 int found = 0;
282 tor_assert(dirservers);
283 /* This tries dirservers which we believe to be down, but ultimately, that's
284 * harmless, and we may as well err on the side of getting things uploaded.
286 SMARTLIST_FOREACH_BEGIN(dirservers, trusted_dir_server_t *, ds) {
287 routerstatus_t *rs = &(ds->fake_status);
288 size_t upload_len = payload_len;
289 tor_addr_t ds_addr;
291 if ((type & ds->type) == 0)
292 continue;
294 if (options->ExcludeNodes && options->StrictNodes &&
295 routerset_contains_routerstatus(options->ExcludeNodes, rs)) {
296 log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
297 "it's in our ExcludedNodes list and StrictNodes is set. "
298 "Skipping.",
299 ds->nickname,
300 dir_conn_purpose_to_string(dir_purpose));
301 continue;
304 found = 1; /* at least one authority of this type was listed */
305 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
306 ds->has_accepted_serverdesc = 0;
308 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
309 upload_len += extrainfo_len;
310 log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
311 (int) extrainfo_len);
313 tor_addr_from_ipv4h(&ds_addr, ds->addr);
314 post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) ||
315 !fascist_firewall_allows_address_dir(&ds_addr, ds->dir_port);
316 directory_initiate_command_routerstatus(rs, dir_purpose,
317 router_purpose,
318 post_via_tor,
319 NULL, payload, upload_len, 0);
320 } SMARTLIST_FOREACH_END(ds);
321 if (!found) {
322 char *s = authority_type_to_string(type);
323 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
324 "of type '%s', but no authorities of that type listed!", s);
325 tor_free(s);
329 /** Start a connection to a random running directory server, using
330 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
331 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
332 * Use <b>pds_flags</b> as arguments to router_pick_directory_server()
333 * or router_pick_trusteddirserver().
335 void
336 directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
337 const char *resource, int pds_flags)
339 routerstatus_t *rs = NULL;
340 or_options_t *options = get_options();
341 int prefer_authority = directory_fetches_from_authorities(options);
342 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
343 authority_type_t type;
344 time_t if_modified_since = 0;
346 /* FFFF we could break this switch into its own function, and call
347 * it elsewhere in directory.c. -RD */
348 switch (dir_purpose) {
349 case DIR_PURPOSE_FETCH_EXTRAINFO:
350 type = EXTRAINFO_CACHE |
351 (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
352 V3_AUTHORITY);
353 break;
354 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
355 type = V2_AUTHORITY;
356 prefer_authority = 1; /* Only v2 authorities have these anyway. */
357 break;
358 case DIR_PURPOSE_FETCH_SERVERDESC:
359 type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
360 V3_AUTHORITY);
361 break;
362 case DIR_PURPOSE_FETCH_RENDDESC:
363 type = HIDSERV_AUTHORITY;
364 break;
365 case DIR_PURPOSE_FETCH_STATUS_VOTE:
366 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
367 type = V3_AUTHORITY;
368 break;
369 case DIR_PURPOSE_FETCH_CONSENSUS:
370 case DIR_PURPOSE_FETCH_CERTIFICATE:
371 type = V3_AUTHORITY;
372 break;
373 default:
374 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
375 return;
378 if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
379 networkstatus_t *v = networkstatus_get_latest_consensus();
380 if (v)
381 if_modified_since = v->valid_after + 180;
384 if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
385 return;
387 if (!get_via_tor) {
388 if (options->UseBridges && type != BRIDGE_AUTHORITY) {
389 /* want to ask a running bridge for which we have a descriptor. */
390 /* XXX023 we assume that all of our bridges can answer any
391 * possible directory question. This won't be true forever. -RD */
392 /* It certainly is not true with conditional consensus downloading,
393 * so, for now, never assume the server supports that. */
394 routerinfo_t *ri = choose_random_entry(NULL);
395 if (ri) {
396 tor_addr_t addr;
397 tor_addr_from_ipv4h(&addr, ri->addr);
398 directory_initiate_command(ri->address, &addr,
399 ri->or_port, 0,
400 0, /* don't use conditional consensus url */
401 1, ri->cache_info.identity_digest,
402 dir_purpose,
403 router_purpose,
404 0, resource, NULL, 0, if_modified_since);
405 } else
406 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
407 "nodes are available yet.");
408 return;
409 } else {
410 if (prefer_authority || type == BRIDGE_AUTHORITY) {
411 /* only ask authdirservers, and don't ask myself */
412 rs = router_pick_trusteddirserver(type, pds_flags);
413 if (rs == NULL && (pds_flags & PDS_NO_EXISTING_SERVERDESC_FETCH)) {
414 /* We don't want to fetch from any authorities that we're currently
415 * fetching server descriptors from, and we got no match. Did we
416 * get no match because all the authorities have connections
417 * fetching server descriptors (in which case we should just
418 * return,) or because all the authorities are down or on fire or
419 * unreachable or something (in which case we should go on with
420 * our fallback code)? */
421 pds_flags &= ~PDS_NO_EXISTING_SERVERDESC_FETCH;
422 rs = router_pick_trusteddirserver(type, pds_flags);
423 if (rs) {
424 log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
425 "are in use.");
426 return;
430 if (!rs && type != BRIDGE_AUTHORITY) {
431 /* anybody with a non-zero dirport will do */
432 rs = router_pick_directory_server(type, pds_flags);
433 if (!rs) {
434 log_info(LD_DIR, "No router found for %s; falling back to "
435 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
436 rs = router_pick_trusteddirserver(type, pds_flags);
437 if (!rs)
438 get_via_tor = 1; /* last resort: try routing it via Tor */
442 } else { /* get_via_tor */
443 /* Never use fascistfirewall; we're going via Tor. */
444 if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
445 /* only ask hidserv authorities, any of them will do */
446 pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
447 rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, pds_flags);
448 } else {
449 /* anybody with a non-zero dirport will do. Disregard firewalls. */
450 pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
451 rs = router_pick_directory_server(type, pds_flags);
452 /* If we have any hope of building an indirect conn, we know some router
453 * descriptors. If (rs==NULL), we can't build circuits anyway, so
454 * there's no point in falling back to the authorities in this case. */
458 if (rs)
459 directory_initiate_command_routerstatus(rs, dir_purpose,
460 router_purpose,
461 get_via_tor,
462 resource, NULL, 0,
463 if_modified_since);
464 else {
465 log_notice(LD_DIR,
466 "While fetching directory info, "
467 "no running dirservers known. Will try again later. "
468 "(purpose %d)", dir_purpose);
469 if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
470 /* remember we tried them all and failed. */
471 directory_all_unreachable(time(NULL));
476 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
477 * directory authority other than ourself. Only for use by authorities when
478 * searching for missing information while voting. */
479 void
480 directory_get_from_all_authorities(uint8_t dir_purpose,
481 uint8_t router_purpose,
482 const char *resource)
484 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
485 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
487 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
488 trusted_dir_server_t *, ds,
490 routerstatus_t *rs;
491 if (router_digest_is_me(ds->digest))
492 continue;
493 if (!(ds->type & V3_AUTHORITY))
494 continue;
495 rs = &ds->fake_status;
496 directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
497 0, resource, NULL, 0, 0);
501 /** Same as directory_initiate_command_routerstatus(), but accepts
502 * rendezvous data to fetch a hidden service descriptor. */
503 void
504 directory_initiate_command_routerstatus_rend(routerstatus_t *status,
505 uint8_t dir_purpose,
506 uint8_t router_purpose,
507 int anonymized_connection,
508 const char *resource,
509 const char *payload,
510 size_t payload_len,
511 time_t if_modified_since,
512 const rend_data_t *rend_query)
514 or_options_t *options = get_options();
515 routerinfo_t *router;
516 char address_buf[INET_NTOA_BUF_LEN+1];
517 struct in_addr in;
518 const char *address;
519 tor_addr_t addr;
520 router = router_get_by_digest(status->identity_digest);
522 if (!router && anonymized_connection) {
523 log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
524 "don't have its router descriptor.", status->nickname);
525 return;
526 } else if (router) {
527 address = router->address;
528 } else {
529 in.s_addr = htonl(status->addr);
530 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
531 address = address_buf;
533 tor_addr_from_ipv4h(&addr, status->addr);
535 if (options->ExcludeNodes && options->StrictNodes &&
536 routerset_contains_routerstatus(options->ExcludeNodes, status)) {
537 log_warn(LD_DIR, "Wanted to contact directory mirror '%s' for %s, but "
538 "it's in our ExcludedNodes list and StrictNodes is set. "
539 "Skipping. This choice might make your Tor not work.",
540 status->nickname,
541 dir_conn_purpose_to_string(dir_purpose));
542 return;
545 directory_initiate_command_rend(address, &addr,
546 status->or_port, status->dir_port,
547 status->version_supports_conditional_consensus,
548 status->version_supports_begindir,
549 status->identity_digest,
550 dir_purpose, router_purpose,
551 anonymized_connection, resource,
552 payload, payload_len, if_modified_since,
553 rend_query);
556 /** Launch a new connection to the directory server <b>status</b> to
557 * upload or download a server or rendezvous
558 * descriptor. <b>dir_purpose</b> determines what
559 * kind of directory connection we're launching, and must be one of
560 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC|RENDDESC_V2}. <b>router_purpose</b>
561 * specifies the descriptor purposes we have in mind (currently only
562 * used for FETCH_DIR).
564 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
565 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
567 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
568 * want to fetch.
570 void
571 directory_initiate_command_routerstatus(routerstatus_t *status,
572 uint8_t dir_purpose,
573 uint8_t router_purpose,
574 int anonymized_connection,
575 const char *resource,
576 const char *payload,
577 size_t payload_len,
578 time_t if_modified_since)
580 directory_initiate_command_routerstatus_rend(status, dir_purpose,
581 router_purpose,
582 anonymized_connection, resource,
583 payload, payload_len,
584 if_modified_since, NULL);
587 /** Return true iff <b>conn</b> is the client side of a directory connection
588 * we launched to ourself in order to determine the reachability of our
589 * dir_port. */
590 static int
591 directory_conn_is_self_reachability_test(dir_connection_t *conn)
593 if (conn->requested_resource &&
594 !strcmpstart(conn->requested_resource,"authority")) {
595 routerinfo_t *me = router_get_my_routerinfo();
596 if (me &&
597 router_digest_is_me(conn->identity_digest) &&
598 tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/
599 me->dir_port == conn->_base.port)
600 return 1;
602 return 0;
605 /** Called when we are unable to complete the client's request to a directory
606 * server due to a network error: Mark the router as down and try again if
607 * possible.
609 void
610 connection_dir_request_failed(dir_connection_t *conn)
612 if (directory_conn_is_self_reachability_test(conn)) {
613 return; /* this was a test fetch. don't retry. */
615 if (!entry_list_is_constrained(get_options()))
616 router_set_status(conn->identity_digest, 0); /* don't try him again */
617 if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
618 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
619 conn->_base.address);
620 connection_dir_download_v2_networkstatus_failed(conn, -1);
621 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
622 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
623 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
624 conn->_base.address);
625 if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
626 connection_dir_bridge_routerdesc_failed(conn);
627 connection_dir_download_routerdesc_failed(conn);
628 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
629 networkstatus_consensus_download_failed(0);
630 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
631 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
632 conn->_base.address);
633 connection_dir_download_cert_failed(conn, 0);
634 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
635 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
636 conn->_base.address);
637 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
638 log_info(LD_DIR, "Giving up downloading votes from '%s'",
639 conn->_base.address);
643 /** Called when an attempt to download one or more network status
644 * documents on connection <b>conn</b> failed. Decide whether to
645 * retry the fetch now, later, or never.
647 static void
648 connection_dir_download_v2_networkstatus_failed(dir_connection_t *conn,
649 int status_code)
651 if (!conn->requested_resource) {
652 /* We never reached directory_send_command, which means that we never
653 * opened a network connection. Either we're out of sockets, or the
654 * network is down. Either way, retrying would be pointless. */
655 return;
657 if (!strcmpstart(conn->requested_resource, "all")) {
658 /* We're a non-authoritative directory cache; try again. Ignore status
659 * code, since we don't want to keep trying forever in a tight loop
660 * if all the authorities are shutting us out. */
661 smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
662 SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
663 download_status_failed(&ds->v2_ns_dl_status, 0));
664 directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose,
665 "all.z", 0 /* don't retry_if_no_servers */);
666 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
667 /* We were trying to download by fingerprint; mark them all as having
668 * failed, and possibly retry them later.*/
669 smartlist_t *failed = smartlist_create();
670 dir_split_resource_into_fingerprints(conn->requested_resource+3,
671 failed, NULL, 0);
672 if (smartlist_len(failed)) {
673 dir_networkstatus_download_failed(failed, status_code);
674 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
676 smartlist_free(failed);
680 /** Helper: Attempt to fetch directly the descriptors of each bridge
681 * listed in <b>failed</b>.
683 static void
684 connection_dir_retry_bridges(smartlist_t *descs)
686 char digest[DIGEST_LEN];
687 SMARTLIST_FOREACH(descs, const char *, cp,
689 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
690 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
691 escaped(cp));
692 continue;
694 retry_bridge_descriptor_fetch_directly(digest);
698 /** Called when an attempt to download one or more router descriptors
699 * or extra-info documents on connection <b>conn</b> failed.
701 static void
702 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
704 /* No need to increment the failure count for routerdescs, since
705 * it's not their fault. */
707 /* No need to relaunch descriptor downloads here: we already do it
708 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
709 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
710 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
712 (void) conn;
715 /** Called when an attempt to download a bridge's routerdesc from
716 * one of the authorities failed due to a network error. If
717 * possible attempt to download descriptors from the bridge directly.
719 static void
720 connection_dir_bridge_routerdesc_failed(dir_connection_t *conn)
722 smartlist_t *which = NULL;
724 /* Requests for bridge descriptors are in the form 'fp/', so ignore
725 anything else. */
726 if (!conn->requested_resource || strcmpstart(conn->requested_resource,"fp/"))
727 return;
729 which = smartlist_create();
730 dir_split_resource_into_fingerprints(conn->requested_resource
731 + strlen("fp/"),
732 which, NULL, 0);
734 tor_assert(conn->_base.purpose != DIR_PURPOSE_FETCH_EXTRAINFO);
735 if (smartlist_len(which)) {
736 connection_dir_retry_bridges(which);
737 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
739 smartlist_free(which);
742 /** Called when an attempt to fetch a certificate fails. */
743 static void
744 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
746 smartlist_t *failed;
747 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
749 if (!conn->requested_resource)
750 return;
751 failed = smartlist_create();
752 dir_split_resource_into_fingerprints(conn->requested_resource+3,
753 failed, NULL, DSR_HEX);
754 SMARTLIST_FOREACH(failed, char *, cp,
756 authority_cert_dl_failed(cp, status);
757 tor_free(cp);
759 smartlist_free(failed);
761 update_certificate_downloads(time(NULL));
764 /** Evaluate the situation and decide if we should use an encrypted
765 * "begindir-style" connection for this directory request.
766 * 1) If or_port is 0, or it's a direct conn and or_port is firewalled
767 * or we're a dir mirror, no.
768 * 2) If we prefer to avoid begindir conns, and we're not fetching or
769 * publishing a bridge relay descriptor, no.
770 * 3) Else yes.
772 static int
773 directory_command_should_use_begindir(or_options_t *options,
774 const tor_addr_t *addr,
775 int or_port, uint8_t router_purpose,
776 int anonymized_connection)
778 if (!or_port)
779 return 0; /* We don't know an ORPort -- no chance. */
780 if (!anonymized_connection)
781 if (!fascist_firewall_allows_address_or(addr, or_port) ||
782 directory_fetches_from_authorities(options) ||
783 (server_mode(options) && !options->Address))
784 return 0; /* We're firewalled or are acting like a relay -- also no. */
785 if (!options->TunnelDirConns &&
786 router_purpose != ROUTER_PURPOSE_BRIDGE)
787 return 0; /* We prefer to avoid using begindir conns. Fine. */
788 return 1;
791 /** Helper for directory_initiate_command_routerstatus: send the
792 * command to a server whose address is <b>address</b>, whose IP is
793 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
794 * <b>supports_begindir</b>, and whose identity key digest is
795 * <b>digest</b>. */
796 void
797 directory_initiate_command(const char *address, const tor_addr_t *_addr,
798 uint16_t or_port, uint16_t dir_port,
799 int supports_conditional_consensus,
800 int supports_begindir, const char *digest,
801 uint8_t dir_purpose, uint8_t router_purpose,
802 int anonymized_connection, const char *resource,
803 const char *payload, size_t payload_len,
804 time_t if_modified_since)
806 directory_initiate_command_rend(address, _addr, or_port, dir_port,
807 supports_conditional_consensus,
808 supports_begindir, digest, dir_purpose,
809 router_purpose, anonymized_connection,
810 resource, payload, payload_len,
811 if_modified_since, NULL);
814 /** Same as directory_initiate_command(), but accepts rendezvous data to
815 * fetch a hidden service descriptor. */
816 static void
817 directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
818 uint16_t or_port, uint16_t dir_port,
819 int supports_conditional_consensus,
820 int supports_begindir, const char *digest,
821 uint8_t dir_purpose, uint8_t router_purpose,
822 int anonymized_connection,
823 const char *resource,
824 const char *payload, size_t payload_len,
825 time_t if_modified_since,
826 const rend_data_t *rend_query)
828 dir_connection_t *conn;
829 or_options_t *options = get_options();
830 int socket_error = 0;
831 int use_begindir = supports_begindir &&
832 directory_command_should_use_begindir(options, _addr,
833 or_port, router_purpose, anonymized_connection);
834 tor_addr_t addr;
836 tor_assert(address);
837 tor_assert(_addr);
838 tor_assert(or_port || dir_port);
839 tor_assert(digest);
841 tor_addr_copy(&addr, _addr);
843 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
844 anonymized_connection, use_begindir);
846 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
848 /* ensure that we don't make direct connections when a SOCKS server is
849 * configured. */
850 if (!anonymized_connection && !use_begindir && !options->HTTPProxy &&
851 (options->Socks4Proxy || options->Socks5Proxy)) {
852 log_warn(LD_DIR, "Cannot connect to a directory server through a "
853 "SOCKS proxy!");
854 return;
857 conn = dir_connection_new(AF_INET);
859 /* set up conn so it's got all the data we need to remember */
860 tor_addr_copy(&conn->_base.addr, &addr);
861 conn->_base.port = use_begindir ? or_port : dir_port;
862 conn->_base.address = tor_strdup(address);
863 memcpy(conn->identity_digest, digest, DIGEST_LEN);
865 conn->_base.purpose = dir_purpose;
866 conn->router_purpose = router_purpose;
868 /* give it an initial state */
869 conn->_base.state = DIR_CONN_STATE_CONNECTING;
871 /* decide whether we can learn our IP address from this conn */
872 conn->dirconn_direct = !anonymized_connection;
874 /* copy rendezvous data, if any */
875 if (rend_query)
876 conn->rend_data = rend_data_dup(rend_query);
878 if (!anonymized_connection && !use_begindir) {
879 /* then we want to connect to dirport directly */
881 if (options->HTTPProxy) {
882 tor_addr_copy(&addr, &options->HTTPProxyAddr);
883 dir_port = options->HTTPProxyPort;
886 switch (connection_connect(TO_CONN(conn), conn->_base.address, &addr,
887 dir_port, &socket_error)) {
888 case -1:
889 connection_dir_request_failed(conn); /* retry if we want */
890 /* XXX we only pass 'conn' above, not 'resource', 'payload',
891 * etc. So in many situations it can't retry! -RD */
892 connection_free(TO_CONN(conn));
893 return;
894 case 1:
895 /* start flushing conn */
896 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
897 /* fall through */
898 case 0:
899 /* queue the command on the outbuf */
900 directory_send_command(conn, dir_purpose, 1, resource,
901 payload, payload_len,
902 supports_conditional_consensus,
903 if_modified_since);
904 connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT);
905 /* writable indicates finish, readable indicates broken link,
906 error indicates broken link in windowsland. */
908 } else { /* we want to connect via a tor connection */
909 edge_connection_t *linked_conn;
911 /* If it's an anonymized connection, remember the fact that we
912 * wanted it for later: maybe we'll want it again soon. */
913 if (anonymized_connection && use_begindir)
914 rep_hist_note_used_internal(time(NULL), 0, 1);
915 else if (anonymized_connection && !use_begindir)
916 rep_hist_note_used_port(time(NULL), conn->_base.port);
918 /* make an AP connection
919 * populate it and add it at the right state
920 * hook up both sides
922 linked_conn =
923 connection_ap_make_link(conn->_base.address, conn->_base.port,
924 digest, use_begindir, conn->dirconn_direct);
925 if (!linked_conn) {
926 log_warn(LD_NET,"Making tunnel to dirserver failed.");
927 connection_mark_for_close(TO_CONN(conn));
928 return;
930 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
932 if (connection_add(TO_CONN(conn)) < 0) {
933 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
934 connection_mark_for_close(TO_CONN(conn));
935 return;
937 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
938 /* queue the command on the outbuf */
939 directory_send_command(conn, dir_purpose, 0, resource,
940 payload, payload_len,
941 supports_conditional_consensus,
942 if_modified_since);
943 connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
944 connection_start_reading(TO_CONN(linked_conn));
948 /** Return true iff anything we say on <b>conn</b> is being encrypted before
949 * we send it to the client/server. */
951 connection_dir_is_encrypted(dir_connection_t *conn)
953 /* Right now it's sufficient to see if conn is or has been linked, since
954 * the only thing it could be linked to is an edge connection on a
955 * circuit, and the only way it could have been unlinked is at the edge
956 * connection getting closed.
958 return TO_CONN(conn)->linked;
961 /** Helper for sorting
963 * sort strings alphabetically
965 static int
966 _compare_strs(const void **a, const void **b)
968 const char *s1 = *a, *s2 = *b;
969 return strcmp(s1, s2);
972 #define CONDITIONAL_CONSENSUS_FPR_LEN 3
973 #if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
974 #error "conditional consensus fingerprint length is larger than digest length"
975 #endif
977 /** Return the URL we should use for a consensus download.
979 * This url depends on whether or not the server we go to
980 * is sufficiently new to support conditional consensus downloading,
981 * i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
983 static char *
984 directory_get_consensus_url(int supports_conditional_consensus)
986 char *url;
987 size_t len;
989 if (supports_conditional_consensus) {
990 char *authority_id_list;
991 smartlist_t *authority_digests = smartlist_create();
993 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
994 trusted_dir_server_t *, ds,
996 char *hex;
997 if (!(ds->type & V3_AUTHORITY))
998 continue;
1000 hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
1001 base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
1002 ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN);
1003 smartlist_add(authority_digests, hex);
1005 smartlist_sort(authority_digests, _compare_strs);
1006 authority_id_list = smartlist_join_strings(authority_digests,
1007 "+", 0, NULL);
1009 len = strlen(authority_id_list)+64;
1010 url = tor_malloc(len);
1011 tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z",
1012 authority_id_list);
1014 SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
1015 smartlist_free(authority_digests);
1016 tor_free(authority_id_list);
1017 } else {
1018 url = tor_strdup("/tor/status-vote/current/consensus.z");
1020 return url;
1023 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
1024 * are as in directory_initiate_command().
1026 static void
1027 directory_send_command(dir_connection_t *conn,
1028 int purpose, int direct, const char *resource,
1029 const char *payload, size_t payload_len,
1030 int supports_conditional_consensus,
1031 time_t if_modified_since)
1033 char proxystring[256];
1034 char proxyauthstring[256];
1035 char hoststring[128];
1036 char imsstring[RFC1123_TIME_LEN+32];
1037 char *url;
1038 char request[8192];
1039 const char *httpcommand = NULL;
1040 size_t len;
1042 tor_assert(conn);
1043 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1045 tor_free(conn->requested_resource);
1046 if (resource)
1047 conn->requested_resource = tor_strdup(resource);
1049 /* come up with a string for which Host: we want */
1050 if (conn->_base.port == 80) {
1051 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
1052 } else {
1053 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
1054 conn->_base.address, conn->_base.port);
1057 /* Format if-modified-since */
1058 if (!if_modified_since) {
1059 imsstring[0] = '\0';
1060 } else {
1061 char b[RFC1123_TIME_LEN+1];
1062 format_rfc1123_time(b, if_modified_since);
1063 tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
1066 /* come up with some proxy lines, if we're using one. */
1067 if (direct && get_options()->HTTPProxy) {
1068 char *base64_authenticator=NULL;
1069 const char *authenticator = get_options()->HTTPProxyAuthenticator;
1071 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
1072 if (authenticator) {
1073 base64_authenticator = alloc_http_authenticator(authenticator);
1074 if (!base64_authenticator)
1075 log_warn(LD_BUG, "Encoding http authenticator failed");
1077 if (base64_authenticator) {
1078 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
1079 "\r\nProxy-Authorization: Basic %s",
1080 base64_authenticator);
1081 tor_free(base64_authenticator);
1082 } else {
1083 proxyauthstring[0] = 0;
1085 } else {
1086 proxystring[0] = 0;
1087 proxyauthstring[0] = 0;
1090 switch (purpose) {
1091 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
1092 tor_assert(resource);
1093 httpcommand = "GET";
1094 len = strlen(resource)+32;
1095 url = tor_malloc(len);
1096 tor_snprintf(url, len, "/tor/status/%s", resource);
1097 break;
1098 case DIR_PURPOSE_FETCH_CONSENSUS:
1099 tor_assert(!resource);
1100 tor_assert(!payload);
1101 httpcommand = "GET";
1102 url = directory_get_consensus_url(supports_conditional_consensus);
1103 log_info(LD_DIR, "Downloading consensus from %s using %s",
1104 hoststring, url);
1105 break;
1106 case DIR_PURPOSE_FETCH_CERTIFICATE:
1107 tor_assert(resource);
1108 tor_assert(!payload);
1109 httpcommand = "GET";
1110 len = strlen(resource)+32;
1111 url = tor_malloc(len);
1112 tor_snprintf(url, len, "/tor/keys/%s", resource);
1113 break;
1114 case DIR_PURPOSE_FETCH_STATUS_VOTE:
1115 tor_assert(resource);
1116 tor_assert(!payload);
1117 httpcommand = "GET";
1118 len = strlen(resource)+32;
1119 url = tor_malloc(len);
1120 tor_snprintf(url, len, "/tor/status-vote/next/%s.z", resource);
1121 break;
1122 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
1123 tor_assert(!resource);
1124 tor_assert(!payload);
1125 httpcommand = "GET";
1126 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
1127 break;
1128 case DIR_PURPOSE_FETCH_SERVERDESC:
1129 tor_assert(resource);
1130 httpcommand = "GET";
1131 len = strlen(resource)+32;
1132 url = tor_malloc(len);
1133 tor_snprintf(url, len, "/tor/server/%s", resource);
1134 break;
1135 case DIR_PURPOSE_FETCH_EXTRAINFO:
1136 tor_assert(resource);
1137 httpcommand = "GET";
1138 len = strlen(resource)+32;
1139 url = tor_malloc(len);
1140 tor_snprintf(url, len, "/tor/extra/%s", resource);
1141 break;
1142 case DIR_PURPOSE_UPLOAD_DIR:
1143 tor_assert(!resource);
1144 tor_assert(payload);
1145 httpcommand = "POST";
1146 url = tor_strdup("/tor/");
1147 break;
1148 case DIR_PURPOSE_UPLOAD_VOTE:
1149 tor_assert(!resource);
1150 tor_assert(payload);
1151 httpcommand = "POST";
1152 url = tor_strdup("/tor/post/vote");
1153 break;
1154 case DIR_PURPOSE_UPLOAD_SIGNATURES:
1155 tor_assert(!resource);
1156 tor_assert(payload);
1157 httpcommand = "POST";
1158 url = tor_strdup("/tor/post/consensus-signature");
1159 break;
1160 case DIR_PURPOSE_FETCH_RENDDESC_V2:
1161 tor_assert(resource);
1162 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
1163 tor_assert(!payload);
1164 httpcommand = "GET";
1165 len = strlen(resource) + 32;
1166 url = tor_malloc(len);
1167 tor_snprintf(url, len, "/tor/rendezvous2/%s", resource);
1168 break;
1169 case DIR_PURPOSE_UPLOAD_RENDDESC:
1170 tor_assert(!resource);
1171 tor_assert(payload);
1172 httpcommand = "POST";
1173 url = tor_strdup("/tor/rendezvous/publish");
1174 break;
1175 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
1176 tor_assert(!resource);
1177 tor_assert(payload);
1178 httpcommand = "POST";
1179 url = tor_strdup("/tor/rendezvous2/publish");
1180 break;
1181 default:
1182 tor_assert(0);
1183 return;
1186 if (strlen(proxystring) + strlen(url) >= 4096) {
1187 log_warn(LD_BUG,
1188 "Squid does not like URLs longer than 4095 bytes, and this "
1189 "one is %d bytes long: %s%s",
1190 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
1193 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
1194 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1195 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
1196 tor_free(url);
1198 if (!strcmp(httpcommand, "GET") && !payload) {
1199 tor_snprintf(request, sizeof(request),
1200 " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
1201 hoststring,
1202 imsstring,
1203 proxyauthstring);
1204 } else {
1205 tor_snprintf(request, sizeof(request),
1206 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
1207 payload ? (unsigned long)payload_len : 0,
1208 hoststring,
1209 imsstring,
1210 proxyauthstring);
1212 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1214 if (payload) {
1215 /* then send the payload afterwards too */
1216 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
1220 /** Parse an HTTP request string <b>headers</b> of the form
1221 * \verbatim
1222 * "\%s [http[s]://]\%s HTTP/1..."
1223 * \endverbatim
1224 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
1225 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
1226 * so it does. Return 0.
1227 * Otherwise, return -1.
1229 static int
1230 parse_http_url(const char *headers, char **url)
1232 char *s, *start, *tmp;
1234 s = (char *)eat_whitespace_no_nl(headers);
1235 if (!*s) return -1;
1236 s = (char *)find_whitespace(s); /* get past GET/POST */
1237 if (!*s) return -1;
1238 s = (char *)eat_whitespace_no_nl(s);
1239 if (!*s) return -1;
1240 start = s; /* this is it, assuming it's valid */
1241 s = (char *)find_whitespace(start);
1242 if (!*s) return -1;
1244 /* tolerate the http[s] proxy style of putting the hostname in the url */
1245 if (s-start >= 4 && !strcmpstart(start,"http")) {
1246 tmp = start + 4;
1247 if (*tmp == 's')
1248 tmp++;
1249 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
1250 tmp = strchr(tmp+3, '/');
1251 if (tmp && tmp < s) {
1252 log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
1253 start = tmp;
1258 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
1259 *url = tor_malloc(s - start + 5);
1260 strlcpy(*url,"/tor", s-start+5);
1261 strlcat((*url)+4, start, s-start+1);
1262 } else {
1263 *url = tor_strndup(start, s-start);
1265 return 0;
1268 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1269 * <b>which</b>. The key should be given with a terminating colon and space;
1270 * this function copies everything after, up to but not including the
1271 * following \\r\\n. */
1272 static char *
1273 http_get_header(const char *headers, const char *which)
1275 const char *cp = headers;
1276 while (cp) {
1277 if (!strcasecmpstart(cp, which)) {
1278 char *eos;
1279 cp += strlen(which);
1280 if ((eos = strchr(cp,'\r')))
1281 return tor_strndup(cp, eos-cp);
1282 else
1283 return tor_strdup(cp);
1285 cp = strchr(cp, '\n');
1286 if (cp)
1287 ++cp;
1289 return NULL;
1292 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1293 * <b>conn</b>-\>address to describe our best guess of the address that
1294 * originated this HTTP request. */
1295 static void
1296 http_set_address_origin(const char *headers, connection_t *conn)
1298 char *fwd;
1300 fwd = http_get_header(headers, "Forwarded-For: ");
1301 if (!fwd)
1302 fwd = http_get_header(headers, "X-Forwarded-For: ");
1303 if (fwd) {
1304 struct in_addr in;
1305 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
1306 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
1307 escaped(fwd));
1308 tor_free(fwd);
1309 return;
1311 tor_free(conn->address);
1312 conn->address = tor_strdup(fwd);
1313 tor_free(fwd);
1317 /** Parse an HTTP response string <b>headers</b> of the form
1318 * \verbatim
1319 * "HTTP/1.\%d \%d\%s\r\n...".
1320 * \endverbatim
1322 * If it's well-formed, assign the status code to *<b>code</b> and
1323 * return 0. Otherwise, return -1.
1325 * On success: If <b>date</b> is provided, set *date to the Date
1326 * header in the http headers, or 0 if no such header is found. If
1327 * <b>compression</b> is provided, set *<b>compression</b> to the
1328 * compression method given in the Content-Encoding header, or 0 if no
1329 * such header is found, or -1 if the value of the header is not
1330 * recognized. If <b>reason</b> is provided, strdup the reason string
1331 * into it.
1334 parse_http_response(const char *headers, int *code, time_t *date,
1335 compress_method_t *compression, char **reason)
1337 unsigned n1, n2;
1338 char datestr[RFC1123_TIME_LEN+1];
1339 smartlist_t *parsed_headers;
1340 tor_assert(headers);
1341 tor_assert(code);
1343 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1345 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
1346 (n1 != 0 && n1 != 1) ||
1347 (n2 < 100 || n2 >= 600)) {
1348 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1349 return -1;
1351 *code = n2;
1353 parsed_headers = smartlist_create();
1354 smartlist_split_string(parsed_headers, headers, "\n",
1355 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1356 if (reason) {
1357 smartlist_t *status_line_elements = smartlist_create();
1358 tor_assert(smartlist_len(parsed_headers));
1359 smartlist_split_string(status_line_elements,
1360 smartlist_get(parsed_headers, 0),
1361 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1362 tor_assert(smartlist_len(status_line_elements) <= 3);
1363 if (smartlist_len(status_line_elements) == 3) {
1364 *reason = smartlist_get(status_line_elements, 2);
1365 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1367 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1368 smartlist_free(status_line_elements);
1370 if (date) {
1371 *date = 0;
1372 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1373 if (!strcmpstart(s, "Date: ")) {
1374 strlcpy(datestr, s+6, sizeof(datestr));
1375 /* This will do nothing on failure, so we don't need to check
1376 the result. We shouldn't warn, since there are many other valid
1377 date formats besides the one we use. */
1378 parse_rfc1123_time(datestr, date);
1379 break;
1382 if (compression) {
1383 const char *enc = NULL;
1384 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1385 if (!strcmpstart(s, "Content-Encoding: ")) {
1386 enc = s+18; break;
1388 if (!enc || !strcmp(enc, "identity")) {
1389 *compression = NO_METHOD;
1390 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1391 *compression = ZLIB_METHOD;
1392 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1393 *compression = GZIP_METHOD;
1394 } else {
1395 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1396 escaped(enc));
1397 *compression = UNKNOWN_METHOD;
1400 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1401 smartlist_free(parsed_headers);
1403 return 0;
1406 /** Return true iff <b>body</b> doesn't start with a plausible router or
1407 * running-list or directory opening. This is a sign of possible compression.
1409 static int
1410 body_is_plausible(const char *body, size_t len, int purpose)
1412 int i;
1413 if (len == 0)
1414 return 1; /* empty bodies don't need decompression */
1415 if (len < 32)
1416 return 0;
1417 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
1418 if (!strcmpstart(body,"router") ||
1419 !strcmpstart(body,"signed-directory") ||
1420 !strcmpstart(body,"network-status") ||
1421 !strcmpstart(body,"running-routers"))
1422 return 1;
1423 for (i=0;i<32;++i) {
1424 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1425 return 0;
1427 return 1;
1428 } else {
1429 return 1;
1433 /** Called when we've just fetched a bunch of router descriptors in
1434 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1435 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1436 * is true, or identity digests otherwise. Parse the descriptors, validate
1437 * them, and annotate them as having purpose <b>purpose</b> and as having been
1438 * downloaded from <b>source</b>.
1440 * Return the number of routers actually added. */
1441 static int
1442 load_downloaded_routers(const char *body, smartlist_t *which,
1443 int descriptor_digests,
1444 int router_purpose,
1445 const char *source)
1447 char buf[256];
1448 char time_buf[ISO_TIME_LEN+1];
1449 int added = 0;
1450 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1451 format_iso_time(time_buf, time(NULL));
1452 tor_assert(source);
1454 if (tor_snprintf(buf, sizeof(buf),
1455 "@downloaded-at %s\n"
1456 "@source %s\n"
1457 "%s%s%s", time_buf, escaped(source),
1458 !general ? "@purpose " : "",
1459 !general ? router_purpose_to_string(router_purpose) : "",
1460 !general ? "\n" : "")<0)
1461 return added;
1463 added = router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1464 descriptor_digests, buf);
1465 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
1466 count_loading_descriptors_progress());
1467 return added;
1470 /** We are a client, and we've finished reading the server's
1471 * response. Parse it and act appropriately.
1473 * If we're still happy with using this directory server in the future, return
1474 * 0. Otherwise return -1; and the caller should consider trying the request
1475 * again.
1477 * The caller will take care of marking the connection for close.
1479 static int
1480 connection_dir_client_reached_eof(dir_connection_t *conn)
1482 char *body;
1483 char *headers;
1484 char *reason = NULL;
1485 size_t body_len=0, orig_len=0;
1486 int status_code;
1487 time_t date_header=0;
1488 long delta;
1489 compress_method_t compression;
1490 int plausible;
1491 int skewed=0;
1492 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1493 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
1494 int was_compressed=0;
1495 time_t now = time(NULL);
1497 switch (fetch_from_buf_http(conn->_base.inbuf,
1498 &headers, MAX_HEADERS_SIZE,
1499 &body, &body_len, MAX_DIR_DL_SIZE,
1500 allow_partial)) {
1501 case -1: /* overflow */
1502 log_warn(LD_PROTOCOL,
1503 "'fetch' response too large (server '%s:%d'). Closing.",
1504 conn->_base.address, conn->_base.port);
1505 return -1;
1506 case 0:
1507 log_info(LD_HTTP,
1508 "'fetch' response not all here, but we're at eof. Closing.");
1509 return -1;
1510 /* case 1, fall through */
1512 orig_len = body_len;
1514 if (parse_http_response(headers, &status_code, &date_header,
1515 &compression, &reason) < 0) {
1516 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1517 conn->_base.address, conn->_base.port);
1518 tor_free(body); tor_free(headers);
1519 return -1;
1521 if (!reason) reason = tor_strdup("[no reason given]");
1523 log_debug(LD_DIR,
1524 "Received response from directory server '%s:%d': %d %s",
1525 conn->_base.address, conn->_base.port, status_code,
1526 escaped(reason));
1528 /* now check if it's got any hints for us about our IP address. */
1529 if (conn->dirconn_direct) {
1530 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1531 if (guess) {
1532 router_new_address_suggestion(guess, conn);
1533 tor_free(guess);
1537 if (date_header > 0) {
1538 /* The date header was written very soon after we sent our request,
1539 * so compute the skew as the difference between sending the request
1540 * and the date header. (We used to check now-date_header, but that's
1541 * inaccurate if we spend a lot of time downloading.)
1543 delta = conn->_base.timestamp_lastwritten - date_header;
1544 if (labs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1545 char dbuf[64];
1546 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1547 format_time_interval(dbuf, sizeof(dbuf), delta);
1548 log_fn(trusted ? LOG_WARN : LOG_INFO,
1549 LD_HTTP,
1550 "Received directory with skewed time (server '%s:%d'): "
1551 "It seems that our clock is %s by %s, or that theirs is %s. "
1552 "Tor requires an accurate clock to work: please check your time, "
1553 "timezone, and date settings.",
1554 conn->_base.address, conn->_base.port,
1555 delta>0 ? "ahead" : "behind", dbuf,
1556 delta>0 ? "behind" : "ahead");
1557 skewed = 1; /* don't check the recommended-versions line */
1558 if (trusted)
1559 control_event_general_status(LOG_WARN,
1560 "CLOCK_SKEW SKEW=%ld SOURCE=DIRSERV:%s:%d",
1561 delta, conn->_base.address, conn->_base.port);
1562 } else {
1563 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1564 "we are %ld seconds skewed. (That's okay.)", delta);
1567 (void) skewed; /* skewed isn't used yet. */
1569 if (status_code == 503) {
1570 routerstatus_t *rs;
1571 trusted_dir_server_t *ds;
1572 log_info(LD_DIR,"Received http status code %d (%s) from server "
1573 "'%s:%d'. I'll try again soon.",
1574 status_code, escaped(reason), conn->_base.address,
1575 conn->_base.port);
1576 if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
1577 rs->last_dir_503_at = now;
1578 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1579 ds->fake_status.last_dir_503_at = now;
1581 tor_free(body); tor_free(headers); tor_free(reason);
1582 return -1;
1585 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1586 if (compression != NO_METHOD || !plausible) {
1587 char *new_body = NULL;
1588 size_t new_len = 0;
1589 compress_method_t guessed = detect_compression_method(body, body_len);
1590 if (compression == UNKNOWN_METHOD || guessed != compression) {
1591 /* Tell the user if we don't believe what we're told about compression.*/
1592 const char *description1, *description2;
1593 if (compression == ZLIB_METHOD)
1594 description1 = "as deflated";
1595 else if (compression == GZIP_METHOD)
1596 description1 = "as gzipped";
1597 else if (compression == NO_METHOD)
1598 description1 = "as uncompressed";
1599 else
1600 description1 = "with an unknown Content-Encoding";
1601 if (guessed == ZLIB_METHOD)
1602 description2 = "deflated";
1603 else if (guessed == GZIP_METHOD)
1604 description2 = "gzipped";
1605 else if (!plausible)
1606 description2 = "confusing binary junk";
1607 else
1608 description2 = "uncompressed";
1610 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1611 "but it seems to be %s.%s",
1612 conn->_base.address, conn->_base.port, description1,
1613 description2,
1614 (compression>0 && guessed>0)?" Trying both.":"");
1616 /* Try declared compression first if we can. */
1617 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1618 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1619 !allow_partial, LOG_PROTOCOL_WARN);
1620 /* Okay, if that didn't work, and we think that it was compressed
1621 * differently, try that. */
1622 if (!new_body &&
1623 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1624 compression != guessed)
1625 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1626 !allow_partial, LOG_PROTOCOL_WARN);
1627 /* If we're pretty sure that we have a compressed directory, and
1628 * we didn't manage to uncompress it, then warn and bail. */
1629 if (!plausible && !new_body) {
1630 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1631 "Unable to decompress HTTP body (server '%s:%d').",
1632 conn->_base.address, conn->_base.port);
1633 tor_free(body); tor_free(headers); tor_free(reason);
1634 return -1;
1636 if (new_body) {
1637 tor_free(body);
1638 body = new_body;
1639 body_len = new_len;
1640 was_compressed = 1;
1644 if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
1645 smartlist_t *which = NULL;
1646 v2_networkstatus_source_t source;
1647 char *cp;
1648 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1649 "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
1650 if (status_code != 200) {
1651 static ratelim_t warning_limit = RATELIM_INIT(3600);
1652 char *m;
1653 if ((m = rate_limit_log(&warning_limit, now))) {
1654 log_warn(LD_DIR,
1655 "Received http status code %d (%s) from server "
1656 "'%s:%d' while fetching \"/tor/status/%s\". "
1657 "I'll try again soon.%s",
1658 status_code, escaped(reason), conn->_base.address,
1659 conn->_base.port, conn->requested_resource, m);
1660 tor_free(m);
1662 tor_free(body); tor_free(headers); tor_free(reason);
1663 connection_dir_download_v2_networkstatus_failed(conn, status_code);
1664 return -1;
1666 if (conn->requested_resource &&
1667 !strcmpstart(conn->requested_resource,"fp/")) {
1668 source = NS_FROM_DIR_BY_FP;
1669 which = smartlist_create();
1670 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1671 which, NULL, 0);
1672 } else if (conn->requested_resource &&
1673 !strcmpstart(conn->requested_resource, "all")) {
1674 source = NS_FROM_DIR_ALL;
1675 which = smartlist_create();
1676 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1677 trusted_dir_server_t *, ds,
1679 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1680 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1681 smartlist_add(which, hex);
1683 } else {
1684 /* XXXX Can we even end up here? -- weasel*/
1685 source = NS_FROM_DIR_BY_FP;
1686 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1687 "for it by fp, nor did we ask for all.");
1689 cp = body;
1690 while (*cp) {
1691 char *next = strstr(cp, "\nnetwork-status-version");
1692 if (next)
1693 next[1] = '\0';
1694 /* learn from it, and then remove it from 'which' */
1695 if (router_set_networkstatus_v2(cp, now, source, which)<0)
1696 break;
1697 if (next) {
1698 next[1] = 'n';
1699 cp = next+1;
1700 } else
1701 break;
1703 /* launches router downloads as needed */
1704 routers_update_all_from_networkstatus(now, 2);
1705 directory_info_has_arrived(now, 0);
1706 if (which) {
1707 if (smartlist_len(which)) {
1708 dir_networkstatus_download_failed(which, status_code);
1710 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1711 smartlist_free(which);
1715 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1716 int r;
1717 if (status_code != 200) {
1718 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1719 log(severity, LD_DIR,
1720 "Received http status code %d (%s) from server "
1721 "'%s:%d' while fetching consensus directory.",
1722 status_code, escaped(reason), conn->_base.address,
1723 conn->_base.port);
1724 tor_free(body); tor_free(headers); tor_free(reason);
1725 networkstatus_consensus_download_failed(status_code);
1726 return -1;
1728 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1729 "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
1730 if ((r=networkstatus_set_current_consensus(body, "ns", 0))<0) {
1731 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1732 "Unable to load consensus directory downloaded from "
1733 "server '%s:%d'. I'll try again soon.",
1734 conn->_base.address, conn->_base.port);
1735 tor_free(body); tor_free(headers); tor_free(reason);
1736 networkstatus_consensus_download_failed(0);
1737 return -1;
1739 /* launches router downloads as needed */
1740 routers_update_all_from_networkstatus(now, 3);
1741 directory_info_has_arrived(now, 0);
1742 log_info(LD_DIR, "Successfully loaded consensus.");
1745 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1746 if (status_code != 200) {
1747 log_warn(LD_DIR,
1748 "Received http status code %d (%s) from server "
1749 "'%s:%d' while fetching \"/tor/keys/%s\".",
1750 status_code, escaped(reason), conn->_base.address,
1751 conn->_base.port, conn->requested_resource);
1752 connection_dir_download_cert_failed(conn, status_code);
1753 tor_free(body); tor_free(headers); tor_free(reason);
1754 return -1;
1756 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1757 "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
1758 if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) {
1759 log_warn(LD_DIR, "Unable to parse fetched certificates");
1760 /* if we fetched more than one and only some failed, the successful
1761 * ones got flushed to disk so it's safe to call this on them */
1762 connection_dir_download_cert_failed(conn, status_code);
1763 } else {
1764 directory_info_has_arrived(now, 0);
1765 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1768 if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1769 const char *msg;
1770 int st;
1771 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1772 (int)body_len, conn->_base.address, conn->_base.port);
1773 if (status_code != 200) {
1774 log_warn(LD_DIR,
1775 "Received http status code %d (%s) from server "
1776 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1777 status_code, escaped(reason), conn->_base.address,
1778 conn->_base.port, conn->requested_resource);
1779 tor_free(body); tor_free(headers); tor_free(reason);
1780 return -1;
1782 dirvote_add_vote(body, &msg, &st);
1783 if (st > 299) {
1784 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1785 } else {
1786 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1789 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1790 const char *msg = NULL;
1791 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1792 (int)body_len, conn->_base.address, conn->_base.port);
1793 if (status_code != 200) {
1794 log_warn(LD_DIR,
1795 "Received http status code %d (%s) from server '%s:%d' while fetching "
1796 "\"/tor/status-vote/next/consensus-signatures.z\".",
1797 status_code, escaped(reason), conn->_base.address,
1798 conn->_base.port);
1799 tor_free(body); tor_free(headers); tor_free(reason);
1800 return -1;
1802 if (dirvote_add_signatures(body, conn->_base.address, &msg)<0) {
1803 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1804 conn->_base.address, conn->_base.port, msg?msg:"???");
1808 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1809 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1810 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1811 smartlist_t *which = NULL;
1812 int n_asked_for = 0;
1813 int descriptor_digests = conn->requested_resource &&
1814 !strcmpstart(conn->requested_resource,"d/");
1815 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1816 was_ei ? "extra server info" : "server info",
1817 (int)body_len, conn->_base.address, conn->_base.port);
1818 if (conn->requested_resource &&
1819 (!strcmpstart(conn->requested_resource,"d/") ||
1820 !strcmpstart(conn->requested_resource,"fp/"))) {
1821 which = smartlist_create();
1822 dir_split_resource_into_fingerprints(conn->requested_resource +
1823 (descriptor_digests ? 2 : 3),
1824 which, NULL, 0);
1825 n_asked_for = smartlist_len(which);
1827 if (status_code != 200) {
1828 int dir_okay = status_code == 404 ||
1829 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1830 /* 404 means that it didn't have them; no big deal.
1831 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1832 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1833 "Received http status code %d (%s) from server '%s:%d' "
1834 "while fetching \"/tor/server/%s\". I'll try again soon.",
1835 status_code, escaped(reason), conn->_base.address,
1836 conn->_base.port, conn->requested_resource);
1837 if (!which) {
1838 connection_dir_download_routerdesc_failed(conn);
1839 } else {
1840 dir_routerdesc_download_failed(which, status_code,
1841 conn->router_purpose,
1842 was_ei, descriptor_digests);
1843 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1844 smartlist_free(which);
1846 tor_free(body); tor_free(headers); tor_free(reason);
1847 return dir_okay ? 0 : -1;
1849 /* Learn the routers, assuming we requested by fingerprint or "all"
1850 * or "authority".
1852 * We use "authority" to fetch our own descriptor for
1853 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1854 * the output of "authority" requests unless we are using bridges,
1855 * since otherwise they'll be the response from reachability tests,
1856 * and we don't really want to add that to our routerlist. */
1857 if (which || (conn->requested_resource &&
1858 (!strcmpstart(conn->requested_resource, "all") ||
1859 (!strcmpstart(conn->requested_resource, "authority") &&
1860 get_options()->UseBridges)))) {
1861 /* as we learn from them, we remove them from 'which' */
1862 if (was_ei) {
1863 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1864 descriptor_digests);
1865 } else {
1866 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1867 // descriptor_digests, conn->router_purpose);
1868 if (load_downloaded_routers(body, which, descriptor_digests,
1869 conn->router_purpose,
1870 conn->_base.address))
1871 directory_info_has_arrived(now, 0);
1874 if (which) { /* mark remaining ones as failed */
1875 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1876 n_asked_for-smartlist_len(which), n_asked_for,
1877 was_ei ? "extra-info documents" : "router descriptors",
1878 conn->_base.address, (int)conn->_base.port);
1879 if (smartlist_len(which)) {
1880 dir_routerdesc_download_failed(which, status_code,
1881 conn->router_purpose,
1882 was_ei, descriptor_digests);
1884 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1885 smartlist_free(which);
1887 if (directory_conn_is_self_reachability_test(conn))
1888 router_dirport_found_reachable();
1891 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1892 switch (status_code) {
1893 case 200: {
1894 trusted_dir_server_t *ds =
1895 router_get_trusteddirserver_by_digest(conn->identity_digest);
1896 char *rejected_hdr = http_get_header(headers,
1897 "X-Descriptor-Not-New: ");
1898 int rejected = 0;
1899 if (rejected_hdr) {
1900 if (!strcmp(rejected_hdr, "Yes")) {
1901 log_info(LD_GENERAL,
1902 "Authority '%s' declined our descriptor (not new)",
1903 ds->nickname);
1904 /* XXXX use this information; be sure to upload next one
1905 * sooner. -NM */
1906 /* XXXX023 On further thought, the task above implies that we're
1907 * basing our regenerate-descriptor time on when we uploaded the
1908 * last descriptor, not on the published time of the last
1909 * descriptor. If those are different, that's a bad thing to
1910 * do. -NM */
1911 rejected = 1;
1913 tor_free(rejected_hdr);
1915 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1916 "descriptor: finished.");
1917 control_event_server_status(
1918 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1919 conn->_base.address, conn->_base.port);
1921 ds->has_accepted_serverdesc = 1;
1922 if (directories_have_accepted_server_descriptor())
1923 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1925 break;
1926 case 400:
1927 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1928 "dirserver '%s:%d'. Please correct.",
1929 escaped(reason), conn->_base.address, conn->_base.port);
1930 control_event_server_status(LOG_WARN,
1931 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1932 conn->_base.address, conn->_base.port, escaped(reason));
1933 break;
1934 default:
1935 log_warn(LD_GENERAL,
1936 "http status %d (%s) reason unexpected while uploading "
1937 "descriptor to server '%s:%d').",
1938 status_code, escaped(reason), conn->_base.address,
1939 conn->_base.port);
1940 break;
1942 /* return 0 in all cases, since we don't want to mark any
1943 * dirservers down just because they don't like us. */
1946 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
1947 switch (status_code) {
1948 case 200: {
1949 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
1950 conn->_base.address, conn->_base.port);
1952 break;
1953 case 400:
1954 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1955 "vote to dirserver '%s:%d'. Please correct.",
1956 escaped(reason), conn->_base.address, conn->_base.port);
1957 break;
1958 default:
1959 log_warn(LD_GENERAL,
1960 "http status %d (%s) reason unexpected while uploading "
1961 "vote to server '%s:%d').",
1962 status_code, escaped(reason), conn->_base.address,
1963 conn->_base.port);
1964 break;
1966 /* return 0 in all cases, since we don't want to mark any
1967 * dirservers down just because they don't like us. */
1970 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
1971 switch (status_code) {
1972 case 200: {
1973 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
1974 conn->_base.address, conn->_base.port);
1976 break;
1977 case 400:
1978 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1979 "signatures to dirserver '%s:%d'. Please correct.",
1980 escaped(reason), conn->_base.address, conn->_base.port);
1981 break;
1982 default:
1983 log_warn(LD_GENERAL,
1984 "http status %d (%s) reason unexpected while uploading "
1985 "signatures to server '%s:%d').",
1986 status_code, escaped(reason), conn->_base.address,
1987 conn->_base.port);
1988 break;
1990 /* return 0 in all cases, since we don't want to mark any
1991 * dirservers down just because they don't like us. */
1994 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1995 tor_assert(conn->rend_data);
1996 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1997 "(%s))",
1998 (int)body_len, status_code, escaped(reason));
1999 switch (status_code) {
2000 case 200:
2001 if (rend_cache_store(body, body_len, 0) < -1) {
2002 log_warn(LD_REND,"Failed to parse rendezvous descriptor.");
2003 /* Any pending rendezvous attempts will notice when
2004 * connection_about_to_close_connection()
2005 * cleans this dir conn up. */
2006 /* We could retry. But since v0 descriptors are going out of
2007 * style, it isn't worth the hassle. We'll do better in v2. */
2008 } else {
2009 /* Success, or at least there's a v2 descriptor already
2010 * present. Notify pending connections about this. */
2011 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
2012 rend_client_desc_trynow(conn->rend_data->onion_address);
2014 break;
2015 case 404:
2016 /* Not there. Pending connections will be notified when
2017 * connection_about_to_close_connection() cleans this conn up. */
2018 break;
2019 case 400:
2020 log_warn(LD_REND,
2021 "http status 400 (%s). Dirserver didn't like our "
2022 "rendezvous query?", escaped(reason));
2023 break;
2024 default:
2025 log_warn(LD_REND,"http status %d (%s) response unexpected while "
2026 "fetching hidden service descriptor (server '%s:%d').",
2027 status_code, escaped(reason), conn->_base.address,
2028 conn->_base.port);
2029 break;
2033 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
2034 tor_assert(conn->rend_data);
2035 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
2036 "(%s))",
2037 (int)body_len, status_code, escaped(reason));
2038 switch (status_code) {
2039 case 200:
2040 switch (rend_cache_store_v2_desc_as_client(body, conn->rend_data)) {
2041 case -2:
2042 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
2043 "Retrying at another directory.");
2044 /* We'll retry when connection_about_to_close_connection()
2045 * cleans this dir conn up. */
2046 break;
2047 case -1:
2048 /* We already have a v0 descriptor here. Ignoring this one
2049 * and _not_ performing another request. */
2050 log_info(LD_REND, "Successfully fetched v2 rendezvous "
2051 "descriptor, but we already have a v0 descriptor.");
2052 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
2053 break;
2054 default:
2055 /* success. notify pending connections about this. */
2056 log_info(LD_REND, "Successfully fetched v2 rendezvous "
2057 "descriptor.");
2058 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
2059 rend_client_desc_trynow(conn->rend_data->onion_address);
2060 break;
2062 break;
2063 case 404:
2064 /* Not there. We'll retry when
2065 * connection_about_to_close_connection() cleans this conn up. */
2066 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
2067 "Retrying at another directory.");
2068 break;
2069 case 400:
2070 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
2071 "http status 400 (%s). Dirserver didn't like our "
2072 "v2 rendezvous query? Retrying at another directory.",
2073 escaped(reason));
2074 break;
2075 default:
2076 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
2077 "http status %d (%s) response unexpected while "
2078 "fetching v2 hidden service descriptor (server '%s:%d'). "
2079 "Retrying at another directory.",
2080 status_code, escaped(reason), conn->_base.address,
2081 conn->_base.port);
2082 break;
2086 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
2087 conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
2088 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
2089 "(%s))",
2090 status_code, escaped(reason));
2091 switch (status_code) {
2092 case 200:
2093 log_info(LD_REND,
2094 "Uploading rendezvous descriptor: finished with status "
2095 "200 (%s)", escaped(reason));
2096 break;
2097 case 400:
2098 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
2099 "'%s:%d'. Malformed rendezvous descriptor?",
2100 escaped(reason), conn->_base.address, conn->_base.port);
2101 break;
2102 default:
2103 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
2104 "'%s:%d').",
2105 status_code, escaped(reason), conn->_base.address,
2106 conn->_base.port);
2107 break;
2110 note_client_request(conn->_base.purpose, was_compressed, orig_len);
2111 tor_free(body); tor_free(headers); tor_free(reason);
2112 return 0;
2115 /** Called when a directory connection reaches EOF. */
2117 connection_dir_reached_eof(dir_connection_t *conn)
2119 int retval;
2120 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
2121 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
2122 conn->_base.state);
2123 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
2124 connection_mark_for_close(TO_CONN(conn));
2125 return -1;
2128 retval = connection_dir_client_reached_eof(conn);
2129 if (retval == 0) /* success */
2130 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
2131 connection_mark_for_close(TO_CONN(conn));
2132 return retval;
2135 /** If any directory object is arriving, and it's over 10MB large, we're
2136 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
2137 * ask for more than 96 router descriptors at a time.)
2139 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
2141 /** Read handler for directory connections. (That's connections <em>to</em>
2142 * directory servers and connections <em>at</em> directory servers.)
2145 connection_dir_process_inbuf(dir_connection_t *conn)
2147 tor_assert(conn);
2148 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2150 /* Directory clients write, then read data until they receive EOF;
2151 * directory servers read data until they get an HTTP command, then
2152 * write their response (when it's finished flushing, they mark for
2153 * close).
2156 /* If we're on the dirserver side, look for a command. */
2157 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
2158 if (directory_handle_command(conn) < 0) {
2159 connection_mark_for_close(TO_CONN(conn));
2160 return -1;
2162 return 0;
2165 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
2166 log_warn(LD_HTTP, "Too much data received from directory connection: "
2167 "denial of service attempt, or you need to upgrade?");
2168 connection_mark_for_close(TO_CONN(conn));
2169 return -1;
2172 if (!conn->_base.inbuf_reached_eof)
2173 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
2174 return 0;
2177 /** Create an http response for the client <b>conn</b> out of
2178 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
2180 static void
2181 write_http_status_line(dir_connection_t *conn, int status,
2182 const char *reason_phrase)
2184 char buf[256];
2185 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
2186 status, reason_phrase ? reason_phrase : "OK") < 0) {
2187 log_warn(LD_BUG,"status line too long.");
2188 return;
2190 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
2193 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
2194 * with <b>type</b> as the Content-Type.
2196 * If <b>length</b> is nonnegative, it is the Content-Length.
2197 * If <b>encoding</b> is provided, it is the Content-Encoding.
2198 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
2199 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
2200 static void
2201 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
2202 const char *type, const char *encoding,
2203 const char *extra_headers,
2204 long cache_lifetime)
2206 char date[RFC1123_TIME_LEN+1];
2207 char tmp[1024];
2208 char *cp;
2209 time_t now = time(NULL);
2211 tor_assert(conn);
2213 format_rfc1123_time(date, now);
2214 cp = tmp;
2215 tor_snprintf(cp, sizeof(tmp),
2216 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
2217 date);
2218 cp += strlen(tmp);
2219 if (type) {
2220 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
2221 cp += strlen(cp);
2223 if (!is_local_addr(&conn->_base.addr)) {
2224 /* Don't report the source address for a nearby/private connection.
2225 * Otherwise we tend to mis-report in cases where incoming ports are
2226 * being forwarded to a Tor server running behind the firewall. */
2227 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2228 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
2229 cp += strlen(cp);
2231 if (encoding) {
2232 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2233 "Content-Encoding: %s\r\n", encoding);
2234 cp += strlen(cp);
2236 if (length >= 0) {
2237 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2238 "Content-Length: %ld\r\n", (long)length);
2239 cp += strlen(cp);
2241 if (cache_lifetime > 0) {
2242 char expbuf[RFC1123_TIME_LEN+1];
2243 format_rfc1123_time(expbuf, now + cache_lifetime);
2244 /* We could say 'Cache-control: max-age=%d' here if we start doing
2245 * http/1.1 */
2246 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2247 "Expires: %s\r\n", expbuf);
2248 cp += strlen(cp);
2249 } else if (cache_lifetime == 0) {
2250 /* We could say 'Cache-control: no-cache' here if we start doing
2251 * http/1.1 */
2252 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2253 cp += strlen(cp);
2255 if (extra_headers) {
2256 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2257 cp += strlen(cp);
2259 if (sizeof(tmp)-(cp-tmp) > 3)
2260 memcpy(cp, "\r\n", 3);
2261 else
2262 tor_assert(0);
2263 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2266 /** As write_http_response_header_impl, but sets encoding and content-typed
2267 * based on whether the response will be <b>compressed</b> or not. */
2268 static void
2269 write_http_response_header(dir_connection_t *conn, ssize_t length,
2270 int compressed, long cache_lifetime)
2272 write_http_response_header_impl(conn, length,
2273 compressed?"application/octet-stream":"text/plain",
2274 compressed?"deflate":"identity",
2275 NULL,
2276 cache_lifetime);
2279 #ifdef INSTRUMENT_DOWNLOADS
2280 typedef struct request_t {
2281 uint64_t bytes; /**< How many bytes have we transferred? */
2282 uint64_t count; /**< How many requests have we made? */
2283 } request_t;
2285 /** Map used to keep track of how much data we've up/downloaded in what kind
2286 * of request. Maps from request type to pointer to request_t. */
2287 static strmap_t *request_map = NULL;
2289 /** Record that a client request of <b>purpose</b> was made, and that
2290 * <b>bytes</b> bytes of possibly <b>compressed</b> data were sent/received.
2291 * Used to keep track of how much we've up/downloaded in what kind of
2292 * request. */
2293 static void
2294 note_client_request(int purpose, int compressed, size_t bytes)
2296 char *key;
2297 const char *kind = NULL;
2298 switch (purpose) {
2299 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS: kind = "dl/status"; break;
2300 case DIR_PURPOSE_FETCH_CONSENSUS: kind = "dl/consensus"; break;
2301 case DIR_PURPOSE_FETCH_CERTIFICATE: kind = "dl/cert"; break;
2302 case DIR_PURPOSE_FETCH_STATUS_VOTE: kind = "dl/vote"; break;
2303 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: kind = "dl/detached_sig";
2304 break;
2305 case DIR_PURPOSE_FETCH_SERVERDESC: kind = "dl/server"; break;
2306 case DIR_PURPOSE_FETCH_EXTRAINFO: kind = "dl/extra"; break;
2307 case DIR_PURPOSE_UPLOAD_DIR: kind = "dl/ul-dir"; break;
2308 case DIR_PURPOSE_UPLOAD_VOTE: kind = "dl/ul-vote"; break;
2309 case DIR_PURPOSE_UPLOAD_SIGNATURES: kind = "dl/ul-sig"; break;
2310 case DIR_PURPOSE_FETCH_RENDDESC: kind = "dl/rend"; break;
2311 case DIR_PURPOSE_FETCH_RENDDESC_V2: kind = "dl/rend2"; break;
2312 case DIR_PURPOSE_UPLOAD_RENDDESC: kind = "dl/ul-rend"; break;
2313 case DIR_PURPOSE_UPLOAD_RENDDESC_V2: kind = "dl/ul-rend2"; break;
2315 if (kind) {
2316 key = tor_malloc(256);
2317 tor_snprintf(key, 256, "%s%s", kind, compressed?".z":"");
2318 } else {
2319 key = tor_malloc(256);
2320 tor_snprintf(key, 256, "unknown purpose (%d)%s",
2321 purpose, compressed?".z":"");
2323 note_request(key, bytes);
2324 tor_free(key);
2327 /** Helper: initialize the request map to instrument downloads. */
2328 static void
2329 ensure_request_map_initialized(void)
2331 if (!request_map)
2332 request_map = strmap_new();
2335 /** Called when we just transmitted or received <b>bytes</b> worth of data
2336 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2337 * <b>bytes</b> to the total associated with key. */
2338 void
2339 note_request(const char *key, size_t bytes)
2341 request_t *r;
2342 ensure_request_map_initialized();
2344 r = strmap_get(request_map, key);
2345 if (!r) {
2346 r = tor_malloc_zero(sizeof(request_t));
2347 strmap_set(request_map, key, r);
2349 r->bytes += bytes;
2350 r->count++;
2353 /** Return a newly allocated string holding a summary of bytes used per
2354 * request type. */
2355 char *
2356 directory_dump_request_log(void)
2358 smartlist_t *lines;
2359 char tmp[256];
2360 char *result;
2361 strmap_iter_t *iter;
2363 ensure_request_map_initialized();
2365 lines = smartlist_create();
2367 for (iter = strmap_iter_init(request_map);
2368 !strmap_iter_done(iter);
2369 iter = strmap_iter_next(request_map, iter)) {
2370 const char *key;
2371 void *val;
2372 request_t *r;
2373 strmap_iter_get(iter, &key, &val);
2374 r = val;
2375 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT" "U64_FORMAT"\n",
2376 key, U64_PRINTF_ARG(r->bytes), U64_PRINTF_ARG(r->count));
2377 smartlist_add(lines, tor_strdup(tmp));
2379 smartlist_sort_strings(lines);
2380 result = smartlist_join_strings(lines, "", 0, NULL);
2381 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2382 smartlist_free(lines);
2383 return result;
2385 #else
2386 static void
2387 note_client_request(int purpose, int compressed, size_t bytes)
2389 (void)purpose;
2390 (void)compressed;
2391 (void)bytes;
2394 void
2395 note_request(const char *key, size_t bytes)
2397 (void)key;
2398 (void)bytes;
2401 char *
2402 directory_dump_request_log(void)
2404 return tor_strdup("Not supported.");
2406 #endif
2408 /** Decide whether a client would accept the consensus we have.
2410 * Clients can say they only want a consensus if it's signed by more
2411 * than half the authorities in a list. They pass this list in
2412 * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
2414 * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
2415 * of the full authority identity digest. (Only strings of even length,
2416 * i.e. encodings of full bytes, are handled correctly. In the case
2417 * of an odd number of hex digits the last one is silently ignored.)
2419 * Returns 1 if more than half of the requested authorities signed the
2420 * consensus, 0 otherwise.
2423 client_likes_consensus(networkstatus_t *v, const char *want_url)
2425 smartlist_t *want_authorities = smartlist_create();
2426 int need_at_least;
2427 int have = 0;
2429 dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0);
2430 need_at_least = smartlist_len(want_authorities)/2+1;
2431 SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, d) {
2432 char want_digest[DIGEST_LEN];
2433 size_t want_len = strlen(d)/2;
2434 if (want_len > DIGEST_LEN)
2435 want_len = DIGEST_LEN;
2437 if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) {
2438 log_fn(LOG_PROTOCOL_WARN, LD_DIR,
2439 "Failed to decode requested authority digest %s.", d);
2440 continue;
2443 SMARTLIST_FOREACH_BEGIN(v->voters, networkstatus_voter_info_t *, vi) {
2444 if (smartlist_len(vi->sigs) &&
2445 tor_memeq(vi->identity_digest, want_digest, want_len)) {
2446 have++;
2447 break;
2449 } SMARTLIST_FOREACH_END(vi);
2451 /* early exit, if we already have enough */
2452 if (have >= need_at_least)
2453 break;
2454 } SMARTLIST_FOREACH_END(d);
2456 SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
2457 smartlist_free(want_authorities);
2458 return (have >= need_at_least);
2461 /** Helper function: called when a dirserver gets a complete HTTP GET
2462 * request. Look for a request for a directory or for a rendezvous
2463 * service descriptor. On finding one, write a response into
2464 * conn-\>outbuf. If the request is unrecognized, send a 400.
2465 * Always return 0. */
2466 static int
2467 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2468 const char *body, size_t body_len)
2470 size_t dlen;
2471 char *url, *url_mem, *header;
2472 or_options_t *options = get_options();
2473 time_t if_modified_since = 0;
2474 int compressed;
2475 size_t url_len;
2477 /* We ignore the body of a GET request. */
2478 (void)body;
2479 (void)body_len;
2481 log_debug(LD_DIRSERV,"Received GET command.");
2483 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2485 if (parse_http_url(headers, &url) < 0) {
2486 write_http_status_line(conn, 400, "Bad request");
2487 return 0;
2489 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2490 struct tm tm;
2491 if (parse_http_time(header, &tm) == 0) {
2492 if_modified_since = tor_timegm(&tm);
2494 /* The correct behavior on a malformed If-Modified-Since header is to
2495 * act as if no If-Modified-Since header had been given. */
2496 tor_free(header);
2498 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2500 url_mem = url;
2501 url_len = strlen(url);
2502 compressed = url_len > 2 && !strcmp(url+url_len-2, ".z");
2503 if (compressed) {
2504 url[url_len-2] = '\0';
2505 url_len -= 2;
2508 if (!strcmp(url,"/tor/")) {
2509 const char *frontpage = get_dirportfrontpage();
2511 if (frontpage) {
2512 dlen = strlen(frontpage);
2513 /* Let's return a disclaimer page (users shouldn't use V1 anymore,
2514 and caches don't fetch '/', so this is safe). */
2516 /* [We don't check for write_bucket_low here, since we want to serve
2517 * this page no matter what.] */
2518 note_request(url, dlen);
2519 write_http_response_header_impl(conn, dlen, "text/html", "identity",
2520 NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
2521 connection_write_to_buf(frontpage, dlen, TO_CONN(conn));
2522 goto done;
2524 /* if no disclaimer file, fall through and continue */
2527 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* v1 dir fetch */
2528 cached_dir_t *d = dirserv_get_directory();
2530 if (!d) {
2531 log_info(LD_DIRSERV,"Client asked for the mirrored directory, but we "
2532 "don't have a good one yet. Sending 503 Dir not available.");
2533 write_http_status_line(conn, 503, "Directory unavailable");
2534 goto done;
2536 if (d->published < if_modified_since) {
2537 write_http_status_line(conn, 304, "Not modified");
2538 goto done;
2541 dlen = compressed ? d->dir_z_len : d->dir_len;
2543 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2544 log_debug(LD_DIRSERV,
2545 "Client asked for the mirrored directory, but we've been "
2546 "writing too many bytes lately. Sending 503 Dir busy.");
2547 write_http_status_line(conn, 503, "Directory busy, try again later");
2548 goto done;
2551 note_request(url, dlen);
2553 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
2554 compressed?"compressed ":"");
2555 write_http_response_header(conn, dlen, compressed,
2556 FULL_DIR_CACHE_LIFETIME);
2557 conn->cached_dir = d;
2558 conn->cached_dir_offset = 0;
2559 if (!compressed)
2560 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2561 ++d->refcnt;
2563 /* Prime the connection with some data. */
2564 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
2565 connection_dirserv_flushed_some(conn);
2566 goto done;
2569 if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
2570 cached_dir_t *d = dirserv_get_runningrouters();
2571 if (!d) {
2572 write_http_status_line(conn, 503, "Directory unavailable");
2573 goto done;
2575 if (d->published < if_modified_since) {
2576 write_http_status_line(conn, 304, "Not modified");
2577 goto done;
2579 dlen = compressed ? d->dir_z_len : d->dir_len;
2581 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2582 log_info(LD_DIRSERV,
2583 "Client asked for running-routers, but we've been "
2584 "writing too many bytes lately. Sending 503 Dir busy.");
2585 write_http_status_line(conn, 503, "Directory busy, try again later");
2586 goto done;
2588 note_request(url, dlen);
2589 write_http_response_header(conn, dlen, compressed,
2590 RUNNINGROUTERS_CACHE_LIFETIME);
2591 connection_write_to_buf(compressed ? d->dir_z : d->dir, dlen,
2592 TO_CONN(conn));
2593 goto done;
2596 if (!strcmpstart(url,"/tor/status/")
2597 || !strcmpstart(url, "/tor/status-vote/current/consensus")) {
2598 /* v2 or v3 network status fetch. */
2599 smartlist_t *dir_fps = smartlist_create();
2600 int is_v3 = !strcmpstart(url, "/tor/status-vote");
2601 geoip_client_action_t act =
2602 is_v3 ? GEOIP_CLIENT_NETWORKSTATUS : GEOIP_CLIENT_NETWORKSTATUS_V2;
2603 const char *request_type = NULL;
2604 const char *key = url + strlen("/tor/status/");
2605 long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2607 if (!is_v3) {
2608 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
2609 if (!strcmpstart(key, "fp/"))
2610 request_type = compressed?"/tor/status/fp.z":"/tor/status/fp";
2611 else if (!strcmpstart(key, "authority"))
2612 request_type = compressed?"/tor/status/authority.z":
2613 "/tor/status/authority";
2614 else if (!strcmpstart(key, "all"))
2615 request_type = compressed?"/tor/status/all.z":"/tor/status/all";
2616 else
2617 request_type = "/tor/status/?";
2618 } else {
2619 networkstatus_t *v = networkstatus_get_latest_consensus();
2620 time_t now = time(NULL);
2621 const char *want_fps = NULL;
2622 char *flavor = NULL;
2623 #define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/"
2624 #define CONSENSUS_FLAVORED_PREFIX "/tor/status-vote/current/consensus-"
2625 /* figure out the flavor if any, and who we wanted to sign the thing */
2626 if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) {
2627 const char *f, *cp;
2628 f = url + strlen(CONSENSUS_FLAVORED_PREFIX);
2629 cp = strchr(f, '/');
2630 if (cp) {
2631 want_fps = cp+1;
2632 flavor = tor_strndup(f, cp-f);
2633 } else {
2634 flavor = tor_strdup(f);
2636 } else {
2637 if (!strcmpstart(url, CONSENSUS_URL_PREFIX))
2638 want_fps = url+strlen(CONSENSUS_URL_PREFIX);
2641 /* XXXX MICRODESC NM NM should check document of correct flavor */
2642 if (v && want_fps &&
2643 !client_likes_consensus(v, want_fps)) {
2644 write_http_status_line(conn, 404, "Consensus not signed by sufficient "
2645 "number of requested authorities");
2646 smartlist_free(dir_fps);
2647 geoip_note_ns_response(act, GEOIP_REJECT_NOT_ENOUGH_SIGS);
2648 tor_free(flavor);
2649 goto done;
2653 char *fp = tor_malloc_zero(DIGEST_LEN);
2654 if (flavor)
2655 strlcpy(fp, flavor, DIGEST_LEN);
2656 tor_free(flavor);
2657 smartlist_add(dir_fps, fp);
2659 request_type = compressed?"v3.z":"v3";
2660 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2663 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2664 write_http_status_line(conn, 503, "Network status object unavailable");
2665 smartlist_free(dir_fps);
2666 geoip_note_ns_response(act, GEOIP_REJECT_UNAVAILABLE);
2667 goto done;
2670 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2671 write_http_status_line(conn, 404, "Not found");
2672 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2673 smartlist_free(dir_fps);
2674 geoip_note_ns_response(act, GEOIP_REJECT_NOT_FOUND);
2675 goto done;
2676 } else if (!smartlist_len(dir_fps)) {
2677 write_http_status_line(conn, 304, "Not modified");
2678 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2679 smartlist_free(dir_fps);
2680 geoip_note_ns_response(act, GEOIP_REJECT_NOT_MODIFIED);
2681 goto done;
2684 dlen = dirserv_estimate_data_size(dir_fps, 0, compressed);
2685 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2686 log_debug(LD_DIRSERV,
2687 "Client asked for network status lists, but we've been "
2688 "writing too many bytes lately. Sending 503 Dir busy.");
2689 write_http_status_line(conn, 503, "Directory busy, try again later");
2690 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2691 smartlist_free(dir_fps);
2692 geoip_note_ns_response(act, GEOIP_REJECT_BUSY);
2693 goto done;
2697 struct in_addr in;
2698 if (tor_inet_aton((TO_CONN(conn))->address, &in)) {
2699 geoip_note_client_seen(act, ntohl(in.s_addr), time(NULL));
2700 geoip_note_ns_response(act, GEOIP_SUCCESS);
2701 /* Note that a request for a network status has started, so that we
2702 * can measure the download time later on. */
2703 if (TO_CONN(conn)->dirreq_id)
2704 geoip_start_dirreq(TO_CONN(conn)->dirreq_id, dlen, act,
2705 DIRREQ_TUNNELED);
2706 else
2707 geoip_start_dirreq(TO_CONN(conn)->global_identifier, dlen, act,
2708 DIRREQ_DIRECT);
2712 // note_request(request_type,dlen);
2713 (void) request_type;
2714 write_http_response_header(conn, -1, compressed,
2715 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2716 conn->fingerprint_stack = dir_fps;
2717 if (! compressed)
2718 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2720 /* Prime the connection with some data. */
2721 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2722 connection_dirserv_flushed_some(conn);
2723 goto done;
2726 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2727 !strcmpstart(url,"/tor/status-vote/next/")) {
2728 /* XXXX If-modified-since is only implemented for the current
2729 * consensus: that's probably fine, since it's the only vote document
2730 * people fetch much. */
2731 int current;
2732 ssize_t body_len = 0;
2733 ssize_t estimated_len = 0;
2734 smartlist_t *items = smartlist_create();
2735 smartlist_t *dir_items = smartlist_create();
2736 int lifetime = 60; /* XXXX023 should actually use vote intervals. */
2737 url += strlen("/tor/status-vote/");
2738 current = !strcmpstart(url, "current/");
2739 url = strchr(url, '/');
2740 tor_assert(url);
2741 ++url;
2742 if (!strcmp(url, "consensus")) {
2743 const char *item;
2744 tor_assert(!current); /* we handle current consensus specially above,
2745 * since it wants to be spooled. */
2746 if ((item = dirvote_get_pending_consensus(FLAV_NS)))
2747 smartlist_add(items, (char*)item);
2748 } else if (!current && !strcmp(url, "consensus-signatures")) {
2749 /* XXXX the spec says that we should implement
2750 * current/consensus-signatures too. It doesn't seem to be needed,
2751 * though. */
2752 const char *item;
2753 if ((item=dirvote_get_pending_detached_signatures()))
2754 smartlist_add(items, (char*)item);
2755 } else if (!strcmp(url, "authority")) {
2756 const cached_dir_t *d;
2757 int flags = DGV_BY_ID |
2758 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2759 if ((d=dirvote_get_vote(NULL, flags)))
2760 smartlist_add(dir_items, (cached_dir_t*)d);
2761 } else {
2762 const cached_dir_t *d;
2763 smartlist_t *fps = smartlist_create();
2764 int flags;
2765 if (!strcmpstart(url, "d/")) {
2766 url += 2;
2767 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2768 } else {
2769 flags = DGV_BY_ID |
2770 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2772 dir_split_resource_into_fingerprints(url, fps, NULL,
2773 DSR_HEX|DSR_SORT_UNIQ);
2774 SMARTLIST_FOREACH(fps, char *, fp, {
2775 if ((d = dirvote_get_vote(fp, flags)))
2776 smartlist_add(dir_items, (cached_dir_t*)d);
2777 tor_free(fp);
2779 smartlist_free(fps);
2781 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2782 write_http_status_line(conn, 404, "Not found");
2783 goto vote_done;
2785 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2786 body_len += compressed ? d->dir_z_len : d->dir_len);
2787 estimated_len += body_len;
2788 SMARTLIST_FOREACH(items, const char *, item, {
2789 size_t ln = strlen(item);
2790 if (compressed) {
2791 estimated_len += ln/2;
2792 } else {
2793 body_len += ln; estimated_len += ln;
2797 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
2798 write_http_status_line(conn, 503, "Directory busy, try again later.");
2799 goto vote_done;
2801 write_http_response_header(conn, body_len ? body_len : -1, compressed,
2802 lifetime);
2804 if (smartlist_len(items)) {
2805 if (compressed) {
2806 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2807 SMARTLIST_FOREACH(items, const char *, c,
2808 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2809 connection_write_to_buf_zlib("", 0, conn, 1);
2810 } else {
2811 SMARTLIST_FOREACH(items, const char *, c,
2812 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2814 } else {
2815 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2816 connection_write_to_buf(compressed ? d->dir_z : d->dir,
2817 compressed ? d->dir_z_len : d->dir_len,
2818 TO_CONN(conn)));
2820 vote_done:
2821 smartlist_free(items);
2822 smartlist_free(dir_items);
2823 goto done;
2826 if (!strcmpstart(url, "/tor/micro/d/")) {
2827 smartlist_t *fps = smartlist_create();
2829 dir_split_resource_into_fingerprints(url+strlen("/tor/micro/d/"),
2830 fps, NULL,
2831 DSR_DIGEST256|DSR_BASE64|DSR_SORT_UNIQ);
2833 if (!dirserv_have_any_microdesc(fps)) {
2834 write_http_status_line(conn, 404, "Not found");
2835 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
2836 smartlist_free(fps);
2837 goto done;
2839 dlen = dirserv_estimate_microdesc_size(fps, compressed);
2840 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2841 log_info(LD_DIRSERV,
2842 "Client asked for server descriptors, but we've been "
2843 "writing too many bytes lately. Sending 503 Dir busy.");
2844 write_http_status_line(conn, 503, "Directory busy, try again later");
2845 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
2846 smartlist_free(fps);
2847 goto done;
2850 write_http_response_header(conn, -1, compressed, MICRODESC_CACHE_LIFETIME);
2851 conn->dir_spool_src = DIR_SPOOL_MICRODESC;
2852 conn->fingerprint_stack = fps;
2854 if (compressed)
2855 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2857 connection_dirserv_flushed_some(conn);
2858 goto done;
2861 if (!strcmpstart(url,"/tor/server/") ||
2862 (!options->BridgeAuthoritativeDir &&
2863 !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
2864 int res;
2865 const char *msg;
2866 const char *request_type = NULL;
2867 int cache_lifetime = 0;
2868 int is_extra = !strcmpstart(url,"/tor/extra/");
2869 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2870 conn->fingerprint_stack = smartlist_create();
2871 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2872 &msg,
2873 !connection_dir_is_encrypted(conn),
2874 is_extra);
2876 if (!strcmpstart(url, "fp/")) {
2877 request_type = compressed?"/tor/server/fp.z":"/tor/server/fp";
2878 if (smartlist_len(conn->fingerprint_stack) == 1)
2879 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2880 } else if (!strcmpstart(url, "authority")) {
2881 request_type = compressed?"/tor/server/authority.z":
2882 "/tor/server/authority";
2883 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2884 } else if (!strcmpstart(url, "all")) {
2885 request_type = compressed?"/tor/server/all.z":"/tor/server/all";
2886 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2887 } else if (!strcmpstart(url, "d/")) {
2888 request_type = compressed?"/tor/server/d.z":"/tor/server/d";
2889 if (smartlist_len(conn->fingerprint_stack) == 1)
2890 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2891 } else {
2892 request_type = "/tor/server/?";
2894 (void) request_type; /* usable for note_request. */
2895 if (!strcmpstart(url, "d/"))
2896 conn->dir_spool_src =
2897 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2898 else
2899 conn->dir_spool_src =
2900 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2902 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2903 conn->dir_spool_src)) {
2904 res = -1;
2905 msg = "Not found";
2908 if (res < 0)
2909 write_http_status_line(conn, 404, msg);
2910 else {
2911 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2912 1, compressed);
2913 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2914 log_info(LD_DIRSERV,
2915 "Client asked for server descriptors, but we've been "
2916 "writing too many bytes lately. Sending 503 Dir busy.");
2917 write_http_status_line(conn, 503, "Directory busy, try again later");
2918 conn->dir_spool_src = DIR_SPOOL_NONE;
2919 goto done;
2921 write_http_response_header(conn, -1, compressed, cache_lifetime);
2922 if (compressed)
2923 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2924 /* Prime the connection with some data. */
2925 connection_dirserv_flushed_some(conn);
2927 goto done;
2930 if (!strcmpstart(url,"/tor/keys/")) {
2931 smartlist_t *certs = smartlist_create();
2932 ssize_t len = -1;
2933 if (!strcmp(url, "/tor/keys/all")) {
2934 authority_cert_get_all(certs);
2935 } else if (!strcmp(url, "/tor/keys/authority")) {
2936 authority_cert_t *cert = get_my_v3_authority_cert();
2937 if (cert)
2938 smartlist_add(certs, cert);
2939 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
2940 smartlist_t *fps = smartlist_create();
2941 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
2942 fps, NULL,
2943 DSR_HEX|DSR_SORT_UNIQ);
2944 SMARTLIST_FOREACH(fps, char *, d, {
2945 authority_cert_t *c = authority_cert_get_newest_by_id(d);
2946 if (c) smartlist_add(certs, c);
2947 tor_free(d);
2949 smartlist_free(fps);
2950 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
2951 smartlist_t *fps = smartlist_create();
2952 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
2953 fps, NULL,
2954 DSR_HEX|DSR_SORT_UNIQ);
2955 SMARTLIST_FOREACH(fps, char *, d, {
2956 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
2957 if (c) smartlist_add(certs, c);
2958 tor_free(d);
2960 smartlist_free(fps);
2961 } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
2962 smartlist_t *fp_sks = smartlist_create();
2963 dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
2964 fp_sks);
2965 SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
2966 authority_cert_t *c = authority_cert_get_by_digests(pair->first,
2967 pair->second);
2968 if (c) smartlist_add(certs, c);
2969 tor_free(pair);
2971 smartlist_free(fp_sks);
2972 } else {
2973 write_http_status_line(conn, 400, "Bad request");
2974 goto keys_done;
2976 if (!smartlist_len(certs)) {
2977 write_http_status_line(conn, 404, "Not found");
2978 goto keys_done;
2980 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2981 if (c->cache_info.published_on < if_modified_since)
2982 SMARTLIST_DEL_CURRENT(certs, c));
2983 if (!smartlist_len(certs)) {
2984 write_http_status_line(conn, 304, "Not modified");
2985 goto keys_done;
2987 len = 0;
2988 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2989 len += c->cache_info.signed_descriptor_len);
2991 if (global_write_bucket_low(TO_CONN(conn), compressed?len/2:len, 2)) {
2992 write_http_status_line(conn, 503, "Directory busy, try again later.");
2993 goto keys_done;
2996 write_http_response_header(conn, compressed?-1:len, compressed, 60*60);
2997 if (compressed) {
2998 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2999 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3000 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
3001 c->cache_info.signed_descriptor_len,
3002 conn, 0));
3003 connection_write_to_buf_zlib("", 0, conn, 1);
3004 } else {
3005 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
3006 connection_write_to_buf(c->cache_info.signed_descriptor_body,
3007 c->cache_info.signed_descriptor_len,
3008 TO_CONN(conn)));
3010 keys_done:
3011 smartlist_free(certs);
3012 goto done;
3015 if (options->HidServDirectoryV2 &&
3016 !strcmpstart(url,"/tor/rendezvous2/")) {
3017 /* Handle v2 rendezvous descriptor fetch request. */
3018 const char *descp;
3019 const char *query = url + strlen("/tor/rendezvous2/");
3020 if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) {
3021 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
3022 safe_str(query));
3023 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
3024 case 1: /* valid */
3025 write_http_response_header(conn, strlen(descp), 0, 0);
3026 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
3027 break;
3028 case 0: /* well-formed but not present */
3029 write_http_status_line(conn, 404, "Not found");
3030 break;
3031 case -1: /* not well-formed */
3032 write_http_status_line(conn, 400, "Bad request");
3033 break;
3035 } else { /* not well-formed */
3036 write_http_status_line(conn, 400, "Bad request");
3038 goto done;
3041 if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) {
3042 /* rendezvous descriptor fetch */
3043 const char *descp;
3044 size_t desc_len;
3045 const char *query = url+strlen("/tor/rendezvous/");
3047 log_info(LD_REND, "Handling rendezvous descriptor get");
3048 switch (rend_cache_lookup_desc(query, 0, &descp, &desc_len)) {
3049 case 1: /* valid */
3050 write_http_response_header_impl(conn, desc_len,
3051 "application/octet-stream",
3052 NULL, NULL, 0);
3053 note_request("/tor/rendezvous?/", desc_len);
3054 /* need to send descp separately, because it may include NULs */
3055 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
3056 break;
3057 case 0: /* well-formed but not present */
3058 write_http_status_line(conn, 404, "Not found");
3059 break;
3060 case -1: /* not well-formed */
3061 write_http_status_line(conn, 400, "Bad request");
3062 break;
3064 goto done;
3067 if (options->BridgeAuthoritativeDir &&
3068 options->BridgePassword &&
3069 connection_dir_is_encrypted(conn) &&
3070 !strcmp(url,"/tor/networkstatus-bridges")) {
3071 char *status;
3072 char *secret = alloc_http_authenticator(options->BridgePassword);
3074 header = http_get_header(headers, "Authorization: Basic ");
3076 /* now make sure the password is there and right */
3077 if (!header || strcmp(header, secret)) {
3078 write_http_status_line(conn, 404, "Not found");
3079 tor_free(secret);
3080 tor_free(header);
3081 goto done;
3083 tor_free(secret);
3084 tor_free(header);
3086 /* all happy now. send an answer. */
3087 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
3088 dlen = strlen(status);
3089 write_http_response_header(conn, dlen, 0, 0);
3090 connection_write_to_buf(status, dlen, TO_CONN(conn));
3091 tor_free(status);
3092 goto done;
3095 if (!strcmpstart(url,"/tor/bytes.txt")) {
3096 char *bytes = directory_dump_request_log();
3097 size_t len = strlen(bytes);
3098 write_http_response_header(conn, len, 0, 0);
3099 connection_write_to_buf(bytes, len, TO_CONN(conn));
3100 tor_free(bytes);
3101 goto done;
3104 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
3105 rewritten to /tor/robots.txt */
3106 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
3107 size_t len = strlen(robots);
3108 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
3109 connection_write_to_buf(robots, len, TO_CONN(conn));
3110 goto done;
3113 if (!strcmp(url,"/tor/dbg-stability.txt")) {
3114 const char *stability;
3115 size_t len;
3116 if (options->BridgeAuthoritativeDir ||
3117 ! authdir_mode_tests_reachability(options) ||
3118 ! (stability = rep_hist_get_router_stability_doc(time(NULL)))) {
3119 write_http_status_line(conn, 404, "Not found.");
3120 goto done;
3123 len = strlen(stability);
3124 write_http_response_header(conn, len, 0, 0);
3125 connection_write_to_buf(stability, len, TO_CONN(conn));
3126 goto done;
3129 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
3130 #define ADD_MALLINFO_LINE(x) do { \
3131 tor_snprintf(tmp, sizeof(tmp), "%s %d\n", #x, mi.x); \
3132 smartlist_add(lines, tor_strdup(tmp)); \
3133 }while(0);
3135 if (!strcmp(url,"/tor/mallinfo.txt") &&
3136 (tor_addr_eq_ipv4h(&conn->_base.addr, 0x7f000001ul))) {
3137 char *result;
3138 size_t len;
3139 struct mallinfo mi;
3140 smartlist_t *lines;
3141 char tmp[256];
3143 memset(&mi, 0, sizeof(mi));
3144 mi = mallinfo();
3145 lines = smartlist_create();
3147 ADD_MALLINFO_LINE(arena)
3148 ADD_MALLINFO_LINE(ordblks)
3149 ADD_MALLINFO_LINE(smblks)
3150 ADD_MALLINFO_LINE(hblks)
3151 ADD_MALLINFO_LINE(hblkhd)
3152 ADD_MALLINFO_LINE(usmblks)
3153 ADD_MALLINFO_LINE(fsmblks)
3154 ADD_MALLINFO_LINE(uordblks)
3155 ADD_MALLINFO_LINE(fordblks)
3156 ADD_MALLINFO_LINE(keepcost)
3158 result = smartlist_join_strings(lines, "", 0, NULL);
3159 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
3160 smartlist_free(lines);
3162 len = strlen(result);
3163 write_http_response_header(conn, len, 0, 0);
3164 connection_write_to_buf(result, len, TO_CONN(conn));
3165 tor_free(result);
3166 goto done;
3168 #endif
3170 /* we didn't recognize the url */
3171 write_http_status_line(conn, 404, "Not found");
3173 done:
3174 tor_free(url_mem);
3175 return 0;
3178 /** Helper function: called when a dirserver gets a complete HTTP POST
3179 * request. Look for an uploaded server descriptor or rendezvous
3180 * service descriptor. On finding one, process it and write a
3181 * response into conn-\>outbuf. If the request is unrecognized, send a
3182 * 400. Always return 0. */
3183 static int
3184 directory_handle_command_post(dir_connection_t *conn, const char *headers,
3185 const char *body, size_t body_len)
3187 char *url = NULL;
3188 or_options_t *options = get_options();
3190 log_debug(LD_DIRSERV,"Received POST command.");
3192 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
3194 if (parse_http_url(headers, &url) < 0) {
3195 write_http_status_line(conn, 400, "Bad request");
3196 return 0;
3198 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
3200 /* Handle v2 rendezvous service publish request. */
3201 if (options->HidServDirectoryV2 &&
3202 !strcmpstart(url,"/tor/rendezvous2/publish")) {
3203 switch (rend_cache_store_v2_desc_as_dir(body)) {
3204 case -2:
3205 log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
3206 "since we're not currently a hidden service directory.",
3207 (int)body_len, conn->_base.address);
3208 write_http_status_line(conn, 503, "Currently not acting as v2 "
3209 "hidden service directory");
3210 break;
3211 case -1:
3212 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
3213 (int)body_len, conn->_base.address);
3214 write_http_status_line(conn, 400,
3215 "Invalid v2 service descriptor rejected");
3216 break;
3217 default:
3218 write_http_status_line(conn, 200, "Service descriptor (v2) stored");
3219 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
3221 goto done;
3224 if (!authdir_mode(options)) {
3225 /* we just provide cached directories; we don't want to
3226 * receive anything. */
3227 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
3228 "accept posted server descriptors");
3229 goto done;
3232 if (authdir_mode_handles_descs(options, -1) &&
3233 !strcmp(url,"/tor/")) { /* server descriptor post */
3234 const char *msg = "[None]";
3235 uint8_t purpose = authdir_mode_bridge(options) ?
3236 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
3237 was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
3238 conn->_base.address, &msg);
3239 tor_assert(msg);
3240 if (WRA_WAS_ADDED(r))
3241 dirserv_get_directory(); /* rebuild and write to disk */
3243 if (r == ROUTER_ADDED_NOTIFY_GENERATOR) {
3244 /* Accepted with a message. */
3245 log_info(LD_DIRSERV,
3246 "Problematic router descriptor or extra-info from %s "
3247 "(\"%s\").",
3248 conn->_base.address, msg);
3249 write_http_status_line(conn, 400, msg);
3250 } else if (r == ROUTER_ADDED_SUCCESSFULLY) {
3251 write_http_status_line(conn, 200, msg);
3252 } else if (WRA_WAS_OUTDATED(r)) {
3253 write_http_response_header_impl(conn, -1, NULL, NULL,
3254 "X-Descriptor-Not-New: Yes\r\n", -1);
3255 } else {
3256 log_info(LD_DIRSERV,
3257 "Rejected router descriptor or extra-info from %s "
3258 "(\"%s\").",
3259 conn->_base.address, msg);
3260 write_http_status_line(conn, 400, msg);
3262 goto done;
3265 if (options->HSAuthoritativeDir &&
3266 !strcmpstart(url,"/tor/rendezvous/publish")) {
3267 /* rendezvous descriptor post */
3268 log_info(LD_REND, "Handling rendezvous descriptor post.");
3269 if (rend_cache_store(body, body_len, 1) < 0) {
3270 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
3271 "Rejected rend descriptor (length %d) from %s.",
3272 (int)body_len, conn->_base.address);
3273 write_http_status_line(conn, 400,
3274 "Invalid v0 service descriptor rejected");
3275 } else {
3276 write_http_status_line(conn, 200, "Service descriptor (v0) stored");
3278 goto done;
3281 if (authdir_mode_v3(options) &&
3282 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
3283 const char *msg = "OK";
3284 int status;
3285 if (dirvote_add_vote(body, &msg, &status)) {
3286 write_http_status_line(conn, status, "Vote stored");
3287 } else {
3288 tor_assert(msg);
3289 log_warn(LD_DIRSERV, "Rejected vote from %s (\"%s\").",
3290 conn->_base.address, msg);
3291 write_http_status_line(conn, status, msg);
3293 goto done;
3296 if (authdir_mode_v3(options) &&
3297 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
3298 const char *msg = NULL;
3299 if (dirvote_add_signatures(body, conn->_base.address, &msg)>=0) {
3300 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
3301 } else {
3302 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
3303 conn->_base.address, msg?msg:"???");
3304 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
3306 goto done;
3309 /* we didn't recognize the url */
3310 write_http_status_line(conn, 404, "Not found");
3312 done:
3313 tor_free(url);
3314 return 0;
3317 /** Called when a dirserver receives data on a directory connection;
3318 * looks for an HTTP request. If the request is complete, remove it
3319 * from the inbuf, try to process it; otherwise, leave it on the
3320 * buffer. Return a 0 on success, or -1 on error.
3322 static int
3323 directory_handle_command(dir_connection_t *conn)
3325 char *headers=NULL, *body=NULL;
3326 size_t body_len=0;
3327 int r;
3329 tor_assert(conn);
3330 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3332 switch (fetch_from_buf_http(conn->_base.inbuf,
3333 &headers, MAX_HEADERS_SIZE,
3334 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
3335 case -1: /* overflow */
3336 log_warn(LD_DIRSERV,
3337 "Request too large from address '%s' to DirPort. Closing.",
3338 safe_str(conn->_base.address));
3339 return -1;
3340 case 0:
3341 log_debug(LD_DIRSERV,"command not all here yet.");
3342 return 0;
3343 /* case 1, fall through */
3346 http_set_address_origin(headers, TO_CONN(conn));
3347 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
3349 if (!strncasecmp(headers,"GET",3))
3350 r = directory_handle_command_get(conn, headers, body, body_len);
3351 else if (!strncasecmp(headers,"POST",4))
3352 r = directory_handle_command_post(conn, headers, body, body_len);
3353 else {
3354 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
3355 "Got headers %s with unknown command. Closing.",
3356 escaped(headers));
3357 r = -1;
3360 tor_free(headers); tor_free(body);
3361 return r;
3364 /** Write handler for directory connections; called when all data has
3365 * been flushed. Close the connection or wait for a response as
3366 * appropriate.
3369 connection_dir_finished_flushing(dir_connection_t *conn)
3371 tor_assert(conn);
3372 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3374 /* Note that we have finished writing the directory response. For direct
3375 * connections this means we're done, for tunneled connections its only
3376 * an intermediate step. */
3377 if (TO_CONN(conn)->dirreq_id)
3378 geoip_change_dirreq_state(TO_CONN(conn)->dirreq_id, DIRREQ_TUNNELED,
3379 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3380 else
3381 geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
3382 DIRREQ_DIRECT,
3383 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3384 switch (conn->_base.state) {
3385 case DIR_CONN_STATE_CLIENT_SENDING:
3386 log_debug(LD_DIR,"client finished sending command.");
3387 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
3388 connection_stop_writing(TO_CONN(conn));
3389 return 0;
3390 case DIR_CONN_STATE_SERVER_WRITING:
3391 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
3392 connection_mark_for_close(TO_CONN(conn));
3393 return 0;
3394 default:
3395 log_warn(LD_BUG,"called in unexpected state %d.",
3396 conn->_base.state);
3397 tor_fragile_assert();
3398 return -1;
3400 return 0;
3403 /** Connected handler for directory connections: begin sending data to the
3404 * server */
3406 connection_dir_finished_connecting(dir_connection_t *conn)
3408 tor_assert(conn);
3409 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3410 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
3412 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
3413 conn->_base.address,conn->_base.port);
3415 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
3416 return 0;
3419 /** Called when one or more networkstatus fetches have failed (with uppercase
3420 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
3421 * failed once, unless they failed with status code 503. */
3422 static void
3423 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
3425 if (status_code == 503)
3426 return;
3427 SMARTLIST_FOREACH(failed, const char *, fp,
3429 char digest[DIGEST_LEN];
3430 trusted_dir_server_t *dir;
3431 if (base16_decode(digest, DIGEST_LEN, fp, strlen(fp))<0) {
3432 log_warn(LD_BUG, "Called with bad fingerprint in list: %s",
3433 escaped(fp));
3434 continue;
3436 dir = router_get_trusteddirserver_by_digest(digest);
3438 if (dir)
3439 download_status_failed(&dir->v2_ns_dl_status, status_code);
3443 /** Schedule for when servers should download things in general. */
3444 static const int server_dl_schedule[] = {
3445 0, 0, 0, 60, 60, 60*2, 60*5, 60*15, INT_MAX
3447 /** Schedule for when clients should download things in general. */
3448 static const int client_dl_schedule[] = {
3449 0, 0, 60, 60*5, 60*10, INT_MAX
3451 /** Schedule for when servers should download consensuses. */
3452 static const int server_consensus_dl_schedule[] = {
3453 0, 0, 60, 60*5, 60*10, 60*30, 60*30, 60*30, 60*30, 60*30, 60*60, 60*60*2
3455 /** Schedule for when clients should download consensuses. */
3456 static const int client_consensus_dl_schedule[] = {
3457 0, 0, 60, 60*5, 60*10, 60*30, 60*60, 60*60, 60*60, 60*60*3, 60*60*6, 60*60*12
3459 /** Schedule for when clients should download bridge descriptors. */
3460 static const int bridge_dl_schedule[] = {
3461 60*60, 15*60, 15*60, 60*60
3464 /** Decide which download schedule we want to use, and then return a
3465 * pointer to it along with a pointer to its length. Helper function for
3466 * download_status_increment_failure() and download_status_reset(). */
3467 static void
3468 find_dl_schedule_and_len(download_status_t *dls, int server,
3469 const int **schedule, size_t *schedule_len)
3471 switch (dls->schedule) {
3472 case DL_SCHED_GENERIC:
3473 if (server) {
3474 *schedule = server_dl_schedule;
3475 *schedule_len = sizeof(server_dl_schedule)/sizeof(int);
3476 } else {
3477 *schedule = client_dl_schedule;
3478 *schedule_len = sizeof(client_dl_schedule)/sizeof(int);
3480 break;
3481 case DL_SCHED_CONSENSUS:
3482 if (server) {
3483 *schedule = server_consensus_dl_schedule;
3484 *schedule_len = sizeof(server_consensus_dl_schedule)/sizeof(int);
3485 } else {
3486 *schedule = client_consensus_dl_schedule;
3487 *schedule_len = sizeof(client_consensus_dl_schedule)/sizeof(int);
3489 break;
3490 case DL_SCHED_BRIDGE:
3491 *schedule = bridge_dl_schedule;
3492 *schedule_len = sizeof(bridge_dl_schedule)/sizeof(int);
3493 break;
3494 default:
3495 tor_assert(0);
3499 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
3500 * <b>status_code</b>. Increment the failure count (if the code indicates a
3501 * real failure) and set <b>dls</b>-\>next_attempt_at to an appropriate time
3502 * in the future. */
3503 time_t
3504 download_status_increment_failure(download_status_t *dls, int status_code,
3505 const char *item, int server, time_t now)
3507 const int *schedule;
3508 size_t schedule_len;
3509 int increment;
3510 tor_assert(dls);
3511 if (status_code != 503 || server) {
3512 if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1)
3513 ++dls->n_download_failures;
3516 find_dl_schedule_and_len(dls, server, &schedule, &schedule_len);
3518 if (dls->n_download_failures < schedule_len)
3519 increment = schedule[dls->n_download_failures];
3520 else if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
3521 increment = INT_MAX;
3522 else
3523 increment = schedule[schedule_len-1];
3525 if (increment < INT_MAX)
3526 dls->next_attempt_at = now+increment;
3527 else
3528 dls->next_attempt_at = TIME_MAX;
3530 if (item) {
3531 if (increment == 0)
3532 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
3533 item, (int)dls->n_download_failures);
3534 else if (dls->next_attempt_at < TIME_MAX)
3535 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
3536 item, (int)dls->n_download_failures,
3537 (int)(dls->next_attempt_at-now));
3538 else
3539 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
3540 item, (int)dls->n_download_failures);
3542 return dls->next_attempt_at;
3545 /** Reset <b>dls</b> so that it will be considered downloadable
3546 * immediately, and/or to show that we don't need it anymore.
3548 * (We find the zeroth element of the download schedule, and set
3549 * next_attempt_at to be the appropriate offset from 'now'. In most
3550 * cases this means setting it to 'now', so the item will be immediately
3551 * downloadable; in the case of bridge descriptors, the zeroth element
3552 * is an hour from now.) */
3553 void
3554 download_status_reset(download_status_t *dls)
3556 const int *schedule;
3557 size_t schedule_len;
3559 find_dl_schedule_and_len(dls, get_options()->DirPort,
3560 &schedule, &schedule_len);
3562 dls->n_download_failures = 0;
3563 dls->next_attempt_at = time(NULL) + schedule[0];
3566 /** Return the number of failures on <b>dls</b> since the last success (if
3567 * any). */
3569 download_status_get_n_failures(const download_status_t *dls)
3571 return dls->n_download_failures;
3574 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
3575 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
3576 * either as descriptor digests or as identity digests based on
3577 * <b>was_descriptor_digests</b>).
3579 static void
3580 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
3581 int router_purpose,
3582 int was_extrainfo, int was_descriptor_digests)
3584 char digest[DIGEST_LEN];
3585 time_t now = time(NULL);
3586 int server = directory_fetches_from_authorities(get_options());
3587 if (!was_descriptor_digests) {
3588 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
3589 tor_assert(!was_extrainfo);
3590 connection_dir_retry_bridges(failed);
3592 return; /* FFFF should implement for other-than-router-purpose someday */
3594 SMARTLIST_FOREACH(failed, const char *, cp,
3596 download_status_t *dls = NULL;
3597 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) {
3598 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
3599 continue;
3601 if (was_extrainfo) {
3602 signed_descriptor_t *sd =
3603 router_get_by_extrainfo_digest(digest);
3604 if (sd)
3605 dls = &sd->ei_dl_status;
3606 } else {
3607 dls = router_get_dl_status_by_descriptor_digest(digest);
3609 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
3610 continue;
3611 download_status_increment_failure(dls, status_code, cp, server, now);
3614 /* No need to relaunch descriptor downloads here: we already do it
3615 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3618 /** Helper. Compare two fp_pair_t objects, and return negative, 0, or
3619 * positive as appropriate. */
3620 static int
3621 _compare_pairs(const void **a, const void **b)
3623 const fp_pair_t *fp1 = *a, *fp2 = *b;
3624 int r;
3625 if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
3626 return r;
3627 else
3628 return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
3631 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
3632 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
3633 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
3634 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
3636 dir_split_resource_into_fingerprint_pairs(const char *res,
3637 smartlist_t *pairs_out)
3639 smartlist_t *pairs_tmp = smartlist_create();
3640 smartlist_t *pairs_result = smartlist_create();
3642 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
3643 if (smartlist_len(pairs_tmp)) {
3644 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
3645 size_t last_len = strlen(last);
3646 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3647 last[last_len-2] = '\0';
3650 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
3651 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
3652 log_info(LD_DIR,
3653 "Skipping digest pair %s with non-standard length.", escaped(cp));
3654 } else if (cp[HEX_DIGEST_LEN] != '-') {
3655 log_info(LD_DIR,
3656 "Skipping digest pair %s with missing dash.", escaped(cp));
3657 } else {
3658 fp_pair_t pair;
3659 if (base16_decode(pair.first, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0 ||
3660 base16_decode(pair.second,
3661 DIGEST_LEN, cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN)<0) {
3662 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
3663 } else {
3664 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
3667 tor_free(cp);
3668 } SMARTLIST_FOREACH_END(cp);
3669 smartlist_free(pairs_tmp);
3671 /* Uniq-and-sort */
3672 smartlist_sort(pairs_result, _compare_pairs);
3673 smartlist_uniq(pairs_result, _compare_pairs, _tor_free);
3675 smartlist_add_all(pairs_out, pairs_result);
3676 smartlist_free(pairs_result);
3677 return 0;
3680 /** Given a directory <b>resource</b> request, containing zero
3681 * or more strings separated by plus signs, followed optionally by ".z", store
3682 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3683 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
3685 * If (flags & DSR_HEX), then delete all elements that aren't hex digests, and
3686 * decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as
3687 * a separator, delete all the elements that aren't base64-encoded digests,
3688 * and decode the rest. If (flags & DSR_DIGEST256), these digests should be
3689 * 256 bits long; else they should be 160.
3691 * If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates.
3694 dir_split_resource_into_fingerprints(const char *resource,
3695 smartlist_t *fp_out, int *compressed_out,
3696 int flags)
3698 const int decode_hex = flags & DSR_HEX;
3699 const int decode_base64 = flags & DSR_BASE64;
3700 const int digests_are_256 = flags & DSR_DIGEST256;
3701 const int sort_uniq = flags & DSR_SORT_UNIQ;
3703 const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
3704 const int hex_digest_len = digests_are_256 ?
3705 HEX_DIGEST256_LEN : HEX_DIGEST_LEN;
3706 const int base64_digest_len = digests_are_256 ?
3707 BASE64_DIGEST256_LEN : BASE64_DIGEST_LEN;
3708 smartlist_t *fp_tmp = smartlist_create();
3710 tor_assert(!(decode_hex && decode_base64));
3711 tor_assert(fp_out);
3713 smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
3714 if (compressed_out)
3715 *compressed_out = 0;
3716 if (smartlist_len(fp_tmp)) {
3717 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3718 size_t last_len = strlen(last);
3719 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3720 last[last_len-2] = '\0';
3721 if (compressed_out)
3722 *compressed_out = 1;
3725 if (decode_hex || decode_base64) {
3726 const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
3727 int i;
3728 char *cp, *d = NULL;
3729 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3730 cp = smartlist_get(fp_tmp, i);
3731 if (strlen(cp) != encoded_len) {
3732 log_info(LD_DIR,
3733 "Skipping digest %s with non-standard length.", escaped(cp));
3734 smartlist_del_keeporder(fp_tmp, i--);
3735 goto again;
3737 d = tor_malloc_zero(digest_len);
3738 if (decode_hex ?
3739 (base16_decode(d, digest_len, cp, hex_digest_len)<0) :
3740 (base64_decode(d, digest_len, cp, base64_digest_len)<0)) {
3741 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3742 smartlist_del_keeporder(fp_tmp, i--);
3743 goto again;
3745 smartlist_set(fp_tmp, i, d);
3746 d = NULL;
3747 again:
3748 tor_free(cp);
3749 tor_free(d);
3752 if (sort_uniq) {
3753 if (decode_hex || decode_base64) {
3754 if (digests_are_256) {
3755 smartlist_sort_digests256(fp_tmp);
3756 smartlist_uniq_digests256(fp_tmp);
3757 } else {
3758 smartlist_sort_digests(fp_tmp);
3759 smartlist_uniq_digests(fp_tmp);
3761 } else {
3762 smartlist_sort_strings(fp_tmp);
3763 smartlist_uniq_strings(fp_tmp);
3766 smartlist_add_all(fp_out, fp_tmp);
3767 smartlist_free(fp_tmp);
3768 return 0;