make the complaints about missing v2hidserv directories quieter,
[tor.git] / src / or / directory.c
blob8e6d3c9eecd3bdb3b6277633ae531fca9b118a67
1 /* Copyright 2001-2004 Roger Dingledine.
2 * Copyright 2004-2007 Roger Dingledine, Nick Mathewson. */
3 /* See LICENSE for licensing information */
4 /* $Id$ */
5 const char directory_c_id[] =
6 "$Id$";
8 #include "or.h"
9 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
10 #include <malloc.h>
11 #endif
13 /**
14 * \file directory.c
15 * \brief Code to send and fetch directories and router
16 * descriptors via HTTP. Directories use dirserv.c to generate the
17 * results; clients use routers.c to parse them.
18 **/
20 /* In-points to directory.c:
22 * - directory_post_to_dirservers(), called from
23 * router_upload_dir_desc_to_dirservers() in router.c
24 * upload_service_descriptor() in rendservice.c
25 * - directory_get_from_dirserver(), called from
26 * rend_client_refetch_renddesc() in rendclient.c
27 * run_scheduled_events() in main.c
28 * do_hup() in main.c
29 * - connection_dir_process_inbuf(), called from
30 * connection_process_inbuf() in connection.c
31 * - connection_dir_finished_flushing(), called from
32 * connection_finished_flushing() in connection.c
33 * - connection_dir_finished_connecting(), called from
34 * connection_finished_connecting() in connection.c
36 static void directory_send_command(dir_connection_t *conn,
37 int purpose, int direct, const char *resource,
38 const char *payload, size_t payload_len,
39 time_t if_modified_since);
40 static int directory_handle_command(dir_connection_t *conn);
41 static int body_is_plausible(const char *body, size_t body_len, int purpose);
42 static int purpose_needs_anonymity(uint8_t dir_purpose,
43 uint8_t router_purpose);
44 static char *http_get_header(const char *headers, const char *which);
45 static void http_set_address_origin(const char *headers, connection_t *conn);
46 static void connection_dir_download_networkstatus_failed(
47 dir_connection_t *conn, int status_code);
48 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
49 static void connection_dir_download_cert_failed(
50 dir_connection_t *conn, int status_code);
51 static void dir_networkstatus_download_failed(smartlist_t *failed,
52 int status_code);
53 static void dir_routerdesc_download_failed(smartlist_t *failed,
54 int status_code,
55 int router_purpose,
56 int was_extrainfo,
57 int was_descriptor_digests);
58 static void note_request(const char *key, size_t bytes);
60 /********* START VARIABLES **********/
62 /** How far in the future do we allow a directory server to tell us it is
63 * before deciding that one of us has the wrong time? */
64 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
66 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
68 /** HTTP cache control: how long do we tell proxies they can cache each
69 * kind of document we serve? */
70 #define FULL_DIR_CACHE_LIFETIME (60*60)
71 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
72 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
73 #define ROUTERDESC_CACHE_LIFETIME (30*60)
74 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
75 #define ROBOTS_CACHE_LIFETIME (24*60*60)
77 /********* END VARIABLES ************/
79 /** Return true iff the directory purpose 'purpose' must use an
80 * anonymous connection to a directory. */
81 static int
82 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
84 if (get_options()->AllDirActionsPrivate)
85 return 1;
86 if (router_purpose == ROUTER_PURPOSE_BRIDGE && has_completed_circuit)
87 return 1; /* if no circuits yet, we may need this info to bootstrap. */
88 if (dir_purpose == DIR_PURPOSE_FETCH_DIR ||
89 dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
90 dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
91 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
92 dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
93 dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
94 dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
95 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
96 dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
97 dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
98 dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
99 dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
100 return 0;
101 return 1;
104 /** Return a newly allocated string describing <b>auth</b>. */
105 char *
106 authority_type_to_string(authority_type_t auth)
108 char *result;
109 smartlist_t *lst = smartlist_create();
110 if (auth & V1_AUTHORITY)
111 smartlist_add(lst, (void*)"V1");
112 if (auth & V2_AUTHORITY)
113 smartlist_add(lst, (void*)"V2");
114 if (auth & BRIDGE_AUTHORITY)
115 smartlist_add(lst, (void*)"Bridge");
116 if (auth & HIDSERV_AUTHORITY)
117 smartlist_add(lst, (void*)"Hidden service");
118 if (smartlist_len(lst)) {
119 result = smartlist_join_strings(lst, ", ", 0, NULL);
120 } else {
121 result = tor_strdup("[Not an authority]");
123 smartlist_free(lst);
124 return result;
127 /** Return a string describing a given directory connection purpose. */
128 static const char *
129 dir_conn_purpose_to_string(int purpose)
131 switch (purpose)
133 case DIR_PURPOSE_FETCH_DIR:
134 return "v1 directory fetch";
135 case DIR_PURPOSE_FETCH_RENDDESC:
136 return "hidden-service descriptor fetch";
137 case DIR_PURPOSE_UPLOAD_DIR:
138 return "server descriptor upload";
139 case DIR_PURPOSE_UPLOAD_RENDDESC:
140 return "hidden-service descriptor upload";
141 case DIR_PURPOSE_UPLOAD_VOTE:
142 return "server vote upload";
143 case DIR_PURPOSE_UPLOAD_SIGNATURES:
144 return "consensus signature upload";
145 case DIR_PURPOSE_FETCH_RUNNING_LIST:
146 return "running-routers fetch";
147 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
148 return "network-status fetch";
149 case DIR_PURPOSE_FETCH_SERVERDESC:
150 return "server descriptor fetch";
151 case DIR_PURPOSE_FETCH_EXTRAINFO:
152 return "extra-info fetch";
153 case DIR_PURPOSE_FETCH_CONSENSUS:
154 return "consensus network-status fetch";
155 case DIR_PURPOSE_FETCH_CERTIFICATE:
156 return "authority cert fetch";
157 case DIR_PURPOSE_FETCH_STATUS_VOTE:
158 return "status vote fetch";
159 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
160 return "consensus signature fetch";
161 case DIR_PURPOSE_FETCH_RENDDESC_V2:
162 return "hidden-service v2 descriptor fetch";
163 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
164 return "hidden-service v2 descriptor upload";
167 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
168 return "(unknown)";
171 /** Return true iff <b>identity_digest</b> is the digest of a router we
172 * believe to support extrainfo downloads. (If <b>is_authority</b> we do
173 * additional checking that's only valid for authorities.) */
175 router_supports_extrainfo(const char *identity_digest, int is_authority)
177 routerinfo_t *ri = router_get_by_digest(identity_digest);
179 if (ri) {
180 if (ri->caches_extra_info)
181 return 1;
182 if (is_authority && ri->platform &&
183 tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
184 return 1;
186 if (is_authority) {
187 routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
188 if (rs && rs->version_supports_extrainfo_upload)
189 return 1;
191 return 0;
194 /** Return true iff all trusted directory servers have accepted our
195 * server descriptor. */
197 directories_have_accepted_server_descriptor(void)
199 smartlist_t *servers = router_get_trusted_dir_servers();
200 or_options_t *options = get_options();
201 /* XXX020 If any authority of the needed type is down, this
202 * function will never return true. Perhaps we need to be
203 * tolerant of down servers? Or even better, should we change
204 * this so one successful upload is enough? -RD */
205 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
206 if ((d->type & options->_PublishServerDescriptor) &&
207 !d->has_accepted_serverdesc) {
208 return 0;
211 return 1;
214 /** Start a connection to every suitable directory authority, using
215 * connection purpose 'purpose' and uploading the payload 'payload'
216 * (length 'payload_len'). The purpose should be one of
217 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
219 * <b>type</b> specifies what sort of dir authorities (V1, V2,
220 * HIDSERV, BRIDGE) we should upload to.
222 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
223 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
224 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
225 * to all authorities, and the extra-info document to all authorities that
226 * support it.
228 void
229 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
230 authority_type_t type,
231 const char *payload,
232 size_t payload_len, size_t extrainfo_len)
234 int post_via_tor;
235 smartlist_t *dirservers = router_get_trusted_dir_servers();
236 int found = 0;
237 tor_assert(dirservers);
238 /* This tries dirservers which we believe to be down, but ultimately, that's
239 * harmless, and we may as well err on the side of getting things uploaded.
241 SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
243 routerstatus_t *rs = &(ds->fake_status);
244 size_t upload_len = payload_len;
246 if ((type & ds->type) == 0)
247 continue;
249 found = 1; /* at least one authority of this type was listed */
250 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
251 ds->has_accepted_serverdesc = 0;
253 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
254 upload_len += extrainfo_len;
255 log_info(LD_DIR, "Uploading an extrainfo (length %d)",
256 (int) extrainfo_len);
258 post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) ||
259 !fascist_firewall_allows_address_dir(ds->addr, ds->dir_port);
260 directory_initiate_command_routerstatus(rs, dir_purpose,
261 router_purpose,
262 post_via_tor,
263 NULL, payload, upload_len, 0);
265 if (!found) {
266 char *s = authority_type_to_string(type);
267 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
268 "of type '%s', but no authorities of that type listed!", s);
269 tor_free(s);
273 /** Start a connection to a random running directory server, using
274 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
275 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
276 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
277 * down, mark them up and try again.
279 void
280 directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
281 const char *resource, int retry_if_no_servers)
283 routerstatus_t *rs = NULL;
284 or_options_t *options = get_options();
285 int prefer_authority = server_mode(options) && dirserver_mode(options);
286 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
287 authority_type_t type;
288 int flags = retry_if_no_servers ? PDS_RETRY_IF_NO_SERVERS : 0;
289 time_t if_modified_since = 0;
291 /* FFFF we could break this switch into its own function, and call
292 * it elsewhere in directory.c. -RD */
293 switch (dir_purpose) {
294 case DIR_PURPOSE_FETCH_EXTRAINFO:
295 type = EXTRAINFO_CACHE |
296 (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
297 V2_AUTHORITY);
298 break;
299 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
300 case DIR_PURPOSE_FETCH_SERVERDESC:
301 type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
302 V2_AUTHORITY);
303 break;
304 case DIR_PURPOSE_FETCH_DIR:
305 case DIR_PURPOSE_FETCH_RUNNING_LIST:
306 type = V1_AUTHORITY;
307 break;
308 case DIR_PURPOSE_FETCH_RENDDESC:
309 type = HIDSERV_AUTHORITY;
310 break;
311 case DIR_PURPOSE_FETCH_STATUS_VOTE:
312 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
313 type = V3_AUTHORITY;
314 break;
315 case DIR_PURPOSE_FETCH_CONSENSUS:
316 case DIR_PURPOSE_FETCH_CERTIFICATE:
317 type = V3_AUTHORITY;
318 break;
319 default:
320 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
321 return;
324 if (DIR_PURPOSE_FETCH_CONSENSUS) {
325 networkstatus_vote_t *v = networkstatus_get_latest_consensus();
326 if (v)
327 if_modified_since = v->valid_after + 180;
330 if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
331 return;
333 if (!get_via_tor) {
334 if (options->UseBridges && type != BRIDGE_AUTHORITY) {
335 /* want to ask a running bridge for which we have a descriptor. */
336 /* XXX020 we assume that all of our bridges can answer any
337 * possible directory question. This won't be true forever. -RD */
338 routerinfo_t *ri = choose_random_entry(NULL);
339 if (ri) {
340 directory_initiate_command(ri->address, ri->addr,
341 ri->or_port, 0,
342 1, ri->cache_info.identity_digest,
343 dir_purpose,
344 router_purpose,
345 0, resource, NULL, 0, if_modified_since);
346 } else
347 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
348 "nodes are available yet.");
349 return;
350 } else {
351 if (prefer_authority || type == BRIDGE_AUTHORITY) {
352 /* only ask authdirservers, and don't ask myself */
353 rs = router_pick_trusteddirserver(type, flags);
355 if (!rs && type != BRIDGE_AUTHORITY) {
356 /* anybody with a non-zero dirport will do */
357 rs = router_pick_directory_server(type, flags);
358 if (!rs) {
359 log_info(LD_DIR, "No router found for %s; falling back to "
360 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
361 rs = router_pick_trusteddirserver(type, flags);
362 if (!rs)
363 get_via_tor = 1; /* last resort: try routing it via Tor */
367 } else { /* get_via_tor */
368 /* Never use fascistfirewall; we're going via Tor. */
369 if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
370 /* only ask hidserv authorities, any of them will do */
371 flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
372 rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, flags);
373 } else {
374 /* anybody with a non-zero dirport will do. Disregard firewalls. */
375 flags |= PDS_IGNORE_FASCISTFIREWALL;
376 rs = router_pick_directory_server(type, flags);
377 /* If we have any hope of building an indirect conn, we know some router
378 * descriptors. If (rs==NULL), we can't build circuits anyway, so
379 * there's no point in falling back to the authorities in this case. */
383 if (rs)
384 directory_initiate_command_routerstatus(rs, dir_purpose,
385 router_purpose,
386 get_via_tor,
387 resource, NULL, 0,
388 if_modified_since);
389 else {
390 log_notice(LD_DIR,
391 "While fetching directory info, "
392 "no running dirservers known. Will try again later. "
393 "(purpose %d)", dir_purpose);
394 if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
395 /* remember we tried them all and failed. */
396 directory_all_unreachable(time(NULL));
401 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
402 * directory authority other than ourself. Only for use by authorities when
403 * searching for missing information while voting. */
404 void
405 directory_get_from_all_authorities(uint8_t dir_purpose,
406 uint8_t router_purpose,
407 const char *resource)
409 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
410 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
412 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
413 trusted_dir_server_t *, ds,
415 routerstatus_t *rs;
416 if (router_digest_is_me(ds->digest))
417 continue;
418 if (!(ds->type & V3_AUTHORITY))
419 continue;
420 rs = &ds->fake_status;
421 directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
422 0, resource, NULL, 0, 0);
426 /** Launch a new connection to the directory server <b>status</b> to
427 * upload or download a server or rendezvous
428 * descriptor. <b>dir_purpose</b> determines what
429 * kind of directory connection we're launching, and must be one of
430 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC|RENDDESC_V2}. <b>router_purpose</b>
431 * specifies the descriptor purposes we have in mind (currently only
432 * used for FETCH_DIR).
434 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
435 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
437 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
438 * want to fetch.
440 void
441 directory_initiate_command_routerstatus(routerstatus_t *status,
442 uint8_t dir_purpose,
443 uint8_t router_purpose,
444 int anonymized_connection,
445 const char *resource,
446 const char *payload,
447 size_t payload_len,
448 time_t if_modified_since)
450 routerinfo_t *router;
451 char address_buf[INET_NTOA_BUF_LEN+1];
452 struct in_addr in;
453 const char *address;
454 if ((router = router_get_by_digest(status->identity_digest))) {
455 address = router->address;
456 } else {
457 in.s_addr = htonl(status->addr);
458 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
459 address = address_buf;
461 directory_initiate_command(address, status->addr,
462 status->or_port, status->dir_port,
463 status->version_supports_begindir,
464 status->identity_digest,
465 dir_purpose, router_purpose,
466 anonymized_connection, resource,
467 payload, payload_len, if_modified_since);
470 /** Return true iff <b>conn</b> is the client side of a directory connection
471 * we launched to ourself in order to determine the reachability of our
472 * dir_port. */
473 static int
474 directory_conn_is_self_reachability_test(dir_connection_t *conn)
476 if (conn->requested_resource &&
477 !strcmpstart(conn->requested_resource,"authority")) {
478 routerinfo_t *me = router_get_my_routerinfo();
479 if (me &&
480 router_digest_is_me(conn->identity_digest) &&
481 me->addr == conn->_base.addr &&
482 me->dir_port == conn->_base.port)
483 return 1;
485 return 0;
488 /** Called when we are unable to complete the client's request to a directory
489 * server due to a network error: Mark the router as down and try again if
490 * possible.
492 void
493 connection_dir_request_failed(dir_connection_t *conn)
495 if (directory_conn_is_self_reachability_test(conn)) {
496 routerinfo_t *me = router_get_my_routerinfo();
497 if (me)
498 control_event_server_status(LOG_WARN,
499 "REACHABILITY_FAILED DIRADDRESS=%s:%d",
500 me->address, me->dir_port);
501 return; /* this was a test fetch. don't retry. */
503 router_set_status(conn->identity_digest, 0); /* don't try him again */
504 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR ||
505 conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
506 log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
507 conn->_base.address, conn->_base.port);
508 directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose,
509 NULL, 0 /* don't retry_if_no_servers */);
510 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
511 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
512 conn->_base.address);
513 connection_dir_download_networkstatus_failed(conn, -1);
514 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
515 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
516 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
517 conn->_base.address);
518 connection_dir_download_routerdesc_failed(conn);
519 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
520 networkstatus_consensus_download_failed(0);
521 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
522 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
523 conn->_base.address);
524 connection_dir_download_cert_failed(conn, 0);
525 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
526 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
527 conn->_base.address);
528 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
529 log_info(LD_DIR, "Giving up downloading votes from '%s'",
530 conn->_base.address);
534 /** Called when an attempt to download one or more network status
535 * documents on connection <b>conn</b> failed. Decide whether to
536 * retry the fetch now, later, or never.
538 static void
539 connection_dir_download_networkstatus_failed(dir_connection_t *conn,
540 int status_code)
542 if (!conn->requested_resource) {
543 /* We never reached directory_send_command, which means that we never
544 * opened a network connection. Either we're out of sockets, or the
545 * network is down. Either way, retrying would be pointless. */
546 return;
548 if (!strcmpstart(conn->requested_resource, "all")) {
549 /* We're a non-authoritative directory cache; try again. Ignore status
550 * code, since we don't want to keep trying forever in a tight loop
551 * if all the authorities are shutting us out. */
552 smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
553 SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
554 download_status_failed(&ds->v2_ns_dl_status, 0));
555 directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose,
556 "all.z", 0 /* don't retry_if_no_servers */);
557 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
558 /* We were trying to download by fingerprint; mark them all as having
559 * failed, and possibly retry them later.*/
560 smartlist_t *failed = smartlist_create();
561 dir_split_resource_into_fingerprints(conn->requested_resource+3,
562 failed, NULL, 0, 0);
563 if (smartlist_len(failed)) {
564 dir_networkstatus_download_failed(failed, status_code);
565 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
567 smartlist_free(failed);
571 /** Called when an attempt to download one or more router descriptors
572 * or extra-info documents on connection <b>conn</b> failed.
574 static void
575 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
577 /* No need to increment the failure count for routerdescs, since
578 * it's not their fault. */
580 /* No need to relaunch descriptor downloads here: we already do it
581 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
582 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
583 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
585 (void) conn;
588 /** Called when an attempt to fetch a certificate fails. */
589 static void
590 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
592 smartlist_t *failed;
593 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
595 if (!conn->requested_resource)
596 return;
597 failed = smartlist_create();
598 dir_split_resource_into_fingerprints(conn->requested_resource+3,
599 failed, NULL, 1, 0);
600 SMARTLIST_FOREACH(failed, char *, cp,
602 trusted_dir_server_t *dir = trusteddirserver_get_by_v3_auth_digest(cp);
603 if (dir)
604 download_status_failed(&dir->cert_dl_status, status);
605 tor_free(cp);
607 smartlist_free(failed);
609 update_certificate_downloads(time(NULL));
612 /** Helper for directory_initiate_command_routerstatus: send the
613 * command to a server whose address is <b>address</b>, whose IP is
614 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
615 * <b>supports_begindir</b>, and whose identity key digest is
616 * <b>digest</b>. */
617 void
618 directory_initiate_command(const char *address, uint32_t addr,
619 uint16_t or_port, uint16_t dir_port,
620 int supports_begindir, const char *digest,
621 uint8_t dir_purpose, uint8_t router_purpose,
622 int anonymized_connection, const char *resource,
623 const char *payload, size_t payload_len,
624 time_t if_modified_since)
626 dir_connection_t *conn;
627 or_options_t *options = get_options();
628 int use_begindir = supports_begindir && or_port &&
629 (options->TunnelDirConns ||
630 router_purpose == ROUTER_PURPOSE_BRIDGE) &&
631 (anonymized_connection ||
632 fascist_firewall_allows_address_or(addr, or_port));
634 tor_assert(address);
635 tor_assert(addr);
636 tor_assert(or_port || dir_port);
637 tor_assert(digest);
639 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
640 anonymized_connection, use_begindir);
642 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
644 conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
646 /* set up conn so it's got all the data we need to remember */
647 conn->_base.addr = addr;
648 conn->_base.port = use_begindir ? or_port : dir_port;
649 conn->_base.address = tor_strdup(address);
650 memcpy(conn->identity_digest, digest, DIGEST_LEN);
652 conn->_base.purpose = dir_purpose;
653 conn->router_purpose = router_purpose;
655 /* give it an initial state */
656 conn->_base.state = DIR_CONN_STATE_CONNECTING;
658 /* decide whether we can learn our IP address from this conn */
659 conn->dirconn_direct = !anonymized_connection;
661 if (!anonymized_connection && !use_begindir) {
662 /* then we want to connect to dirport directly */
664 if (options->HttpProxy) {
665 addr = options->HttpProxyAddr;
666 dir_port = options->HttpProxyPort;
669 switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
670 dir_port)) {
671 case -1:
672 connection_dir_request_failed(conn); /* retry if we want */
673 /* XXX we only pass 'conn' above, not 'resource', 'payload',
674 * etc. So in many situations it can't retry! -RD */
675 connection_free(TO_CONN(conn));
676 return;
677 case 1:
678 /* start flushing conn */
679 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
680 /* fall through */
681 case 0:
682 /* queue the command on the outbuf */
683 directory_send_command(conn, dir_purpose, 1, resource,
684 payload, payload_len, if_modified_since);
685 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
686 /* writable indicates finish, readable indicates broken link,
687 error indicates broken link in windowsland. */
689 } else { /* we want to connect via a tor connection */
690 edge_connection_t *linked_conn;
691 /* make an AP connection
692 * populate it and add it at the right state
693 * hook up both sides
695 linked_conn =
696 connection_ap_make_link(conn->_base.address, conn->_base.port,
697 digest, use_begindir, conn->dirconn_direct);
698 if (!linked_conn) {
699 log_warn(LD_NET,"Making tunnel to dirserver failed.");
700 connection_mark_for_close(TO_CONN(conn));
701 return;
703 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
705 if (connection_add(TO_CONN(conn)) < 0) {
706 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
707 connection_mark_for_close(TO_CONN(conn));
708 return;
710 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
711 /* queue the command on the outbuf */
712 directory_send_command(conn, dir_purpose, 0, resource,
713 payload, payload_len, if_modified_since);
714 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
715 connection_start_reading(TO_CONN(linked_conn));
719 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
720 * are as in directory_initiate_command.
722 static void
723 directory_send_command(dir_connection_t *conn,
724 int purpose, int direct, const char *resource,
725 const char *payload, size_t payload_len,
726 time_t if_modified_since)
728 char proxystring[256];
729 char proxyauthstring[256];
730 char hoststring[128];
731 char imsstring[RFC1123_TIME_LEN+32];
732 char *url;
733 char request[8192];
734 const char *httpcommand = NULL;
735 size_t len;
737 tor_assert(conn);
738 tor_assert(conn->_base.type == CONN_TYPE_DIR);
740 tor_free(conn->requested_resource);
741 if (resource)
742 conn->requested_resource = tor_strdup(resource);
744 /* come up with a string for which Host: we want */
745 if (conn->_base.port == 80) {
746 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
747 } else {
748 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
749 conn->_base.address, conn->_base.port);
752 /* Format if-modified-since */
753 if (!if_modified_since) {
754 imsstring[0] = '\0';
755 } else {
756 char b[RFC1123_TIME_LEN+1];
757 format_rfc1123_time(b, if_modified_since);
758 tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
761 /* come up with some proxy lines, if we're using one. */
762 if (direct && get_options()->HttpProxy) {
763 char *base64_authenticator=NULL;
764 const char *authenticator = get_options()->HttpProxyAuthenticator;
766 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
767 if (authenticator) {
768 base64_authenticator = alloc_http_authenticator(authenticator);
769 if (!base64_authenticator)
770 log_warn(LD_BUG, "Encoding http authenticator failed");
772 if (base64_authenticator) {
773 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
774 "\r\nProxy-Authorization: Basic %s",
775 base64_authenticator);
776 tor_free(base64_authenticator);
777 } else {
778 proxyauthstring[0] = 0;
780 } else {
781 proxystring[0] = 0;
782 proxyauthstring[0] = 0;
785 switch (purpose) {
786 case DIR_PURPOSE_FETCH_DIR:
787 tor_assert(!resource);
788 tor_assert(!payload);
789 httpcommand = "GET";
790 url = tor_strdup("/tor/dir.z");
791 break;
792 case DIR_PURPOSE_FETCH_RUNNING_LIST:
793 tor_assert(!resource);
794 tor_assert(!payload);
795 httpcommand = "GET";
796 url = tor_strdup("/tor/running-routers");
797 break;
798 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
799 httpcommand = "GET";
800 len = strlen(resource)+32;
801 url = tor_malloc(len);
802 tor_snprintf(url, len, "/tor/status/%s", resource);
803 break;
804 case DIR_PURPOSE_FETCH_CONSENSUS:
805 tor_assert(!resource);
806 tor_assert(!payload);
807 httpcommand = "GET";
808 url = tor_strdup("/tor/status-vote/current/consensus.z");
809 break;
810 case DIR_PURPOSE_FETCH_CERTIFICATE:
811 tor_assert(resource);
812 tor_assert(!payload);
813 httpcommand = "GET";
814 len = strlen(resource)+32;
815 url = tor_malloc(len);
816 tor_snprintf(url, len, "/tor/keys/%s", resource);
817 break;
818 case DIR_PURPOSE_FETCH_STATUS_VOTE:
819 tor_assert(resource);
820 tor_assert(!payload);
821 httpcommand = "GET";
822 len = strlen(resource)+32;
823 url = tor_malloc(len);
824 tor_snprintf(url, len, "/tor/status-vote/next/%s.z", resource);
825 break;
826 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
827 tor_assert(!resource);
828 tor_assert(!payload);
829 httpcommand = "GET";
830 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
831 break;
832 case DIR_PURPOSE_FETCH_SERVERDESC:
833 httpcommand = "GET";
834 len = strlen(resource)+32;
835 url = tor_malloc(len);
836 tor_snprintf(url, len, "/tor/server/%s", resource);
837 break;
838 case DIR_PURPOSE_FETCH_EXTRAINFO:
839 httpcommand = "GET";
840 len = strlen(resource)+32;
841 url = tor_malloc(len);
842 tor_snprintf(url, len, "/tor/extra/%s", resource);
843 break;
844 case DIR_PURPOSE_UPLOAD_DIR:
845 tor_assert(!resource);
846 tor_assert(payload);
847 httpcommand = "POST";
848 url = tor_strdup("/tor/");
849 break;
850 case DIR_PURPOSE_UPLOAD_VOTE:
851 tor_assert(!resource);
852 tor_assert(payload);
853 httpcommand = "POST";
854 url = tor_strdup("/tor/post/vote");
855 break;
856 case DIR_PURPOSE_UPLOAD_SIGNATURES:
857 tor_assert(!resource);
858 tor_assert(payload);
859 httpcommand = "POST";
860 url = tor_strdup("/tor/post/consensus-signature");
861 break;
862 case DIR_PURPOSE_FETCH_RENDDESC:
863 tor_assert(resource);
864 tor_assert(!payload);
866 /* this must be true or we wouldn't be doing the lookup */
867 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN);
868 /* This breaks the function abstraction. */
869 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
871 httpcommand = "GET";
872 /* Request the most recent versioned descriptor. */
873 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
874 // but that never got testing, and it wasn't a good design.)
875 len = strlen(resource)+32;
876 url = tor_malloc(len);
877 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
878 break;
879 case DIR_PURPOSE_FETCH_RENDDESC_V2:
880 tor_assert(resource);
881 tor_assert(!payload);
882 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
883 httpcommand = "GET";
884 len = strlen(resource) + 32;
885 url = tor_malloc(len);
886 tor_snprintf(url, len, "/tor/rendezvous2/%s", resource);
887 break;
888 case DIR_PURPOSE_UPLOAD_RENDDESC:
889 tor_assert(!resource);
890 tor_assert(payload);
891 httpcommand = "POST";
892 url = tor_strdup("/tor/rendezvous/publish");
893 break;
894 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
895 tor_assert(!resource);
896 tor_assert(payload);
897 httpcommand = "POST";
898 url = tor_strdup("/tor/rendezvous2/publish");
899 break;
900 default:
901 tor_assert(0);
902 return;
905 if (strlen(proxystring) + strlen(url) >= 4096) {
906 log_warn(LD_BUG,
907 "Squid does not like URLs longer than 4095 bytes, and this "
908 "one is %d bytes long: %s%s",
909 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
912 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
913 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
914 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
915 tor_free(url);
917 if (!strcmp(httpcommand, "GET") && !payload) {
918 tor_snprintf(request, sizeof(request),
919 " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
920 hoststring,
921 imsstring,
922 proxyauthstring);
923 } else {
924 tor_snprintf(request, sizeof(request),
925 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
926 payload ? (unsigned long)payload_len : 0,
927 hoststring,
928 imsstring,
929 proxyauthstring);
931 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
933 if (payload) {
934 /* then send the payload afterwards too */
935 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
939 /** Parse an HTTP request string <b>headers</b> of the form
940 * \verbatim
941 * "\%s [http[s]://]\%s HTTP/1..."
942 * \endverbatim
943 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
944 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
945 * so it does. Return 0.
946 * Otherwise, return -1.
948 static int
949 parse_http_url(const char *headers, char **url)
951 char *s, *start, *tmp;
953 s = (char *)eat_whitespace_no_nl(headers);
954 if (!*s) return -1;
955 s = (char *)find_whitespace(s); /* get past GET/POST */
956 if (!*s) return -1;
957 s = (char *)eat_whitespace_no_nl(s);
958 if (!*s) return -1;
959 start = s; /* this is it, assuming it's valid */
960 s = (char *)find_whitespace(start);
961 if (!*s) return -1;
963 /* tolerate the http[s] proxy style of putting the hostname in the url */
964 if (s-start >= 4 && !strcmpstart(start,"http")) {
965 tmp = start + 4;
966 if (*tmp == 's')
967 tmp++;
968 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
969 tmp = strchr(tmp+3, '/');
970 if (tmp && tmp < s) {
971 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
972 start = tmp;
977 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
978 *url = tor_malloc(s - start + 5);
979 strlcpy(*url,"/tor", s-start+5);
980 strlcat((*url)+4, start, s-start+1);
981 } else {
982 *url = tor_strndup(start, s-start);
984 return 0;
987 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
988 * <b>which</b>. The key should be given with a terminating colon and space;
989 * this function copies everything after, up to but not including the
990 * following \\r\\n. */
991 static char *
992 http_get_header(const char *headers, const char *which)
994 const char *cp = headers;
995 while (cp) {
996 if (!strcmpstart(cp, which)) {
997 char *eos;
998 cp += strlen(which);
999 if ((eos = strchr(cp,'\r')))
1000 return tor_strndup(cp, eos-cp);
1001 else
1002 return tor_strdup(cp);
1004 cp = strchr(cp, '\n');
1005 if (cp)
1006 ++cp;
1008 return NULL;
1011 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1012 * <b>conn</b>-\>address to describe our best guess of the address that
1013 * originated this HTTP request. */
1014 static void
1015 http_set_address_origin(const char *headers, connection_t *conn)
1017 char *fwd;
1019 fwd = http_get_header(headers, "Forwarded-For: ");
1020 if (!fwd)
1021 fwd = http_get_header(headers, "X-Forwarded-For: ");
1022 if (fwd) {
1023 struct in_addr in;
1024 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
1025 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
1026 escaped(fwd));
1027 tor_free(fwd);
1028 return;
1030 tor_free(conn->address);
1031 conn->address = tor_strdup(fwd);
1032 tor_free(fwd);
1036 /** Parse an HTTP response string <b>headers</b> of the form
1037 * \verbatim
1038 * "HTTP/1.\%d \%d\%s\r\n...".
1039 * \endverbatim
1041 * If it's well-formed, assign the status code to *<b>code</b> and
1042 * return 0. Otherwise, return -1.
1044 * On success: If <b>date</b> is provided, set *date to the Date
1045 * header in the http headers, or 0 if no such header is found. If
1046 * <b>compression</b> is provided, set *<b>compression</b> to the
1047 * compression method given in the Content-Encoding header, or 0 if no
1048 * such header is found, or -1 if the value of the header is not
1049 * recognized. If <b>reason</b> is provided, strdup the reason string
1050 * into it.
1053 parse_http_response(const char *headers, int *code, time_t *date,
1054 compress_method_t *compression, char **reason)
1056 int n1, n2;
1057 char datestr[RFC1123_TIME_LEN+1];
1058 smartlist_t *parsed_headers;
1059 tor_assert(headers);
1060 tor_assert(code);
1062 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1064 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
1065 (n1 != 0 && n1 != 1) ||
1066 (n2 < 100 || n2 >= 600)) {
1067 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1068 return -1;
1070 *code = n2;
1072 parsed_headers = smartlist_create();
1073 smartlist_split_string(parsed_headers, headers, "\n",
1074 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1075 if (reason) {
1076 smartlist_t *status_line_elements = smartlist_create();
1077 tor_assert(smartlist_len(parsed_headers));
1078 smartlist_split_string(status_line_elements,
1079 smartlist_get(parsed_headers, 0),
1080 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1081 tor_assert(smartlist_len(status_line_elements) <= 3);
1082 if (smartlist_len(status_line_elements) == 3) {
1083 *reason = smartlist_get(status_line_elements, 2);
1084 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1086 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1087 smartlist_free(status_line_elements);
1089 if (date) {
1090 *date = 0;
1091 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1092 if (!strcmpstart(s, "Date: ")) {
1093 strlcpy(datestr, s+6, sizeof(datestr));
1094 /* This will do nothing on failure, so we don't need to check
1095 the result. We shouldn't warn, since there are many other valid
1096 date formats besides the one we use. */
1097 parse_rfc1123_time(datestr, date);
1098 break;
1101 if (compression) {
1102 const char *enc = NULL;
1103 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1104 if (!strcmpstart(s, "Content-Encoding: ")) {
1105 enc = s+18; break;
1107 if (!enc || !strcmp(enc, "identity")) {
1108 *compression = NO_METHOD;
1109 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1110 *compression = ZLIB_METHOD;
1111 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1112 *compression = GZIP_METHOD;
1113 } else {
1114 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1115 escaped(enc));
1116 *compression = UNKNOWN_METHOD;
1119 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1120 smartlist_free(parsed_headers);
1122 return 0;
1125 /** Return true iff <b>body</b> doesn't start with a plausible router or
1126 * running-list or directory opening. This is a sign of possible compression.
1128 static int
1129 body_is_plausible(const char *body, size_t len, int purpose)
1131 int i;
1132 if (len == 0)
1133 return 1; /* empty bodies don't need decompression */
1134 if (len < 32)
1135 return 0;
1136 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
1137 if (!strcmpstart(body,"router") ||
1138 !strcmpstart(body,"signed-directory") ||
1139 !strcmpstart(body,"network-status") ||
1140 !strcmpstart(body,"running-routers"))
1141 return 1;
1142 for (i=0;i<32;++i) {
1143 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1144 return 0;
1146 return 1;
1147 } else {
1148 return 1;
1152 /** Called when we've just fetched a bunch of router descriptors in
1153 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1154 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1155 * is true, or identity digests otherwise. Parse the descriptors, validate
1156 * them, and annotate them as having purpose <b>purpose</b> and as having been
1157 * downloaded from <b>source</b>. */
1158 static void
1159 load_downloaded_routers(const char *body, smartlist_t *which,
1160 int descriptor_digests,
1161 int router_purpose,
1162 const char *source)
1164 char buf[256];
1165 char time_buf[ISO_TIME_LEN+1];
1166 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1167 format_iso_time(time_buf, time(NULL));
1168 tor_assert(source);
1170 if (tor_snprintf(buf, sizeof(buf),
1171 "@downloaded-at %s\n"
1172 "@source %s\n"
1173 "%s%s%s", time_buf, escaped(source),
1174 !general ? "@purpose " : "",
1175 !general ? router_purpose_to_string(router_purpose) : "",
1176 !general ? "\n" : "")<0)
1177 return;
1179 router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1180 descriptor_digests, buf);
1183 /** We are a client, and we've finished reading the server's
1184 * response. Parse and it and act appropriately.
1186 * If we're still happy with using this directory server in the future, return
1187 * 0. Otherwise return -1; and the caller should consider trying the request
1188 * again.
1190 * The caller will take care of marking the connection for close.
1192 static int
1193 connection_dir_client_reached_eof(dir_connection_t *conn)
1195 char *body;
1196 char *headers;
1197 char *reason = NULL;
1198 size_t body_len=0, orig_len=0;
1199 int status_code;
1200 time_t date_header=0;
1201 int delta;
1202 compress_method_t compression;
1203 int plausible;
1204 int skewed=0;
1205 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1206 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
1207 int was_compressed=0;
1208 time_t now = time(NULL);
1210 switch (fetch_from_buf_http(conn->_base.inbuf,
1211 &headers, MAX_HEADERS_SIZE,
1212 &body, &body_len, MAX_DIR_DL_SIZE,
1213 allow_partial)) {
1214 case -1: /* overflow */
1215 log_warn(LD_PROTOCOL,
1216 "'fetch' response too large (server '%s:%d'). Closing.",
1217 conn->_base.address, conn->_base.port);
1218 return -1;
1219 case 0:
1220 log_info(LD_HTTP,
1221 "'fetch' response not all here, but we're at eof. Closing.");
1222 return -1;
1223 /* case 1, fall through */
1225 orig_len = body_len;
1227 if (parse_http_response(headers, &status_code, &date_header,
1228 &compression, &reason) < 0) {
1229 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1230 conn->_base.address, conn->_base.port);
1231 tor_free(body); tor_free(headers);
1232 return -1;
1234 if (!reason) reason = tor_strdup("[no reason given]");
1236 log_debug(LD_DIR,
1237 "Received response from directory server '%s:%d': %d %s",
1238 conn->_base.address, conn->_base.port, status_code,
1239 escaped(reason));
1241 /* now check if it's got any hints for us about our IP address. */
1242 if (conn->dirconn_direct) {
1243 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1244 if (guess) {
1245 router_new_address_suggestion(guess);
1246 tor_free(guess);
1250 if (date_header > 0) {
1251 /* The date header was written very soon after we sent our request,
1252 * so compute the skew as the difference between sending the request
1253 * and the date header. (We used to check now-date_header, but that's
1254 * inaccurate if we spend a lot of time downloading.)
1256 delta = conn->_base.timestamp_lastwritten - date_header;
1257 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1258 char dbuf[64];
1259 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1260 format_time_interval(dbuf, sizeof(dbuf), delta);
1261 log_fn(trusted ? LOG_WARN : LOG_INFO,
1262 LD_HTTP,
1263 "Received directory with skewed time (server '%s:%d'): "
1264 "It seems that our clock is %s by %s, or that theirs is %s. "
1265 "Tor requires an accurate clock to work: please check your time "
1266 "and date settings.",
1267 conn->_base.address, conn->_base.port,
1268 delta>0 ? "ahead" : "behind", dbuf,
1269 delta>0 ? "behind" : "ahead");
1270 skewed = 1; /* don't check the recommended-versions line */
1271 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1272 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
1273 delta, conn->_base.address, conn->_base.port);
1274 } else {
1275 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1276 "we are %d seconds skewed. (That's okay.)", delta);
1279 (void) skewed; /* skewed isn't used yet. */
1281 if (status_code == 503) {
1282 routerstatus_t *rs;
1283 trusted_dir_server_t *ds;
1284 log_info(LD_DIR,"Received http status code %d (%s) from server "
1285 "'%s:%d'. I'll try again soon.",
1286 status_code, escaped(reason), conn->_base.address,
1287 conn->_base.port);
1288 if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
1289 rs->last_dir_503_at = now;
1290 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1291 ds->fake_status.last_dir_503_at = now;
1293 tor_free(body); tor_free(headers); tor_free(reason);
1294 return -1;
1297 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1298 if (compression != NO_METHOD || !plausible) {
1299 char *new_body = NULL;
1300 size_t new_len = 0;
1301 compress_method_t guessed = detect_compression_method(body, body_len);
1302 if (compression == UNKNOWN_METHOD || guessed != compression) {
1303 /* Tell the user if we don't believe what we're told about compression.*/
1304 const char *description1, *description2;
1305 if (compression == ZLIB_METHOD)
1306 description1 = "as deflated";
1307 else if (compression == GZIP_METHOD)
1308 description1 = "as gzipped";
1309 else if (compression == NO_METHOD)
1310 description1 = "as uncompressed";
1311 else
1312 description1 = "with an unknown Content-Encoding";
1313 if (guessed == ZLIB_METHOD)
1314 description2 = "deflated";
1315 else if (guessed == GZIP_METHOD)
1316 description2 = "gzipped";
1317 else if (!plausible)
1318 description2 = "confusing binary junk";
1319 else
1320 description2 = "uncompressed";
1322 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1323 "but it seems to be %s.%s",
1324 conn->_base.address, conn->_base.port, description1,
1325 description2,
1326 (compression>0 && guessed>0)?" Trying both.":"");
1328 /* Try declared compression first if we can. */
1329 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1330 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1331 !allow_partial, LOG_PROTOCOL_WARN);
1332 /* Okay, if that didn't work, and we think that it was compressed
1333 * differently, try that. */
1334 if (!new_body &&
1335 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1336 compression != guessed)
1337 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1338 !allow_partial, LOG_PROTOCOL_WARN);
1339 /* If we're pretty sure that we have a compressed directory, and
1340 * we didn't manage to uncompress it, then warn and bail. */
1341 if (!plausible && !new_body) {
1342 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1343 "Unable to decompress HTTP body (server '%s:%d').",
1344 conn->_base.address, conn->_base.port);
1345 tor_free(body); tor_free(headers); tor_free(reason);
1346 return -1;
1348 if (new_body) {
1349 tor_free(body);
1350 body = new_body;
1351 body_len = new_len;
1352 was_compressed = 1;
1356 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
1357 /* fetch/process the directory to cache it. */
1358 log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
1359 (int)body_len, conn->_base.address, conn->_base.port);
1360 if (status_code != 200) {
1361 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1362 "'%s:%d' while fetching directory. I'll try again soon.",
1363 status_code, escaped(reason), conn->_base.address,
1364 conn->_base.port);
1365 tor_free(body); tor_free(headers); tor_free(reason);
1366 return -1;
1368 if (router_parse_directory(body) < 0) {
1369 log_notice(LD_DIR,"I failed to parse the directory I fetched from "
1370 "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
1372 note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
1375 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
1376 /* just update our list of running routers, if this list is new info */
1377 log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
1378 if (status_code != 200) {
1379 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1380 "'%s:%d' while fetching running-routers. I'll try again soon.",
1381 status_code, escaped(reason), conn->_base.address,
1382 conn->_base.port);
1383 tor_free(body); tor_free(headers); tor_free(reason);
1384 return -1;
1386 if (router_parse_runningrouters(body)<0) {
1387 log_warn(LD_DIR,
1388 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1389 conn->_base.address, conn->_base.port);
1390 tor_free(body); tor_free(headers); tor_free(reason);
1391 return -1;
1393 note_request(was_compressed?"dl/running-routers.z":
1394 "dl/running-routers", orig_len);
1397 if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
1398 smartlist_t *which = NULL;
1399 networkstatus_source_t source;
1400 char *cp;
1401 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1402 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1403 if (status_code != 200) {
1404 log_warn(LD_DIR,
1405 "Received http status code %d (%s) from server "
1406 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1407 status_code, escaped(reason), conn->_base.address,
1408 conn->_base.port, conn->requested_resource);
1409 tor_free(body); tor_free(headers); tor_free(reason);
1410 connection_dir_download_networkstatus_failed(conn, status_code);
1411 return -1;
1413 note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
1414 if (conn->requested_resource &&
1415 !strcmpstart(conn->requested_resource,"fp/")) {
1416 source = NS_FROM_DIR_BY_FP;
1417 which = smartlist_create();
1418 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1419 which, NULL, 0, 0);
1420 } else if (conn->requested_resource &&
1421 !strcmpstart(conn->requested_resource, "all")) {
1422 source = NS_FROM_DIR_ALL;
1423 which = smartlist_create();
1424 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1425 trusted_dir_server_t *, ds,
1427 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1428 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1429 smartlist_add(which, hex);
1431 } else {
1432 /* XXXX Can we even end up here? -- weasel*/
1433 source = NS_FROM_DIR_BY_FP;
1434 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1435 "for it by fp, nor did we ask for all.");
1437 cp = body;
1438 while (*cp) {
1439 char *next = strstr(cp, "\nnetwork-status-version");
1440 if (next)
1441 next[1] = '\0';
1442 /* learn from it, and then remove it from 'which' */
1443 if (router_set_networkstatus_v2(cp, now, source, which)<0)
1444 break;
1445 if (next) {
1446 next[1] = 'n';
1447 cp = next+1;
1448 } else
1449 break;
1451 routers_update_all_from_networkstatus(now); /*launches router downloads*/
1452 directory_info_has_arrived(now, 0);
1453 if (which) {
1454 if (smartlist_len(which)) {
1455 dir_networkstatus_download_failed(which, status_code);
1457 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1458 smartlist_free(which);
1462 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1463 int r;
1464 if (status_code != 200) {
1465 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1466 log(severity, LD_DIR,
1467 "Received http status code %d (%s) from server "
1468 "'%s:%d' while fetching consensus directory.",
1469 status_code, escaped(reason), conn->_base.address,
1470 conn->_base.port);
1471 tor_free(body); tor_free(headers); tor_free(reason);
1472 networkstatus_consensus_download_failed(status_code);
1473 return -1;
1475 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1476 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1477 if ((r=networkstatus_set_current_consensus(body, 0, 0))<0) {
1478 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1479 "Unable to load consensus directory downloaded from "
1480 "server '%s:%d'", conn->_base.address, conn->_base.port);
1481 tor_free(body); tor_free(headers); tor_free(reason);
1482 networkstatus_consensus_download_failed(0);
1483 return -1;
1485 routers_update_all_from_networkstatus(now); /*launches router downloads*/
1486 directory_info_has_arrived(now, 0);
1487 log_info(LD_DIR, "Successfully loaded consensus.");
1490 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1491 if (status_code != 200) {
1492 log_warn(LD_DIR,
1493 "Received http status code %d (%s) from server "
1494 "'%s:%d' while fetching \"/tor/keys/%s\".",
1495 status_code, escaped(reason), conn->_base.address,
1496 conn->_base.port, conn->requested_resource);
1497 connection_dir_download_cert_failed(conn, status_code);
1498 tor_free(body); tor_free(headers); tor_free(reason);
1499 return -1;
1501 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1502 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1503 if (trusted_dirs_load_certs_from_string(body, 0)<0) {
1504 log_warn(LD_DIR, "Unable to parse fetched certificates");
1505 connection_dir_download_cert_failed(conn, status_code);
1506 } else {
1507 directory_info_has_arrived(now, 0);
1508 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1511 if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1512 const char *msg;
1513 int st;
1514 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1515 (int) body_len, conn->_base.address, conn->_base.port);
1516 if (status_code != 200) {
1517 log_warn(LD_DIR,
1518 "Received http status code %d (%s) from server "
1519 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1520 status_code, escaped(reason), conn->_base.address,
1521 conn->_base.port, conn->requested_resource);
1522 tor_free(body); tor_free(headers); tor_free(reason);
1523 return -1;
1525 dirvote_add_vote(body, &msg, &st);
1526 if (st > 299) {
1527 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1528 } else {
1529 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1532 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1533 const char *msg = NULL;
1534 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1535 (int) body_len, conn->_base.address, conn->_base.port);
1536 if (status_code != 200) {
1537 log_warn(LD_DIR,
1538 "Received http status code %d (%s) from server "
1539 "'%s:%d' while fetching \"/tor/status-vote/consensus-signatures.z\".",
1540 status_code, escaped(reason), conn->_base.address,
1541 conn->_base.port);
1542 tor_free(body); tor_free(headers); tor_free(reason);
1543 return -1;
1545 if (dirvote_add_signatures(body, &msg)<0) {
1546 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1547 conn->_base.address, conn->_base.port, msg?msg:"???");
1551 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1552 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1553 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1554 smartlist_t *which = NULL;
1555 int n_asked_for = 0;
1556 int descriptor_digests = conn->requested_resource &&
1557 !strcmpstart(conn->requested_resource,"d/");
1558 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1559 was_ei ? "extra server info" : "server info",
1560 (int)body_len, conn->_base.address, conn->_base.port);
1561 if (was_ei)
1562 note_request(was_compressed?"dl/extra.z":"dl/extra", orig_len);
1563 else
1564 note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
1565 if (conn->requested_resource &&
1566 (!strcmpstart(conn->requested_resource,"d/") ||
1567 !strcmpstart(conn->requested_resource,"fp/"))) {
1568 which = smartlist_create();
1569 dir_split_resource_into_fingerprints(conn->requested_resource +
1570 (descriptor_digests ? 2 : 3),
1571 which, NULL, 0, 0);
1572 n_asked_for = smartlist_len(which);
1574 if (status_code != 200) {
1575 int dir_okay = status_code == 404 ||
1576 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1577 /* 404 means that it didn't have them; no big deal.
1578 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1579 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1580 "Received http status code %d (%s) from server '%s:%d' "
1581 "while fetching \"/tor/server/%s\". I'll try again soon.",
1582 status_code, escaped(reason), conn->_base.address,
1583 conn->_base.port, conn->requested_resource);
1584 if (!which) {
1585 connection_dir_download_routerdesc_failed(conn);
1586 } else {
1587 dir_routerdesc_download_failed(which, status_code,
1588 conn->router_purpose,
1589 was_ei, descriptor_digests);
1590 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1591 smartlist_free(which);
1593 tor_free(body); tor_free(headers); tor_free(reason);
1594 return dir_okay ? 0 : -1;
1596 /* Learn the routers, assuming we requested by fingerprint or "all"
1597 * or "authority".
1599 * We use "authority" to fetch our own descriptor for
1600 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1601 * the output of "authority" requests unless we are using bridges,
1602 * since otherwise they'll be the response from reachability tests,
1603 * and we don't really want to add that to our routerlist. */
1604 if (which || (conn->requested_resource &&
1605 (!strcmpstart(conn->requested_resource, "all") ||
1606 (!strcmpstart(conn->requested_resource, "authority") &&
1607 get_options()->UseBridges)))) {
1608 /* as we learn from them, we remove them from 'which' */
1609 if (was_ei) {
1610 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1611 descriptor_digests);
1612 } else {
1613 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1614 // descriptor_digests, conn->router_purpose);
1615 load_downloaded_routers(body, which, descriptor_digests,
1616 conn->router_purpose,
1617 conn->_base.address);
1618 directory_info_has_arrived(now, 0);
1621 if (which) { /* mark remaining ones as failed */
1622 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1623 n_asked_for-smartlist_len(which), n_asked_for,
1624 was_ei ? "extra-info documents" : "router descriptors",
1625 conn->_base.address, (int)conn->_base.port);
1626 if (smartlist_len(which)) {
1627 dir_routerdesc_download_failed(which, status_code,
1628 conn->router_purpose,
1629 was_ei, descriptor_digests);
1631 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1632 smartlist_free(which);
1634 if (directory_conn_is_self_reachability_test(conn))
1635 router_dirport_found_reachable();
1638 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1639 switch (status_code) {
1640 case 200: {
1641 trusted_dir_server_t *ds =
1642 router_get_trusteddirserver_by_digest(conn->identity_digest);
1643 char *rejected_hdr = http_get_header(headers,
1644 "X-Descriptor-Not-New: ");
1645 int rejected = 0;
1646 if (rejected_hdr) {
1647 if (!strcmp(rejected_hdr, "Yes")) {
1648 /* XXXX020 use this information; be sure to upload next one
1649 * sooner. */
1650 rejected = 1;
1652 tor_free(rejected_hdr);
1654 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1655 "descriptor: finished.");
1656 control_event_server_status(
1657 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1658 conn->_base.address, conn->_base.port);
1660 ds->has_accepted_serverdesc = 1;
1661 if (directories_have_accepted_server_descriptor())
1662 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1664 break;
1665 case 400:
1666 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1667 "dirserver '%s:%d'. Please correct.",
1668 escaped(reason), conn->_base.address, conn->_base.port);
1669 control_event_server_status(LOG_WARN,
1670 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1671 conn->_base.address, conn->_base.port, escaped(reason));
1672 break;
1673 default:
1674 log_warn(LD_GENERAL,
1675 "http status %d (%s) reason unexpected while uploading "
1676 "descriptor to server '%s:%d').",
1677 status_code, escaped(reason), conn->_base.address,
1678 conn->_base.port);
1679 break;
1681 /* return 0 in all cases, since we don't want to mark any
1682 * dirservers down just because they don't like us. */
1685 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
1686 switch (status_code) {
1687 case 200: {
1688 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
1689 conn->_base.address, conn->_base.port);
1691 break;
1692 case 400:
1693 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1694 "vote to dirserver '%s:%d'. Please correct.",
1695 escaped(reason), conn->_base.address, conn->_base.port);
1696 break;
1697 default:
1698 log_warn(LD_GENERAL,
1699 "http status %d (%s) reason unexpected while uploading "
1700 "vote to server '%s:%d').",
1701 status_code, escaped(reason), conn->_base.address,
1702 conn->_base.port);
1703 break;
1705 /* return 0 in all cases, since we don't want to mark any
1706 * dirservers down just because they don't like us. */
1709 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
1710 switch (status_code) {
1711 case 200: {
1712 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
1713 conn->_base.address, conn->_base.port);
1715 break;
1716 case 400:
1717 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1718 "signatures to dirserver '%s:%d'. Please correct.",
1719 escaped(reason), conn->_base.address, conn->_base.port);
1720 break;
1721 default:
1722 log_warn(LD_GENERAL,
1723 "http status %d (%s) reason unexpected while uploading "
1724 "signatures to server '%s:%d').",
1725 status_code, escaped(reason), conn->_base.address,
1726 conn->_base.port);
1727 break;
1729 /* return 0 in all cases, since we don't want to mark any
1730 * dirservers down just because they don't like us. */
1733 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1734 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1735 "(%s))",
1736 (int)body_len, status_code, escaped(reason));
1737 switch (status_code) {
1738 case 200:
1739 if (rend_cache_store(body, body_len, 0) < 0) {
1740 log_warn(LD_REND,"Failed to fetch rendezvous descriptor.");
1741 /* alice's ap_stream will notice when connection_mark_for_close
1742 * cleans it up */
1743 /*XXXX020 maybe retry quickly; timeout takes a while. */
1744 } else {
1745 /* success. notify pending connections about this. */
1746 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1747 rend_client_desc_here(conn->rend_query);
1749 break;
1750 case 404:
1751 /* not there. pending connections will be notified when
1752 * connection_mark_for_close cleans it up. */
1753 /*XXXX020 maybe retry quickly; timeout takes a while. */
1754 break;
1755 case 400:
1756 log_warn(LD_REND,
1757 "http status 400 (%s). Dirserver didn't like our "
1758 "rendezvous query?", escaped(reason));
1759 break;
1760 default:
1761 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1762 "fetching hidden service descriptor (server '%s:%d').",
1763 status_code, escaped(reason), conn->_base.address,
1764 conn->_base.port);
1765 break;
1769 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
1770 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1771 "(%s))",
1772 (int)body_len, status_code, escaped(reason));
1773 switch (status_code) {
1774 case 200:
1775 if (rend_cache_store_v2_desc_as_client(body, NULL) < 0) {
1776 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed.");
1777 /* alice's ap_stream will notice when connection_mark_for_close
1778 * cleans it up */
1779 } else {
1780 /* success. notify pending connections about this. */
1781 log_info(LD_REND, "Successfully fetched rendezvous descriptor.");
1782 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1783 rend_client_desc_here(conn->rend_query);
1785 break;
1786 case 404:
1787 /* not there. pending connections will be notified when
1788 * connection_mark_for_close cleans it up. */
1789 break;
1790 case 400:
1791 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1792 "http status 400 (%s). Dirserver didn't like our "
1793 "v2 rendezvous query?", escaped(reason));
1794 break;
1795 default:
1796 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1797 "http status %d (%s) response unexpected while "
1798 "fetching v2 hidden service descriptor (server '%s:%d').",
1799 status_code, escaped(reason), conn->_base.address,
1800 conn->_base.port);
1801 break;
1805 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
1806 conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
1807 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
1808 "(%s))",
1809 status_code, escaped(reason));
1810 switch (status_code) {
1811 case 200:
1812 log_info(LD_REND,
1813 "Uploading rendezvous descriptor: finished with status "
1814 "200 (%s)", escaped(reason));
1815 break;
1816 case 400:
1817 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1818 "'%s:%d'. Malformed rendezvous descriptor?",
1819 escaped(reason), conn->_base.address, conn->_base.port);
1820 break;
1821 default:
1822 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1823 "'%s:%d').",
1824 status_code, escaped(reason), conn->_base.address,
1825 conn->_base.port);
1826 break;
1829 tor_free(body); tor_free(headers); tor_free(reason);
1830 return 0;
1833 /** Called when a directory connection reaches EOF */
1835 connection_dir_reached_eof(dir_connection_t *conn)
1837 int retval;
1838 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
1839 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
1840 conn->_base.state);
1841 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
1842 connection_mark_for_close(TO_CONN(conn));
1843 return -1;
1846 retval = connection_dir_client_reached_eof(conn);
1847 if (retval == 0) /* success */
1848 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
1849 connection_mark_for_close(TO_CONN(conn));
1850 return retval;
1853 /** If any directory object is arriving, and it's over 10MB large, we're
1854 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1855 * ask for more than 96 router descriptors at a time.)
1857 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1859 /** Read handler for directory connections. (That's connections <em>to</em>
1860 * directory servers and connections <em>at</em> directory servers.)
1863 connection_dir_process_inbuf(dir_connection_t *conn)
1865 tor_assert(conn);
1866 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1868 /* Directory clients write, then read data until they receive EOF;
1869 * directory servers read data until they get an HTTP command, then
1870 * write their response (when it's finished flushing, they mark for
1871 * close).
1874 /* If we're on the dirserver side, look for a command. */
1875 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1876 if (directory_handle_command(conn) < 0) {
1877 connection_mark_for_close(TO_CONN(conn));
1878 return -1;
1880 return 0;
1883 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
1884 log_warn(LD_HTTP, "Too much data received from directory connection: "
1885 "denial of service attempt, or you need to upgrade?");
1886 connection_mark_for_close(TO_CONN(conn));
1887 return -1;
1890 if (!conn->_base.inbuf_reached_eof)
1891 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1892 return 0;
1895 /** Create an http response for the client <b>conn</b> out of
1896 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1898 static void
1899 write_http_status_line(dir_connection_t *conn, int status,
1900 const char *reason_phrase)
1902 char buf[256];
1903 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1904 status, reason_phrase ? reason_phrase : "OK") < 0) {
1905 log_warn(LD_BUG,"status line too long.");
1906 return;
1908 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
1911 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1912 * with <b>type</b> as the Content-Type.
1914 * If <b>length</b> is nonnegative, it is the Content-Length.
1915 * If <b>encoding</b> is provided, it is the Content-Encoding.
1916 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1917 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1918 static void
1919 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
1920 const char *type, const char *encoding,
1921 const char *extra_headers,
1922 int cache_lifetime)
1924 char date[RFC1123_TIME_LEN+1];
1925 char tmp[1024];
1926 char *cp;
1927 time_t now = time(NULL);
1929 tor_assert(conn);
1931 format_rfc1123_time(date, now);
1932 cp = tmp;
1933 tor_snprintf(cp, sizeof(tmp),
1934 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
1935 date);
1936 cp += strlen(tmp);
1937 if (type) {
1938 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
1939 cp += strlen(cp);
1941 if (!is_internal_IP(conn->_base.addr, 0)) {
1942 /* Don't report the source address for a localhost/private connection. */
1943 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1944 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
1945 cp += strlen(cp);
1947 if (encoding) {
1948 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1949 "Content-Encoding: %s\r\n", encoding);
1950 cp += strlen(cp);
1952 if (length >= 0) {
1953 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1954 "Content-Length: %ld\r\n", (long)length);
1955 cp += strlen(cp);
1957 if (cache_lifetime > 0) {
1958 char expbuf[RFC1123_TIME_LEN+1];
1959 format_rfc1123_time(expbuf, now + cache_lifetime);
1960 /* We could say 'Cache-control: max-age=%d' here if we start doing
1961 * http/1.1 */
1962 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1963 "Expires: %s\r\n", expbuf);
1964 cp += strlen(cp);
1965 } else if (cache_lifetime == 0) {
1966 /* We could say 'Cache-control: no-cache' here if we start doing
1967 * http/1.1 */
1968 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
1969 cp += strlen(cp);
1971 if (extra_headers)
1972 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
1973 if (sizeof(tmp)-(cp-tmp) > 3)
1974 memcpy(cp, "\r\n", 3);
1975 else
1976 tor_assert(0);
1977 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
1980 /** As write_http_response_header_impl, but sets encoding and content-typed
1981 * based on whether the response will be <b>deflated</b> or not. */
1982 static void
1983 write_http_response_header(dir_connection_t *conn, ssize_t length,
1984 int deflated, int cache_lifetime)
1986 write_http_response_header_impl(conn, length,
1987 deflated?"application/octet-stream":"text/plain",
1988 deflated?"deflate":"identity",
1989 NULL,
1990 cache_lifetime);
1993 /** Helper function: return 1 if there are any dir conns of purpose
1994 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1995 * Else return 0.
1997 static int
1998 already_fetching_directory(int purpose)
2000 smartlist_t *conns = get_connection_array();
2001 SMARTLIST_FOREACH(conns, connection_t *, conn,
2003 if (conn->type == CONN_TYPE_DIR &&
2004 conn->purpose == purpose &&
2005 !conn->marked_for_close &&
2006 !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
2007 return 1;
2009 return 0;
2012 #ifdef INSTRUMENT_DOWNLOADS
2013 /** Map used to keep track of how much data we've up/downloaded in what kind
2014 * of request. Maps from request type to pointer to uint64_t. */
2015 static strmap_t *request_bytes_map = NULL;
2017 /** Called when we just transmitted or received <b>bytes</b> worth of data
2018 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2019 * <b>bytes</b> to the total associated with key. */
2020 static void
2021 note_request(const char *key, size_t bytes)
2023 uint64_t *n;
2024 if (!request_bytes_map)
2025 request_bytes_map = strmap_new();
2027 n = strmap_get(request_bytes_map, key);
2028 if (!n) {
2029 n = tor_malloc_zero(sizeof(uint64_t));
2030 strmap_set(request_bytes_map, key, n);
2032 *n += bytes;
2035 /** Return a newly allocated string holding a summary of bytes used per
2036 * request type. */
2037 char *
2038 directory_dump_request_log(void)
2040 smartlist_t *lines;
2041 char tmp[256];
2042 char *result;
2043 strmap_iter_t *iter;
2045 if (!request_bytes_map)
2046 request_bytes_map = strmap_new();
2048 lines = smartlist_create();
2050 for (iter = strmap_iter_init(request_bytes_map);
2051 !strmap_iter_done(iter);
2052 iter = strmap_iter_next(request_bytes_map, iter)) {
2053 const char *key;
2054 void *val;
2055 uint64_t *n;
2056 strmap_iter_get(iter, &key, &val);
2057 n = val;
2058 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT"\n",
2059 key, U64_PRINTF_ARG(*n));
2060 smartlist_add(lines, tor_strdup(tmp));
2062 smartlist_sort_strings(lines);
2063 result = smartlist_join_strings(lines, "", 0, NULL);
2064 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2065 smartlist_free(lines);
2066 return result;
2068 #else
2069 static void
2070 note_request(const char *key, size_t bytes)
2072 (void)key;
2073 (void)bytes;
2076 char *
2077 directory_dump_request_log(void)
2079 return tor_strdup("Not supported.");
2081 #endif
2083 /** Helper function: called when a dirserver gets a complete HTTP GET
2084 * request. Look for a request for a directory or for a rendezvous
2085 * service descriptor. On finding one, write a response into
2086 * conn-\>outbuf. If the request is unrecognized, send a 400.
2087 * Always return 0. */
2088 static int
2089 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2090 const char *body, size_t body_len)
2092 size_t dlen;
2093 char *url, *url_mem, *header;
2094 or_options_t *options = get_options();
2095 time_t if_modified_since = 0;
2096 int deflated = 0;
2097 size_t url_len;
2099 /* We ignore the body of a GET request. */
2100 (void)body;
2101 (void)body_len;
2103 log_debug(LD_DIRSERV,"Received GET command.");
2105 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2107 if (parse_http_url(headers, &url) < 0) {
2108 write_http_status_line(conn, 400, "Bad request");
2109 return 0;
2111 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2112 struct tm tm;
2113 if (parse_http_time(header, &tm) == 0) {
2114 if_modified_since = tor_timegm(&tm);
2116 /* The correct behavior on a malformed If-Modified-Since header is to
2117 * act as if no If-Modified-Since header had been given. */
2118 tor_free(header);
2120 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2122 url_mem = url;
2123 url_len = strlen(url);
2124 deflated = url_len > 2 && !strcmp(url+url_len-2, ".z");
2125 if (deflated) {
2126 url[url_len-2] = '\0';
2127 url_len -= 2;
2130 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* dir fetch */
2131 cached_dir_t *d = dirserv_get_directory();
2133 if (!d) {
2134 log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
2135 "don't have a good one yet. Sending 503 Dir not available.");
2136 write_http_status_line(conn, 503, "Directory unavailable");
2137 /* try to get a new one now */
2138 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR) &&
2139 !should_delay_dir_fetches(options))
2140 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR,
2141 ROUTER_PURPOSE_GENERAL, NULL, 1);
2142 goto done;
2144 if (d->published < if_modified_since) {
2145 write_http_status_line(conn, 304, "Not modified");
2146 goto done;
2149 dlen = deflated ? d->dir_z_len : d->dir_len;
2151 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2152 log_info(LD_DIRSERV,
2153 "Client asked for the mirrored directory, but we've been "
2154 "writing too many bytes lately. Sending 503 Dir busy.");
2155 write_http_status_line(conn, 503, "Directory busy, try again later");
2156 goto done;
2159 note_request(url, dlen);
2161 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
2162 deflated?"deflated ":"");
2163 write_http_response_header(conn, dlen, deflated,
2164 FULL_DIR_CACHE_LIFETIME);
2165 conn->cached_dir = d;
2166 conn->cached_dir_offset = 0;
2167 if (! deflated)
2168 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2169 ++d->refcnt;
2171 /* Prime the connection with some data. */
2172 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
2173 connection_dirserv_flushed_some(conn);
2174 goto done;
2177 if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
2178 cached_dir_t *d = dirserv_get_runningrouters();
2179 if (!d) {
2180 write_http_status_line(conn, 503, "Directory unavailable");
2181 /* try to get a new one now */
2182 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST) &&
2183 !should_delay_dir_fetches(options))
2184 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST,
2185 ROUTER_PURPOSE_GENERAL, NULL, 1);
2186 goto done;
2188 if (d->published < if_modified_since) {
2189 write_http_status_line(conn, 304, "Not modified");
2190 goto done;
2192 dlen = deflated ? d->dir_z_len : d->dir_len;
2194 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2195 log_info(LD_DIRSERV,
2196 "Client asked for running-routers, but we've been "
2197 "writing too many bytes lately. Sending 503 Dir busy.");
2198 write_http_status_line(conn, 503, "Directory busy, try again later");
2199 goto done;
2201 note_request(url, dlen);
2202 write_http_response_header(conn, dlen, deflated,
2203 RUNNINGROUTERS_CACHE_LIFETIME);
2204 connection_write_to_buf(deflated ? d->dir_z : d->dir, dlen, TO_CONN(conn));
2205 goto done;
2208 if (!strcmpstart(url,"/tor/status/")
2209 || !strcmp(url, "/tor/status-vote/current/consensus")) {
2210 /* v2 or v3 network status fetch. */
2211 smartlist_t *dir_fps = smartlist_create();
2212 int is_v3 = !strcmpstart(url, "/tor/status-vote");
2213 const char *request_type = NULL;
2214 const char *key = url + strlen("/tor/status/");
2215 int lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2216 if (!is_v3) {
2217 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
2218 if (!strcmpstart(key, "fp/"))
2219 request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
2220 else if (!strcmpstart(key, "authority"))
2221 request_type = deflated?"/tor/status/authority.z":
2222 "/tor/status/authority";
2223 else if (!strcmpstart(key, "all"))
2224 request_type = deflated?"/tor/status/all.z":"/tor/status/all";
2225 else
2226 request_type = "/tor/status/?";
2227 } else {
2228 networkstatus_vote_t *v = networkstatus_get_latest_consensus();
2229 time_t now = time(NULL);
2230 smartlist_add(dir_fps, tor_memdup("\0\0\0\0\0\0\0\0\0\0"
2231 "\0\0\0\0\0\0\0\0\0\0", 20));
2232 request_type = deflated?"v3.z":"v3";
2233 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2236 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2237 write_http_status_line(conn, 503, "Network status object unavailable");
2238 smartlist_free(dir_fps);
2239 goto done;
2242 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2243 write_http_status_line(conn, 404, "Not found");
2244 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2245 smartlist_free(dir_fps);
2246 goto done;
2247 } else if (!smartlist_len(dir_fps)) {
2248 write_http_status_line(conn, 304, "Not modified");
2249 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2250 smartlist_free(dir_fps);
2251 goto done;
2254 dlen = dirserv_estimate_data_size(dir_fps, 0, deflated);
2255 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2256 log_info(LD_DIRSERV,
2257 "Client asked for network status lists, but we've been "
2258 "writing too many bytes lately. Sending 503 Dir busy.");
2259 write_http_status_line(conn, 503, "Directory busy, try again later");
2260 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2261 smartlist_free(dir_fps);
2262 goto done;
2265 // note_request(request_type,dlen);
2266 (void) request_type;
2267 write_http_response_header(conn, -1, deflated,
2268 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2269 conn->fingerprint_stack = dir_fps;
2270 if (! deflated)
2271 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2273 /* Prime the connection with some data. */
2274 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2275 connection_dirserv_flushed_some(conn);
2276 goto done;
2279 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2280 !strcmpstart(url,"/tor/status-vote/next/")) {
2281 /* XXXX If-modified-since is only the implemented for the current
2282 * consensus: that's probably fine, since it's the only vote document
2283 * people fetch much.*/
2284 int current = 1;
2285 ssize_t body_len = 0;
2286 ssize_t estimated_len = 0;
2287 smartlist_t *items = smartlist_create();
2288 smartlist_t *dir_items = smartlist_create();
2289 int lifetime = 60; /* XXXX020 should actually use vote intervals. */
2290 url += strlen("/tor/status-vote/");
2291 current = !strcmpstart(url, "current/");
2292 url = strchr(url, '/');
2293 tor_assert(url);
2294 ++url;
2295 if (!strcmp(url, "consensus")) {
2296 const char *item;
2297 tor_assert(!current); /* we handle current consensus specially above,
2298 * since it wants to be spooled. */
2299 if ((item = dirvote_get_pending_consensus()))
2300 smartlist_add(items, (char*)item);
2301 } else if (!current && !strcmp(url, "consensus-signatures")) {
2302 /* XXXX020 the spec says that we should implement
2303 * currrent/consensus-signatures too. Why? */
2304 const char *item;
2305 if ((item=dirvote_get_pending_detached_signatures()))
2306 smartlist_add(items, (char*)item);
2307 } else if (!strcmp(url, "authority")) {
2308 const cached_dir_t *d;
2309 int flags = DGV_BY_ID |
2310 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2311 if ((d=dirvote_get_vote(NULL, flags)))
2312 smartlist_add(dir_items, (cached_dir_t*)d);
2313 } else {
2314 const cached_dir_t *d;
2315 smartlist_t *fps = smartlist_create();
2316 int flags;
2317 if (!strcmpstart(url, "d/")) {
2318 url += 2;
2319 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2320 } else {
2321 flags = DGV_BY_ID |
2322 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2324 dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1);
2325 SMARTLIST_FOREACH(fps, char *, fp, {
2326 if ((d = dirvote_get_vote(fp, flags)))
2327 smartlist_add(dir_items, (cached_dir_t*)d);
2328 tor_free(fp);
2330 smartlist_free(fps);
2332 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2333 write_http_status_line(conn, 404, "Not found");
2334 goto vote_done;
2336 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2337 body_len += deflated ? d->dir_z_len : d->dir_len);
2338 estimated_len += body_len;
2339 SMARTLIST_FOREACH(items, const char *, item, {
2340 size_t ln = strlen(item);
2341 if (deflated) {
2342 body_len += ln; estimated_len += ln;
2343 } else {
2344 estimated_len += ln/2;
2348 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 1)) {
2349 write_http_status_line(conn, 503, "Directory busy, try again later.");
2350 goto vote_done;
2352 write_http_response_header(conn, body_len ? body_len : -1, deflated,
2353 lifetime);
2355 if (smartlist_len(items)) {
2356 if (deflated) {
2357 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2358 SMARTLIST_FOREACH(items, const char *, c,
2359 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2360 connection_write_to_buf_zlib("", 0, conn, 1);
2361 } else {
2362 SMARTLIST_FOREACH(items, const char *, c,
2363 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2365 } else {
2366 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2367 connection_write_to_buf(deflated ? d->dir_z : d->dir,
2368 deflated ? d->dir_z_len : d->dir_len,
2369 TO_CONN(conn)));
2371 vote_done:
2372 smartlist_free(items);
2373 smartlist_free(dir_items);
2374 goto done;
2377 if (!strcmpstart(url,"/tor/server/") ||
2378 !strcmpstart(url,"/tor/extra/")) {
2379 int res;
2380 const char *msg;
2381 const char *request_type = NULL;
2382 int cache_lifetime = 0;
2383 int is_extra = !strcmpstart(url,"/tor/extra/");
2384 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2385 conn->fingerprint_stack = smartlist_create();
2386 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2387 &msg);
2389 if (!strcmpstart(url, "fp/")) {
2390 request_type = deflated?"/tor/server/fp.z":"/tor/server/fp";
2391 if (smartlist_len(conn->fingerprint_stack) == 1)
2392 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2393 } else if (!strcmpstart(url, "authority")) {
2394 request_type = deflated?"/tor/server/authority.z":
2395 "/tor/server/authority";
2396 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2397 } else if (!strcmpstart(url, "all")) {
2398 request_type = deflated?"/tor/server/all.z":"/tor/server/all";
2399 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2400 } else if (!strcmpstart(url, "d/")) {
2401 request_type = deflated?"/tor/server/d.z":"/tor/server/d";
2402 if (smartlist_len(conn->fingerprint_stack) == 1)
2403 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2404 } else {
2405 request_type = "/tor/server/?";
2407 (void) request_type; /* usable for note_request. */
2408 if (!strcmpstart(url, "d/"))
2409 conn->dir_spool_src =
2410 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2411 else
2412 conn->dir_spool_src =
2413 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2415 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2416 conn->dir_spool_src)) {
2417 res = -1;
2418 msg = "Not found";
2421 if (res < 0)
2422 write_http_status_line(conn, 404, msg);
2423 else {
2424 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2425 1, deflated);
2426 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2427 log_info(LD_DIRSERV,
2428 "Client asked for server descriptors, but we've been "
2429 "writing too many bytes lately. Sending 503 Dir busy.");
2430 write_http_status_line(conn, 503, "Directory busy, try again later");
2431 goto done;
2433 write_http_response_header(conn, -1, deflated, cache_lifetime);
2434 if (deflated)
2435 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2436 /* Prime the connection with some data. */
2437 connection_dirserv_flushed_some(conn);
2439 goto done;
2442 if (!strcmpstart(url,"/tor/keys/")) {
2443 smartlist_t *certs = smartlist_create();
2444 ssize_t len = -1;
2445 if (!strcmp(url, "/tor/keys/all")) {
2446 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
2447 trusted_dir_server_t *, ds,
2449 if (!ds->v3_certs)
2450 continue;
2451 SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
2452 smartlist_add(certs, cert));
2454 } else if (!strcmp(url, "/tor/keys/authority")) {
2455 authority_cert_t *cert = get_my_v3_authority_cert();
2456 if (cert)
2457 smartlist_add(certs, cert);
2458 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
2459 smartlist_t *fps = smartlist_create();
2460 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
2461 fps, NULL, 1, 1);
2462 SMARTLIST_FOREACH(fps, char *, d, {
2463 authority_cert_t *c = authority_cert_get_newest_by_id(d);
2464 if (c) smartlist_add(certs, c);
2465 tor_free(d);
2467 smartlist_free(fps);
2468 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
2469 smartlist_t *fps = smartlist_create();
2470 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
2471 fps, NULL, 1, 1);
2472 SMARTLIST_FOREACH(fps, char *, d, {
2473 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
2474 if (c) smartlist_add(certs, c);
2475 tor_free(d);
2477 smartlist_free(fps);
2478 } else {
2479 write_http_status_line(conn, 400, "Bad request");
2480 goto keys_done;
2482 if (!smartlist_len(certs)) {
2483 write_http_status_line(conn, 404, "Not found");
2484 goto keys_done;
2486 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2487 if (c->cache_info.published_on < if_modified_since)
2488 SMARTLIST_DEL_CURRENT(certs, c));
2489 if (!smartlist_len(certs)) {
2490 write_http_status_line(conn, 304, "Not modified");
2491 goto keys_done;
2493 len = 0;
2494 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2495 len += c->cache_info.signed_descriptor_len);
2497 if (global_write_bucket_low(TO_CONN(conn), deflated?len/2:len, 1)) {
2498 write_http_status_line(conn, 503, "Directory busy, try again later.");
2499 goto keys_done;
2502 write_http_response_header(conn, deflated?-1:len, deflated, 60*60);
2503 if (deflated) {
2504 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2505 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2506 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
2507 c->cache_info.signed_descriptor_len,
2508 conn, 0));
2509 connection_write_to_buf_zlib("", 0, conn, 1);
2510 } else {
2511 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2512 connection_write_to_buf(c->cache_info.signed_descriptor_body,
2513 c->cache_info.signed_descriptor_len,
2514 TO_CONN(conn)));
2516 keys_done:
2517 smartlist_free(certs);
2518 goto done;
2521 if (options->HidServDirectoryV2 &&
2522 !strcmpstart(url,"/tor/rendezvous2/")) {
2523 /* Handle v2 rendezvous descriptor fetch request. */
2524 const char *descp;
2525 const char *query = url + strlen("/tor/rendezvous2/");
2526 if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) {
2527 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
2528 query);
2529 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
2530 case 1: /* valid */
2531 write_http_response_header(conn, strlen(descp), 0, 0);
2532 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
2533 break;
2534 case 0: /* well-formed but not present */
2535 write_http_status_line(conn, 404, "Not found");
2536 break;
2537 case -1: /* not well-formed */
2538 write_http_status_line(conn, 400, "Bad request");
2539 break;
2541 } else { /* not well-formed */
2542 write_http_status_line(conn, 400, "Bad request");
2544 goto done;
2547 if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) {
2548 /* rendezvous descriptor fetch */
2549 const char *descp;
2550 size_t desc_len;
2551 const char *query = url+strlen("/tor/rendezvous/");
2553 log_info(LD_REND, "Handling rendezvous descriptor get");
2554 switch (rend_cache_lookup_desc(query, 0, &descp, &desc_len)) {
2555 case 1: /* valid */
2556 write_http_response_header_impl(conn, desc_len,
2557 "application/octet-stream",
2558 NULL, NULL, 0);
2559 note_request("/tor/rendezvous?/", desc_len);
2560 /* need to send descp separately, because it may include nuls */
2561 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
2562 /* report successful fetch to statistic */
2563 if (options->HSAuthorityRecordStats) {
2564 hs_usage_note_fetch_total(query, time(NULL));
2565 hs_usage_note_fetch_successful(query, time(NULL));
2567 break;
2568 case 0: /* well-formed but not present */
2569 write_http_status_line(conn, 404, "Not found");
2570 /* report (unsuccessful) fetch to statistic */
2571 if (options->HSAuthorityRecordStats) {
2572 hs_usage_note_fetch_total(query, time(NULL));
2574 break;
2575 case -1: /* not well-formed */
2576 write_http_status_line(conn, 400, "Bad request");
2577 break;
2579 goto done;
2582 if (!strcmpstart(url,"/tor/bytes.txt")) {
2583 char *bytes = directory_dump_request_log();
2584 size_t len = strlen(bytes);
2585 write_http_response_header(conn, len, 0, 0);
2586 connection_write_to_buf(bytes, len, TO_CONN(conn));
2587 tor_free(bytes);
2588 goto done;
2591 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
2592 rewritten to /tor/robots.txt */
2593 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
2594 size_t len = strlen(robots);
2595 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
2596 connection_write_to_buf(robots, len, TO_CONN(conn));
2597 goto done;
2600 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
2601 #define ADD_MALLINFO_LINE(x) do { \
2602 tor_snprintf(tmp, sizeof(tmp), "%s %d\n", #x, mi.x); \
2603 smartlist_add(lines, tor_strdup(tmp)); \
2604 }while(0);
2606 if (!strcmp(url,"/tor/mallinfo.txt") &&
2607 (conn->_base.addr == 0x7f000001ul)) {
2608 char *result;
2609 size_t len;
2610 struct mallinfo mi;
2611 smartlist_t *lines;
2612 char tmp[256];
2614 memset(&mi, 0, sizeof(mi));
2615 mi = mallinfo();
2616 lines = smartlist_create();
2618 ADD_MALLINFO_LINE(arena)
2619 ADD_MALLINFO_LINE(ordblks)
2620 ADD_MALLINFO_LINE(smblks)
2621 ADD_MALLINFO_LINE(hblks)
2622 ADD_MALLINFO_LINE(hblkhd)
2623 ADD_MALLINFO_LINE(usmblks)
2624 ADD_MALLINFO_LINE(fsmblks)
2625 ADD_MALLINFO_LINE(uordblks)
2626 ADD_MALLINFO_LINE(fordblks)
2627 ADD_MALLINFO_LINE(keepcost)
2629 result = smartlist_join_strings(lines, "", 0, NULL);
2630 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2631 smartlist_free(lines);
2633 len = strlen(result);
2634 write_http_response_header(conn, len, 0, 0);
2635 connection_write_to_buf(result, len, TO_CONN(conn));
2636 tor_free(result);
2637 goto done;
2639 #endif
2641 /* we didn't recognize the url */
2642 write_http_status_line(conn, 404, "Not found");
2644 done:
2645 tor_free(url_mem);
2646 return 0;
2649 /** Helper function: called when a dirserver gets a complete HTTP POST
2650 * request. Look for an uploaded server descriptor or rendezvous
2651 * service descriptor. On finding one, process it and write a
2652 * response into conn-\>outbuf. If the request is unrecognized, send a
2653 * 400. Always return 0. */
2654 static int
2655 directory_handle_command_post(dir_connection_t *conn, const char *headers,
2656 const char *body, size_t body_len)
2658 char *url = NULL;
2659 or_options_t *options = get_options();
2661 log_debug(LD_DIRSERV,"Received POST command.");
2663 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2665 if (parse_http_url(headers, &url) < 0) {
2666 write_http_status_line(conn, 400, "Bad request");
2667 return 0;
2669 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2671 /* Handle v2 rendezvous service publish request. */
2672 if (options->HidServDirectoryV2 &&
2673 !strcmpstart(url,"/tor/rendezvous2/publish")) {
2674 if (rend_cache_store_v2_desc_as_dir(body) < 0) {
2675 log_warn(LD_REND, "Rejected rend descriptor (length %d) from %s.",
2676 (int)body_len, conn->_base.address);
2677 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
2678 log_info(LD_REND, "Handled v2 rendezvous descriptor post: rejected");
2679 } else {
2680 write_http_status_line(conn, 200, "Service descriptor stored");
2681 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
2683 goto done;
2686 if (!authdir_mode(options)) {
2687 /* we just provide cached directories; we don't want to
2688 * receive anything. */
2689 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
2690 "accept posted server descriptors");
2691 return 0;
2694 if (authdir_mode_handles_descs(options) &&
2695 !strcmp(url,"/tor/")) { /* server descriptor post */
2696 const char *msg = NULL;
2697 uint8_t purpose = authdir_mode_bridge(options) ?
2698 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
2699 int r = dirserv_add_multiple_descriptors(body, purpose,
2700 conn->_base.address, &msg);
2701 tor_assert(msg);
2702 if (r > 0)
2703 dirserv_get_directory(); /* rebuild and write to disk */
2704 switch (r) {
2705 case -2:
2706 case -1:
2707 case 1:
2708 log_notice(LD_DIRSERV,
2709 "Rejected router descriptor or extra-info from %s.",
2710 conn->_base.address);
2711 /* malformed descriptor, or something wrong */
2712 write_http_status_line(conn, 400, msg);
2713 break;
2714 case 0: /* accepted but discarded */
2715 write_http_response_header_impl(conn, -1, NULL, NULL,
2716 "X-Descriptor-Not-New: Yes\r\n", -1);
2717 break;
2718 case 2: /* accepted */
2719 write_http_status_line(conn, 200, msg);
2720 break;
2722 goto done;
2725 if (options->HSAuthoritativeDir &&
2726 !strcmpstart(url,"/tor/rendezvous/publish")) {
2727 /* rendezvous descriptor post */
2728 log_info(LD_REND, "Handling rendezvous descriptor post.");
2729 if (rend_cache_store(body, body_len, 1) < 0) {
2730 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
2731 "Rejected rend descriptor (length %d) from %s.",
2732 (int)body_len, conn->_base.address);
2733 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
2734 } else {
2735 write_http_status_line(conn, 200, "Service descriptor stored");
2737 goto done;
2740 if (authdir_mode_v3(options) &&
2741 !strcmp(url,"/tor/post/vote")) { /* server descriptor post */
2742 const char *msg = "OK";
2743 int status;
2744 if (dirvote_add_vote(body, &msg, &status)) {
2745 write_http_status_line(conn, status, "Vote stored");
2746 } else {
2747 tor_assert(msg);
2748 write_http_status_line(conn, status, msg);
2750 goto done;
2753 if (authdir_mode_v3(options) &&
2754 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
2755 const char *msg = NULL;
2756 if (dirvote_add_signatures(body, &msg)>=0) {
2757 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
2758 } else {
2759 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
2760 conn->_base.address, msg?msg:"???");
2761 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
2763 goto done;
2766 /* we didn't recognize the url */
2767 write_http_status_line(conn, 404, "Not found");
2769 done:
2770 tor_free(url);
2771 return 0;
2774 /** Called when a dirserver receives data on a directory connection;
2775 * looks for an HTTP request. If the request is complete, remove it
2776 * from the inbuf, try to process it; otherwise, leave it on the
2777 * buffer. Return a 0 on success, or -1 on error.
2779 static int
2780 directory_handle_command(dir_connection_t *conn)
2782 char *headers=NULL, *body=NULL;
2783 size_t body_len=0;
2784 int r;
2786 tor_assert(conn);
2787 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2789 switch (fetch_from_buf_http(conn->_base.inbuf,
2790 &headers, MAX_HEADERS_SIZE,
2791 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
2792 case -1: /* overflow */
2793 log_warn(LD_DIRSERV,
2794 "Invalid input from address '%s'. Closing.",
2795 conn->_base.address);
2796 return -1;
2797 case 0:
2798 log_debug(LD_DIRSERV,"command not all here yet.");
2799 return 0;
2800 /* case 1, fall through */
2803 http_set_address_origin(headers, TO_CONN(conn));
2804 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
2806 if (!strncasecmp(headers,"GET",3))
2807 r = directory_handle_command_get(conn, headers, body, body_len);
2808 else if (!strncasecmp(headers,"POST",4))
2809 r = directory_handle_command_post(conn, headers, body, body_len);
2810 else {
2811 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
2812 "Got headers %s with unknown command. Closing.",
2813 escaped(headers));
2814 r = -1;
2817 tor_free(headers); tor_free(body);
2818 return r;
2821 /** Write handler for directory connections; called when all data has
2822 * been flushed. Close the connection or wait for a response as
2823 * appropriate.
2826 connection_dir_finished_flushing(dir_connection_t *conn)
2828 tor_assert(conn);
2829 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2831 switch (conn->_base.state) {
2832 case DIR_CONN_STATE_CLIENT_SENDING:
2833 log_debug(LD_DIR,"client finished sending command.");
2834 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
2835 connection_stop_writing(TO_CONN(conn));
2836 return 0;
2837 case DIR_CONN_STATE_SERVER_WRITING:
2838 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
2839 connection_mark_for_close(TO_CONN(conn));
2840 return 0;
2841 default:
2842 log_warn(LD_BUG,"called in unexpected state %d.",
2843 conn->_base.state);
2844 tor_fragile_assert();
2845 return -1;
2847 return 0;
2850 /** Connected handler for directory connections: begin sending data to the
2851 * server */
2853 connection_dir_finished_connecting(dir_connection_t *conn)
2855 tor_assert(conn);
2856 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2857 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
2859 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
2860 conn->_base.address,conn->_base.port);
2862 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
2863 return 0;
2866 /** Called when one or more networkstatus fetches have failed (with uppercase
2867 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
2868 * failed once, unless they failed with status code 503. */
2869 static void
2870 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
2872 if (status_code == 503)
2873 return;
2874 SMARTLIST_FOREACH(failed, const char *, fp,
2876 char digest[DIGEST_LEN];
2877 trusted_dir_server_t *dir;
2878 base16_decode(digest, DIGEST_LEN, fp, strlen(fp));
2879 dir = router_get_trusteddirserver_by_digest(digest);
2881 if (dir)
2882 download_status_failed(&dir->v2_ns_dl_status, status_code);
2886 static const int server_dl_schedule[] = {
2887 0, 0, 0, 60, 60, 60*2, 60*5, 60*15, INT_MAX
2889 static const int client_dl_schedule[] = {
2890 0, 0, 60, 60*5, 60*10, INT_MAX
2892 static const int server_consensus_dl_schedule[] = {
2893 0, 0, 60, 60*5, 60*10, 60*30, 60*30, 60*30, 60*30, 60*30, 60*60, 60*60*2
2895 static const int client_consensus_dl_schedule[] = {
2896 0, 0, 60, 60*5, 60*10, 60*30, 60*60, 60*60, 60*60, 60*60*3, 60*60*6, 60*60*12
2899 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
2900 * <b>status_code</b>. Increment the failure count (if the code indicates a
2901 * real failure) and set <b>dls<b>->next_attempt_at to an appropriate time in
2902 * the future. */
2903 time_t
2904 download_status_increment_failure(download_status_t *dls, int status_code,
2905 const char *item, int server, time_t now)
2907 const int *schedule;
2908 int schedule_len;
2909 int increment;
2910 tor_assert(dls);
2911 if (status_code != 503 || server)
2912 ++dls->n_download_failures;
2914 switch (dls->schedule) {
2915 case DL_SCHED_GENERIC:
2916 if (server) {
2917 schedule = server_dl_schedule;
2918 schedule_len = sizeof(server_dl_schedule)/sizeof(int);
2919 } else {
2920 schedule = client_dl_schedule;
2921 schedule_len = sizeof(client_dl_schedule)/sizeof(int);
2923 break;
2924 case DL_SCHED_CONSENSUS:
2925 if (server) {
2926 schedule = server_consensus_dl_schedule;
2927 schedule_len = sizeof(server_consensus_dl_schedule)/sizeof(int);
2928 } else {
2929 schedule = client_consensus_dl_schedule;
2930 schedule_len = sizeof(client_consensus_dl_schedule)/sizeof(int);
2932 break;
2933 default:
2934 tor_assert(0);
2937 if (dls->n_download_failures < schedule_len)
2938 increment = schedule[dls->n_download_failures];
2939 else
2940 increment = schedule[schedule_len-1];
2942 if (increment < INT_MAX)
2943 dls->next_attempt_at = now+increment;
2944 else
2945 dls->next_attempt_at = TIME_MAX;
2947 if (item) {
2948 if (dls->next_attempt_at == 0)
2949 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
2950 item, (int)dls->n_download_failures);
2951 else if (dls->next_attempt_at < TIME_MAX)
2952 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
2953 item, (int)dls->n_download_failures,
2954 (int)(dls->next_attempt_at-now));
2955 else
2956 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
2957 item, (int)dls->n_download_failures);
2959 return dls->next_attempt_at;
2962 /** Reset <b>dls</b> so that it will be considered downloadable
2963 * immediately. */
2964 void
2965 download_status_reset(download_status_t *dls)
2967 dls->n_download_failures = 0;
2968 dls->next_attempt_at = 0;
2971 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
2972 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
2973 * either as descriptor digests or as identity digests based on
2974 * <b>was_descriptor_digests</b>).
2976 static void
2977 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
2978 int router_purpose,
2979 int was_extrainfo, int was_descriptor_digests)
2981 char digest[DIGEST_LEN];
2982 time_t now = time(NULL);
2983 or_options_t *options = get_options();
2984 int server = server_mode(options) && dirserver_mode(options);
2985 if (!was_descriptor_digests) {
2986 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
2987 tor_assert(!was_extrainfo); /* not supported yet */
2988 SMARTLIST_FOREACH(failed, const char *, cp,
2990 base16_decode(digest, DIGEST_LEN, cp, strlen(cp));
2991 retry_bridge_descriptor_fetch_directly(digest);
2994 return; /* FFFF should implement for other-than-router-purpose someday */
2996 SMARTLIST_FOREACH(failed, const char *, cp,
2998 download_status_t *dls = NULL;
2999 base16_decode(digest, DIGEST_LEN, cp, strlen(cp));
3000 if (was_extrainfo) {
3001 signed_descriptor_t *sd =
3002 router_get_by_extrainfo_digest(digest);
3003 if (sd)
3004 dls = &sd->ei_dl_status;
3005 } else {
3006 dls = router_get_dl_status_by_descriptor_digest(digest);
3008 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
3009 continue;
3010 download_status_increment_failure(dls, status_code, cp, server, now);
3013 /* No need to relaunch descriptor downloads here: we already do it
3014 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3017 /** Given a directory <b>resource</b> request, containing zero
3018 * or more strings separated by plus signs, followed optionally by ".z", store
3019 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3020 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
3021 * decode_hex is true, then delete all elements that aren't hex digests, and
3022 * decode the rest. If sort_uniq is true, then sort the list and remove
3023 * all duplicates.
3026 dir_split_resource_into_fingerprints(const char *resource,
3027 smartlist_t *fp_out, int *compressed_out,
3028 int decode_hex, int sort_uniq)
3030 smartlist_t *fp_tmp = smartlist_create();
3031 tor_assert(fp_out);
3032 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
3033 if (compressed_out)
3034 *compressed_out = 0;
3035 if (smartlist_len(fp_tmp)) {
3036 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3037 size_t last_len = strlen(last);
3038 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3039 last[last_len-2] = '\0';
3040 if (compressed_out)
3041 *compressed_out = 1;
3044 if (decode_hex) {
3045 int i;
3046 char *cp, *d = NULL;
3047 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3048 cp = smartlist_get(fp_tmp, i);
3049 if (strlen(cp) != HEX_DIGEST_LEN) {
3050 log_info(LD_DIR,
3051 "Skipping digest %s with non-standard length.", escaped(cp));
3052 smartlist_del_keeporder(fp_tmp, i--);
3053 goto again;
3055 d = tor_malloc_zero(DIGEST_LEN);
3056 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
3057 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3058 smartlist_del_keeporder(fp_tmp, i--);
3059 goto again;
3061 smartlist_set(fp_tmp, i, d);
3062 d = NULL;
3063 again:
3064 tor_free(cp);
3065 tor_free(d);
3068 if (sort_uniq) {
3069 smartlist_t *fp_tmp2 = smartlist_create();
3070 int i;
3071 if (decode_hex)
3072 smartlist_sort_digests(fp_tmp);
3073 else
3074 smartlist_sort_strings(fp_tmp);
3075 if (smartlist_len(fp_tmp))
3076 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
3077 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
3078 char *cp = smartlist_get(fp_tmp, i);
3079 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
3081 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
3082 || (!decode_hex && strcasecmp(cp, last)))
3083 smartlist_add(fp_tmp2, cp);
3084 else
3085 tor_free(cp);
3087 smartlist_free(fp_tmp);
3088 fp_tmp = fp_tmp2;
3090 smartlist_add_all(fp_out, fp_tmp);
3091 smartlist_free(fp_tmp);
3092 return 0;
3095 /** Determine the responsible hidden service directories for
3096 * <b>desc_ids</b> and upload the appropriate descriptor from
3097 * <b>desc_strs</b> to them; each smartlist must contain
3098 * REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS entries; <b>service_id</b> and
3099 * <b>seconds_valid</b> are only passed for logging purposes.*/
3100 /* XXXX020 desc_ids and desc_strs could be merged. Should they? */
3101 /* I guess they should. -KL */
3102 void
3103 directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *desc_strs,
3104 const char *service_id, int seconds_valid)
3106 int i, j;
3107 smartlist_t *responsible_dirs;
3108 routerstatus_t *hs_dir;
3109 if (smartlist_len(desc_ids) != REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS ||
3110 smartlist_len(desc_strs) != REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS) {
3111 log_warn(LD_BUG, "Could not post descriptors to hidden service "
3112 "directories: Illegal number of descriptor "
3113 "IDs/strings");
3114 return;
3116 responsible_dirs = smartlist_create();
3117 for (i = 0; i < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) {
3118 const char *desc_id = smartlist_get(desc_ids, i);
3119 const char *desc_str = smartlist_get(desc_strs, i);
3120 /* Determine responsible dirs. */
3121 if (hid_serv_get_responsible_directories(responsible_dirs, desc_id) < 0) {
3122 log_warn(LD_REND, "Could not determine the responsible hidden service "
3123 "directories to post descriptors to.");
3124 smartlist_free(responsible_dirs);
3125 return;
3127 tor_assert(smartlist_len(responsible_dirs) ==
3128 REND_NUMBER_OF_CONSECUTIVE_REPLICAS);
3129 for (j = 0; j < REND_NUMBER_OF_CONSECUTIVE_REPLICAS; j++) {
3130 char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
3131 hs_dir = smartlist_get(responsible_dirs, j);
3132 /* Send publish request. */
3133 directory_initiate_command_routerstatus(hs_dir,
3134 DIR_PURPOSE_UPLOAD_RENDDESC_V2,
3135 ROUTER_PURPOSE_GENERAL,
3136 1, NULL, desc_str,
3137 strlen(desc_str), 0);
3138 base32_encode(desc_id_base32, sizeof(desc_id_base32),
3139 desc_id, DIGEST_LEN);
3140 log_info(LD_REND, "Sending publish request for v2 descriptor for "
3141 "service '%s' with descriptor ID '%s' with validity "
3142 "of %d seconds to hidden service directory '%s' on "
3143 "port %d.",
3144 service_id,
3145 desc_id_base32,
3146 seconds_valid,
3147 hs_dir->nickname,
3148 hs_dir->dir_port);
3150 smartlist_clear(responsible_dirs);
3152 smartlist_free(responsible_dirs);
3155 /** Determine the responsible hidden service directories for <b>desc_id</b>
3156 * and fetch the descriptor belonging to this ID from one of them;
3157 * <b>query</b> is only passed for pretty log statements. */
3158 void
3159 directory_get_from_hs_dir(const char *desc_id, const char *query)
3161 smartlist_t *responsible_dirs = smartlist_create();
3162 routerstatus_t *hs_dir;
3163 char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
3164 tor_assert(desc_id);
3165 tor_assert(query);
3166 tor_assert(strlen(query) == REND_SERVICE_ID_LEN);
3167 /* Determine responsible dirs. */
3168 if (hid_serv_get_responsible_directories(responsible_dirs, desc_id) < 0) {
3169 /* XXX020 make this louder once we have some v2hidservs */
3170 log_info(LD_REND, "Could not determine the responsible hidden service "
3171 "directories to fetch descriptors.");
3172 smartlist_free(responsible_dirs);
3173 return;
3175 hs_dir = smartlist_choose(responsible_dirs);
3176 smartlist_free(responsible_dirs);
3177 if (!hs_dir) {
3178 log_warn(LD_BUG, "Could not pick one of the responsible hidden service "
3179 "directories to fetch descriptors.");
3180 return;
3182 /* XXXX020 if hsdir fails, use another one... */
3183 base32_encode(desc_id_base32, sizeof(desc_id_base32),
3184 desc_id, DIGEST_LEN);
3185 /* Send fetch request. */
3186 directory_initiate_command_routerstatus(hs_dir,
3187 DIR_PURPOSE_FETCH_RENDDESC_V2,
3188 ROUTER_PURPOSE_GENERAL,
3189 1, desc_id_base32, NULL, 0, 0);
3190 log_info(LD_REND, "Sending fetch request for v2 descriptor for "
3191 "service '%s' with descriptor ID '%s' to hidden "
3192 "service directory '%s' on port %d.",
3193 query, desc_id_base32, hs_dir->nickname, hs_dir->dir_port);