more building blocks towards being able to fetch bridge descriptors
[tor.git] / src / or / directory.c
blob8689e38dfecdcd6e6946aed3fc8aed4d9755dcc5
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"
10 /**
11 * \file directory.c
12 * \brief Code to send and fetch directories and router
13 * descriptors via HTTP. Directories use dirserv.c to generate the
14 * results; clients use routers.c to parse them.
15 **/
17 /* In-points to directory.c:
19 * - directory_post_to_dirservers(), called from
20 * router_upload_dir_desc_to_dirservers() in router.c
21 * upload_service_descriptor() in rendservice.c
22 * - directory_get_from_dirserver(), called from
23 * rend_client_refetch_renddesc() in rendclient.c
24 * run_scheduled_events() in main.c
25 * do_hup() in main.c
26 * - connection_dir_process_inbuf(), called from
27 * connection_process_inbuf() in connection.c
28 * - connection_dir_finished_flushing(), called from
29 * connection_finished_flushing() in connection.c
30 * - connection_dir_finished_connecting(), called from
31 * connection_finished_connecting() in connection.c
33 static void
34 directory_send_command(dir_connection_t *conn,
35 int purpose, int direct, const char *resource,
36 const char *payload, size_t payload_len);
37 static int directory_handle_command(dir_connection_t *conn);
38 static int body_is_plausible(const char *body, size_t body_len, int purpose);
39 static int purpose_needs_anonymity(uint8_t purpose);
40 static char *http_get_header(const char *headers, const char *which);
41 static void http_set_address_origin(const char *headers, connection_t *conn);
42 static void connection_dir_download_networkstatus_failed(
43 dir_connection_t *conn, int status_code);
44 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
45 static void dir_networkstatus_download_failed(smartlist_t *failed,
46 int status_code);
47 static void dir_routerdesc_download_failed(smartlist_t *failed,
48 int status_code,
49 int was_extrainfo);
50 static void note_request(const char *key, size_t bytes);
52 /********* START VARIABLES **********/
54 /** How far in the future do we allow a directory server to tell us it is
55 * before deciding that one of us has the wrong time? */
56 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
58 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
60 /** HTTP cache control: how long do we tell proxies they can cache each
61 * kind of document we serve? */
62 #define FULL_DIR_CACHE_LIFETIME (60*60)
63 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
64 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
65 #define ROUTERDESC_CACHE_LIFETIME (30*60)
66 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
67 #define ROBOTS_CACHE_LIFETIME (24*60*60)
69 /********* END VARIABLES ************/
71 /** Return true iff the directory purpose 'purpose' must use an
72 * anonymous connection to a directory. */
73 static int
74 purpose_needs_anonymity(uint8_t purpose)
76 if (get_options()->AllDirActionsPrivate)
77 return 1;
78 if (purpose == DIR_PURPOSE_FETCH_DIR ||
79 purpose == DIR_PURPOSE_UPLOAD_DIR ||
80 purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
81 purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
82 purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
83 purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
84 return 0;
85 return 1;
88 /** Return a newly allocated string describing <b>auth</b>. */
89 char *
90 authority_type_to_string(authority_type_t auth)
92 char *result;
93 smartlist_t *lst = smartlist_create();
94 if (auth & V1_AUTHORITY)
95 smartlist_add(lst, (void*)"V1");
96 if (auth & V2_AUTHORITY)
97 smartlist_add(lst, (void*)"V2");
98 if (auth & BRIDGE_AUTHORITY)
99 smartlist_add(lst, (void*)"Bridge");
100 if (auth & HIDSERV_AUTHORITY)
101 smartlist_add(lst, (void*)"Hidden service");
102 if (smartlist_len(lst)) {
103 result = smartlist_join_strings(lst, ", ", 0, NULL);
104 } else {
105 result = tor_strdup("[Not an authority]");
107 smartlist_free(lst);
108 return result;
111 /** Return true iff <b>identity_digest</b> is the digest of a router we
112 * believe to support extrainfo downloads. (If <b>is_authority</b> we do
113 * additional checking that's only valid for authorities.) */
115 router_supports_extrainfo(const char *identity_digest, int is_authority)
117 routerinfo_t *ri = router_get_by_digest(identity_digest);
118 local_routerstatus_t *lrs;
120 if (ri) {
121 if (ri->caches_extra_info)
122 return 1;
123 if (is_authority && ri->platform &&
124 tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
125 return 1;
127 if (is_authority) {
128 lrs = router_get_combined_status_by_digest(identity_digest);
129 if (lrs && lrs->status.version_supports_extrainfo_upload)
130 return 1;
132 return 0;
135 /** Start a connection to every suitable directory authority, using
136 * connection purpose 'purpose' and uploading the payload 'payload'
137 * (length 'payload_len'). The purpose should be one of
138 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
140 * <b>type</b> specifies what sort of dir authorities (V1, V2,
141 * HIDSERV, BRIDGE) we should upload to.
143 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
144 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
145 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
146 * to all authorities, and the extra-info document to all authorities that
147 * support it.
149 void
150 directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
151 const char *payload,
152 size_t payload_len, size_t extrainfo_len)
154 int post_via_tor;
155 smartlist_t *dirservers = router_get_trusted_dir_servers();
156 int found = 0;
157 tor_assert(dirservers);
158 /* This tries dirservers which we believe to be down, but ultimately, that's
159 * harmless, and we may as well err on the side of getting things uploaded.
161 SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
163 routerstatus_t *rs = &(ds->fake_status.status);
164 size_t upload_len = payload_len;
166 if ((type & ds->type) == 0)
167 continue;
169 found = 1; /* at least one authority of this type was listed */
170 if (purpose == DIR_PURPOSE_UPLOAD_DIR)
171 ds->has_accepted_serverdesc = 0;
173 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
174 upload_len += extrainfo_len;
175 log_info(LD_DIR, "Uploading an extrainfo (length %d)",
176 (int) extrainfo_len);
178 post_via_tor = purpose_needs_anonymity(purpose) ||
179 !fascist_firewall_allows_address_dir(ds->addr, ds->dir_port);
180 directory_initiate_command_routerstatus(rs, purpose,
181 ROUTER_PURPOSE_GENERAL,
182 post_via_tor,
183 NULL, payload, upload_len);
185 if (!found) {
186 char *s = authority_type_to_string(type);
187 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
188 "of type '%s', but no authorities of that type listed!", s);
189 tor_free(s);
193 /** Start a connection to a random running directory server, using
194 * connection purpose 'purpose' and requesting 'resource'.
195 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
196 * down, mark them up and try again.
198 void
199 directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
200 int retry_if_no_servers)
202 routerstatus_t *rs = NULL;
203 or_options_t *options = get_options();
204 int prefer_authority = server_mode(options) && options->DirPort != 0;
205 int directconn = !purpose_needs_anonymity(dir_purpose);
206 authority_type_t type;
208 /* FFFF we could break this switch into its own function, and call
209 * it elsewhere in directory.c. -RD */
210 switch (dir_purpose) {
211 case DIR_PURPOSE_FETCH_EXTRAINFO:
212 type = EXTRAINFO_CACHE | V2_AUTHORITY;
213 break;
214 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
215 case DIR_PURPOSE_FETCH_SERVERDESC:
216 type = V2_AUTHORITY;
217 break;
218 case DIR_PURPOSE_FETCH_DIR:
219 case DIR_PURPOSE_FETCH_RUNNING_LIST:
220 type = V1_AUTHORITY;
221 break;
222 case DIR_PURPOSE_FETCH_RENDDESC:
223 type = HIDSERV_AUTHORITY;
224 break;
225 default:
226 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
227 return;
230 if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
231 return;
233 if (directconn) {
234 if (prefer_authority) {
235 /* only ask authdirservers, and don't ask myself */
236 rs = router_pick_trusteddirserver(type, 1, 1,
237 retry_if_no_servers);
239 if (!rs) {
240 /* anybody with a non-zero dirport will do */
241 rs = router_pick_directory_server(1, 1, type,
242 retry_if_no_servers);
243 if (!rs) {
244 const char *which;
245 if (dir_purpose == DIR_PURPOSE_FETCH_DIR)
246 which = "directory";
247 else if (dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST)
248 which = "status list";
249 else if (dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
250 which = "network status";
251 else // if (dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
252 which = "server descriptors";
253 log_info(LD_DIR,
254 "No router found for %s; falling back to dirserver list",
255 which);
256 rs = router_pick_trusteddirserver(type, 1, 1,
257 retry_if_no_servers);
258 if (!rs)
259 directconn = 0; /* last resort: try routing it via Tor */
263 if (!directconn) {
264 /* Never use fascistfirewall; we're going via Tor. */
265 if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
266 /* only ask hidserv authorities, any of them will do */
267 rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, 0, 0,
268 retry_if_no_servers);
269 } else {
270 /* anybody with a non-zero dirport will do. Disregard firewalls. */
271 rs = router_pick_directory_server(1, 0, type,
272 retry_if_no_servers);
273 /* If we have any hope of building an indirect conn, we know some router
274 * descriptors. If (rs==NULL), we can't build circuits anyway, so
275 * there's no point in falling back to the authorities in this case. */
279 if (rs)
280 directory_initiate_command_routerstatus(rs, dir_purpose,
281 ROUTER_PURPOSE_GENERAL,
282 !directconn,
283 resource, NULL, 0);
284 else {
285 log_notice(LD_DIR,
286 "While fetching directory info, "
287 "no running dirservers known. Will try again later. "
288 "(purpose %d)", dir_purpose);
289 if (!purpose_needs_anonymity(dir_purpose)) {
290 /* remember we tried them all and failed. */
291 directory_all_unreachable(time(NULL));
296 /** Launch a new connection to the directory server <b>status</b> to
297 * upload or download a server or rendezvous
298 * descriptor. <b>dir_purpose</b> determines what
299 * kind of directory connection we're launching, and must be one of
300 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}. <b>router_purpose</b>
301 * specifies the descriptor purposes we have in mind (currently only
302 * used for FETCH_DIR).
304 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
305 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
307 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
308 * want to fetch.
310 void
311 directory_initiate_command_routerstatus(routerstatus_t *status,
312 uint8_t dir_purpose,
313 uint8_t router_purpose,
314 int anonymized_connection,
315 const char *resource,
316 const char *payload,
317 size_t payload_len)
319 routerinfo_t *router;
320 char address_buf[INET_NTOA_BUF_LEN+1];
321 struct in_addr in;
322 const char *address;
323 if ((router = router_get_by_digest(status->identity_digest))) {
324 address = router->address;
325 } else {
326 in.s_addr = htonl(status->addr);
327 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
328 address = address_buf;
330 directory_initiate_command(address, status->addr,
331 status->or_port, status->dir_port,
332 status->version_supports_begindir,
333 status->identity_digest,
334 dir_purpose, router_purpose,
335 anonymized_connection, resource,
336 payload, payload_len);
339 /** Return true iff <b>conn</b> is the client side of a directory connection
340 * we launched to ourself in order to determine the reachability of our
341 * dir_port. */
342 static int
343 directory_conn_is_self_reachability_test(dir_connection_t *conn)
345 if (conn->requested_resource &&
346 !strcmpstart(conn->requested_resource,"authority")) {
347 routerinfo_t *me = router_get_my_routerinfo();
348 if (me &&
349 router_digest_is_me(conn->identity_digest) &&
350 me->addr == conn->_base.addr &&
351 me->dir_port == conn->_base.port)
352 return 1;
354 return 0;
357 /** Called when we are unable to complete the client's request to a directory
358 * server due to a network error: Mark the router as down and try again if
359 * possible.
361 void
362 connection_dir_request_failed(dir_connection_t *conn)
364 if (directory_conn_is_self_reachability_test(conn)) {
365 routerinfo_t *me = router_get_my_routerinfo();
366 if (me)
367 control_event_server_status(LOG_WARN,
368 "REACHABILITY_FAILED DIRADDRESS=%s:%d",
369 me->address, me->dir_port);
370 return; /* this was a test fetch. don't retry. */
372 router_set_status(conn->identity_digest, 0); /* don't try him again */
373 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR ||
374 conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
375 log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
376 conn->_base.address, conn->_base.port);
377 directory_get_from_dirserver(conn->_base.purpose, NULL,
378 0 /* don't retry_if_no_servers */);
379 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
380 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
381 conn->_base.address);
382 connection_dir_download_networkstatus_failed(conn, -1);
383 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
384 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
385 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
386 conn->_base.address);
387 connection_dir_download_routerdesc_failed(conn);
391 /** Called when an attempt to download one or more network status
392 * documents on connection <b>conn</b> failed. Decide whether to
393 * retry the fetch now, later, or never.
395 static void
396 connection_dir_download_networkstatus_failed(dir_connection_t *conn,
397 int status_code)
399 if (!conn->requested_resource) {
400 /* We never reached directory_send_command, which means that we never
401 * opened a network connection. Either we're out of sockets, or the
402 * network is down. Either way, retrying would be pointless. */
403 return;
405 if (!strcmpstart(conn->requested_resource, "all")) {
406 /* We're a non-authoritative directory cache; try again. Ignore status
407 * code, since we don't want to keep trying forever in a tight loop
408 * if all the authorities are shutting us out. */
409 smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
410 SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
411 ++ds->n_networkstatus_failures);
412 directory_get_from_dirserver(conn->_base.purpose, "all.z",
413 0 /* don't retry_if_no_servers */);
414 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
415 /* We were trying to download by fingerprint; mark them all as having
416 * failed, and possibly retry them later.*/
417 smartlist_t *failed = smartlist_create();
418 dir_split_resource_into_fingerprints(conn->requested_resource+3,
419 failed, NULL, 0, 0);
420 if (smartlist_len(failed)) {
421 dir_networkstatus_download_failed(failed, status_code);
422 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
424 smartlist_free(failed);
428 /** Called when an attempt to download one or more router descriptors
429 * or extra-info documents on connection <b>conn</b> failed.
431 static void
432 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
434 /* No need to increment the failure count for routerdescs, since
435 * it's not their fault. */
437 /* No need to relaunch descriptor downloads here: we already do it
438 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
439 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
440 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
442 (void) conn;
445 /** Helper for directory_initiate_command_(router|trusted_dir): send the
446 * command to a server whose address is <b>address</b>, whose IP is
447 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
448 * <b>supports_begindir</b>, and whose identity key digest is
449 * <b>digest</b>. */
450 void
451 directory_initiate_command(const char *address, uint32_t addr,
452 uint16_t or_port, uint16_t dir_port,
453 int supports_begindir, const char *digest,
454 uint8_t dir_purpose, uint8_t router_purpose,
455 int anonymized_connection, const char *resource,
456 const char *payload, size_t payload_len)
458 dir_connection_t *conn;
459 or_options_t *options = get_options();
460 int want_to_tunnel = options->TunnelDirConns && supports_begindir &&
461 !anonymized_connection && or_port &&
462 fascist_firewall_allows_address_or(addr, or_port);
464 tor_assert(address);
465 tor_assert(addr);
466 tor_assert(dir_port);
467 tor_assert(digest);
469 log_debug(LD_DIR, "anonymized %d, want_to_tunnel %d.",
470 anonymized_connection, want_to_tunnel);
472 switch (dir_purpose) {
473 case DIR_PURPOSE_FETCH_DIR:
474 log_debug(LD_DIR,"initiating directory fetch");
475 break;
476 case DIR_PURPOSE_FETCH_RENDDESC:
477 log_debug(LD_DIR,"initiating hidden-service descriptor fetch");
478 break;
479 case DIR_PURPOSE_UPLOAD_DIR:
480 log_debug(LD_OR,"initiating server descriptor upload");
481 break;
482 case DIR_PURPOSE_UPLOAD_RENDDESC:
483 log_debug(LD_REND,"initiating hidden-service descriptor upload");
484 break;
485 case DIR_PURPOSE_FETCH_RUNNING_LIST:
486 log_debug(LD_DIR,"initiating running-routers fetch");
487 break;
488 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
489 log_debug(LD_DIR,"initiating network-status fetch");
490 break;
491 case DIR_PURPOSE_FETCH_SERVERDESC:
492 log_debug(LD_DIR,"initiating server descriptor fetch");
493 break;
494 case DIR_PURPOSE_FETCH_EXTRAINFO:
495 log_debug(LD_DIR,"initiating extra-info fetch");
496 break;
497 default:
498 log_err(LD_BUG, "Unrecognized directory connection purpose.");
499 tor_assert(0);
502 conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
504 /* set up conn so it's got all the data we need to remember */
505 conn->_base.addr = addr;
506 conn->_base.port = want_to_tunnel ? or_port : dir_port;
507 conn->_base.address = tor_strdup(address);
508 memcpy(conn->identity_digest, digest, DIGEST_LEN);
510 conn->_base.purpose = dir_purpose;
511 conn->router_purpose = router_purpose;
513 /* give it an initial state */
514 conn->_base.state = DIR_CONN_STATE_CONNECTING;
516 if (!anonymized_connection && !want_to_tunnel) {
517 /* then we want to connect directly */
519 conn->dirconn_direct = 1;
520 if (options->HttpProxy) {
521 addr = options->HttpProxyAddr;
522 dir_port = options->HttpProxyPort;
525 switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
526 dir_port)) {
527 case -1:
528 connection_dir_request_failed(conn); /* retry if we want */
529 connection_free(TO_CONN(conn));
530 return;
531 case 1:
532 /* start flushing conn */
533 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
534 /* fall through */
535 case 0:
536 /* queue the command on the outbuf */
537 directory_send_command(conn, dir_purpose, 1, resource,
538 payload, payload_len);
539 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
540 /* writable indicates finish, readable indicates broken link,
541 error indicates broken link in windowsland. */
543 } else { /* we want to connect via tor */
544 edge_connection_t *linked_conn;
545 /* make an AP connection
546 * populate it and add it at the right state
547 * hook up both sides
549 conn->dirconn_direct = 0;
550 linked_conn =
551 connection_ap_make_link(conn->_base.address, conn->_base.port,
552 digest,
553 anonymized_connection ?
554 SOCKS_COMMAND_CONNECT :
555 SOCKS_COMMAND_CONNECT_DIR);
556 if (!linked_conn) {
557 log_warn(LD_NET,"Making tunnel to dirserver failed.");
558 connection_mark_for_close(TO_CONN(conn));
559 return;
561 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
563 if (connection_add(TO_CONN(conn)) < 0) {
564 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
565 connection_mark_for_close(TO_CONN(conn));
566 return;
568 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
569 /* queue the command on the outbuf */
570 directory_send_command(conn, dir_purpose, 0, resource,
571 payload, payload_len);
572 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
573 connection_start_reading(TO_CONN(linked_conn));
577 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
578 * are as in directory_initiate_command.
580 static void
581 directory_send_command(dir_connection_t *conn,
582 int purpose, int direct, const char *resource,
583 const char *payload, size_t payload_len)
585 char proxystring[256];
586 char proxyauthstring[256];
587 char hoststring[128];
588 char *url;
589 char request[8192];
590 const char *httpcommand = NULL;
591 size_t len;
593 tor_assert(conn);
594 tor_assert(conn->_base.type == CONN_TYPE_DIR);
596 tor_free(conn->requested_resource);
597 if (resource)
598 conn->requested_resource = tor_strdup(resource);
600 /* come up with a string for which Host: we want */
601 if (conn->_base.port == 80) {
602 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
603 } else {
604 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
605 conn->_base.address, conn->_base.port);
608 /* come up with some proxy lines, if we're using one. */
609 if (direct && get_options()->HttpProxy) {
610 char *base64_authenticator=NULL;
611 const char *authenticator = get_options()->HttpProxyAuthenticator;
613 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
614 if (authenticator) {
615 base64_authenticator = alloc_http_authenticator(authenticator);
616 if (!base64_authenticator)
617 log_warn(LD_BUG, "Encoding http authenticator failed");
619 if (base64_authenticator) {
620 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
621 "\r\nProxy-Authorization: Basic %s",
622 base64_authenticator);
623 tor_free(base64_authenticator);
624 } else {
625 proxyauthstring[0] = 0;
627 } else {
628 proxystring[0] = 0;
629 proxyauthstring[0] = 0;
632 switch (purpose) {
633 case DIR_PURPOSE_FETCH_DIR:
634 tor_assert(!resource);
635 tor_assert(!payload);
636 httpcommand = "GET";
637 url = tor_strdup("/tor/dir.z");
638 break;
639 case DIR_PURPOSE_FETCH_RUNNING_LIST:
640 tor_assert(!resource);
641 tor_assert(!payload);
642 httpcommand = "GET";
643 url = tor_strdup("/tor/running-routers");
644 break;
645 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
646 httpcommand = "GET";
647 len = strlen(resource)+32;
648 url = tor_malloc(len);
649 tor_snprintf(url, len, "/tor/status/%s", resource);
650 break;
651 case DIR_PURPOSE_FETCH_SERVERDESC:
652 httpcommand = "GET";
653 len = strlen(resource)+32;
654 url = tor_malloc(len);
655 tor_snprintf(url, len, "/tor/server/%s", resource);
656 break;
657 case DIR_PURPOSE_FETCH_EXTRAINFO:
658 httpcommand = "GET";
659 len = strlen(resource)+32;
660 url = tor_malloc(len);
661 tor_snprintf(url, len, "/tor/extra/%s", resource);
662 break;
663 case DIR_PURPOSE_UPLOAD_DIR:
664 tor_assert(!resource);
665 tor_assert(payload);
666 httpcommand = "POST";
667 url = tor_strdup("/tor/");
668 break;
669 case DIR_PURPOSE_FETCH_RENDDESC:
670 tor_assert(resource);
671 tor_assert(!payload);
673 /* this must be true or we wouldn't be doing the lookup */
674 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN);
675 /* This breaks the function abstraction. */
676 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
678 httpcommand = "GET";
679 /* Request the most recent versioned descriptor. */
680 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
681 // but that never got testing, and it wasn't a good design.)
682 len = strlen(resource)+32;
683 url = tor_malloc(len);
684 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
685 break;
686 case DIR_PURPOSE_UPLOAD_RENDDESC:
687 tor_assert(!resource);
688 tor_assert(payload);
689 httpcommand = "POST";
690 url = tor_strdup("/tor/rendezvous/publish");
691 break;
692 default:
693 tor_assert(0);
694 return;
697 if (strlen(proxystring) + strlen(url) >= 4096) {
698 log_warn(LD_BUG,
699 "Squid does not like URLs longer than 4095 bytes, and this "
700 "one is %d bytes long: %s%s",
701 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
704 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
705 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
706 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
707 tor_free(url);
709 if (!strcmp(httpcommand, "GET") && !payload) {
710 tor_snprintf(request, sizeof(request),
711 " HTTP/1.0\r\nHost: %s%s\r\n\r\n",
712 hoststring,
713 proxyauthstring);
714 } else {
715 tor_snprintf(request, sizeof(request),
716 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
717 payload ? (unsigned long)payload_len : 0,
718 hoststring,
719 proxyauthstring);
721 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
723 if (payload) {
724 /* then send the payload afterwards too */
725 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
729 /** Parse an HTTP request string <b>headers</b> of the form
730 * \verbatim
731 * "\%s [http[s]://]\%s HTTP/1..."
732 * \endverbatim
733 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
734 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
735 * so it does. Return 0.
736 * Otherwise, return -1.
738 static int
739 parse_http_url(const char *headers, char **url)
741 char *s, *start, *tmp;
743 s = (char *)eat_whitespace_no_nl(headers);
744 if (!*s) return -1;
745 s = (char *)find_whitespace(s); /* get past GET/POST */
746 if (!*s) return -1;
747 s = (char *)eat_whitespace_no_nl(s);
748 if (!*s) return -1;
749 start = s; /* this is it, assuming it's valid */
750 s = (char *)find_whitespace(start);
751 if (!*s) return -1;
753 /* tolerate the http[s] proxy style of putting the hostname in the url */
754 if (s-start >= 4 && !strcmpstart(start,"http")) {
755 tmp = start + 4;
756 if (*tmp == 's')
757 tmp++;
758 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
759 tmp = strchr(tmp+3, '/');
760 if (tmp && tmp < s) {
761 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
762 start = tmp;
767 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
768 *url = tor_malloc(s - start + 5);
769 strlcpy(*url,"/tor", s-start+5);
770 strlcat((*url)+4, start, s-start+1);
771 } else {
772 *url = tor_strndup(start, s-start);
774 return 0;
777 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
778 * <b>which</b>. The key should be given with a terminating colon and space;
779 * this function copies everything after, up to but not including the
780 * following \\r\\n. */
781 static char *
782 http_get_header(const char *headers, const char *which)
784 const char *cp = headers;
785 while (cp) {
786 if (!strcmpstart(cp, which)) {
787 char *eos;
788 cp += strlen(which);
789 if ((eos = strchr(cp,'\r')))
790 return tor_strndup(cp, eos-cp);
791 else
792 return tor_strdup(cp);
794 cp = strchr(cp, '\n');
795 if (cp)
796 ++cp;
798 return NULL;
801 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
802 * <b>conn</b>-\>address to describe our best guess of the address that
803 * originated this HTTP request. */
804 static void
805 http_set_address_origin(const char *headers, connection_t *conn)
807 char *fwd;
809 fwd = http_get_header(headers, "Forwarded-For: ");
810 if (!fwd)
811 fwd = http_get_header(headers, "X-Forwarded-For: ");
812 if (fwd) {
813 struct in_addr in;
814 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
815 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
816 escaped(fwd));
817 tor_free(fwd);
818 return;
820 tor_free(conn->address);
821 conn->address = tor_strdup(fwd);
822 tor_free(fwd);
826 /** Parse an HTTP response string <b>headers</b> of the form
827 * \verbatim
828 * "HTTP/1.\%d \%d\%s\r\n...".
829 * \endverbatim
831 * If it's well-formed, assign the status code to *<b>code</b> and
832 * return 0. Otherwise, return -1.
834 * On success: If <b>date</b> is provided, set *date to the Date
835 * header in the http headers, or 0 if no such header is found. If
836 * <b>compression</b> is provided, set *<b>compression</b> to the
837 * compression method given in the Content-Encoding header, or 0 if no
838 * such header is found, or -1 if the value of the header is not
839 * recognized. If <b>reason</b> is provided, strdup the reason string
840 * into it.
843 parse_http_response(const char *headers, int *code, time_t *date,
844 compress_method_t *compression, char **reason)
846 int n1, n2;
847 char datestr[RFC1123_TIME_LEN+1];
848 smartlist_t *parsed_headers;
849 tor_assert(headers);
850 tor_assert(code);
852 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
854 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
855 (n1 != 0 && n1 != 1) ||
856 (n2 < 100 || n2 >= 600)) {
857 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
858 return -1;
860 *code = n2;
862 parsed_headers = smartlist_create();
863 smartlist_split_string(parsed_headers, headers, "\n",
864 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
865 if (reason) {
866 smartlist_t *status_line_elements = smartlist_create();
867 tor_assert(smartlist_len(parsed_headers));
868 smartlist_split_string(status_line_elements,
869 smartlist_get(parsed_headers, 0),
870 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
871 tor_assert(smartlist_len(status_line_elements) <= 3);
872 if (smartlist_len(status_line_elements) == 3) {
873 *reason = smartlist_get(status_line_elements, 2);
874 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
876 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
877 smartlist_free(status_line_elements);
879 if (date) {
880 *date = 0;
881 SMARTLIST_FOREACH(parsed_headers, const char *, s,
882 if (!strcmpstart(s, "Date: ")) {
883 strlcpy(datestr, s+6, sizeof(datestr));
884 /* This will do nothing on failure, so we don't need to check
885 the result. We shouldn't warn, since there are many other valid
886 date formats besides the one we use. */
887 parse_rfc1123_time(datestr, date);
888 break;
891 if (compression) {
892 const char *enc = NULL;
893 SMARTLIST_FOREACH(parsed_headers, const char *, s,
894 if (!strcmpstart(s, "Content-Encoding: ")) {
895 enc = s+18; break;
897 if (!enc || !strcmp(enc, "identity")) {
898 *compression = NO_METHOD;
899 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
900 *compression = ZLIB_METHOD;
901 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
902 *compression = GZIP_METHOD;
903 } else {
904 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
905 escaped(enc));
906 *compression = UNKNOWN_METHOD;
909 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
910 smartlist_free(parsed_headers);
912 return 0;
915 /** Return true iff <b>body</b> doesn't start with a plausible router or
916 * running-list or directory opening. This is a sign of possible compression.
918 static int
919 body_is_plausible(const char *body, size_t len, int purpose)
921 int i;
922 if (len == 0)
923 return 1; /* empty bodies don't need decompression */
924 if (len < 32)
925 return 0;
926 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
927 if (!strcmpstart(body,"router") ||
928 !strcmpstart(body,"signed-directory") ||
929 !strcmpstart(body,"network-status") ||
930 !strcmpstart(body,"running-routers"))
931 return 1;
932 for (i=0;i<32;++i) {
933 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
934 return 0;
936 return 1;
937 } else {
938 return 1;
942 /** We are a client, and we've finished reading the server's
943 * response. Parse and it and act appropriately.
945 * If we're still happy with using this directory server in the future, return
946 * 0. Otherwise return -1; and the caller should consider trying the request
947 * again.
949 * The caller will take care of marking the connection for close.
951 static int
952 connection_dir_client_reached_eof(dir_connection_t *conn)
954 char *body;
955 char *headers;
956 char *reason = NULL;
957 size_t body_len=0, orig_len=0;
958 int status_code;
959 time_t date_header=0;
960 int delta;
961 compress_method_t compression;
962 int plausible;
963 int skewed=0;
964 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
965 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
966 int was_compressed=0;
967 time_t now = time(NULL);
969 switch (fetch_from_buf_http(conn->_base.inbuf,
970 &headers, MAX_HEADERS_SIZE,
971 &body, &body_len, MAX_DIR_DL_SIZE,
972 allow_partial)) {
973 case -1: /* overflow */
974 log_warn(LD_PROTOCOL,
975 "'fetch' response too large (server '%s:%d'). Closing.",
976 conn->_base.address, conn->_base.port);
977 return -1;
978 case 0:
979 log_info(LD_HTTP,
980 "'fetch' response not all here, but we're at eof. Closing.");
981 return -1;
982 /* case 1, fall through */
984 orig_len = body_len;
986 if (parse_http_response(headers, &status_code, &date_header,
987 &compression, &reason) < 0) {
988 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
989 conn->_base.address, conn->_base.port);
990 tor_free(body); tor_free(headers);
991 return -1;
993 if (!reason) reason = tor_strdup("[no reason given]");
995 log_debug(LD_DIR,
996 "Received response from directory server '%s:%d': %d %s",
997 conn->_base.address, conn->_base.port, status_code,
998 escaped(reason));
1000 /* now check if it's got any hints for us about our IP address. */
1001 if (conn->dirconn_direct) {
1002 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1003 if (guess) {
1004 router_new_address_suggestion(guess);
1005 tor_free(guess);
1009 if (date_header > 0) {
1010 /* The date header was written very soon after we sent our request,
1011 * so compute the skew as the difference between sending the request
1012 * and the date header. (We used to check now-date_header, but that's
1013 * inaccurate if we spend a lot of time downloading.)
1015 delta = conn->_base.timestamp_lastwritten - date_header;
1016 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1017 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1018 log_fn(trusted ? LOG_WARN : LOG_INFO,
1019 LD_HTTP,
1020 "Received directory with skewed time (server '%s:%d'): "
1021 "we are %d minutes %s, or the directory is %d minutes %s.",
1022 conn->_base.address, conn->_base.port,
1023 abs(delta)/60, delta>0 ? "ahead" : "behind",
1024 abs(delta)/60, delta>0 ? "behind" : "ahead");
1025 skewed = 1; /* don't check the recommended-versions line */
1026 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1027 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
1028 delta, conn->_base.address, conn->_base.port);
1029 } else {
1030 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1031 "we are %d seconds skewed. (That's okay.)", delta);
1034 (void) skewed; /* skewed isn't used yet. */
1036 if (status_code == 503) {
1037 local_routerstatus_t *rs;
1038 trusted_dir_server_t *ds;
1039 log_info(LD_DIR,"Received http status code %d (%s) from server "
1040 "'%s:%d'. I'll try again soon.",
1041 status_code, escaped(reason), conn->_base.address,
1042 conn->_base.port);
1043 if ((rs = router_get_combined_status_by_digest(conn->identity_digest)))
1044 rs->last_dir_503_at = now;
1045 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1046 ds->fake_status.last_dir_503_at = now;
1048 tor_free(body); tor_free(headers); tor_free(reason);
1049 return -1;
1052 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1053 if (compression != NO_METHOD || !plausible) {
1054 char *new_body = NULL;
1055 size_t new_len = 0;
1056 compress_method_t guessed = detect_compression_method(body, body_len);
1057 if (compression == UNKNOWN_METHOD || guessed != compression) {
1058 /* Tell the user if we don't believe what we're told about compression.*/
1059 const char *description1, *description2;
1060 if (compression == ZLIB_METHOD)
1061 description1 = "as deflated";
1062 else if (compression == GZIP_METHOD)
1063 description1 = "as gzipped";
1064 else if (compression == NO_METHOD)
1065 description1 = "as uncompressed";
1066 else
1067 description1 = "with an unknown Content-Encoding";
1068 if (guessed == ZLIB_METHOD)
1069 description2 = "deflated";
1070 else if (guessed == GZIP_METHOD)
1071 description2 = "gzipped";
1072 else if (!plausible)
1073 description2 = "confusing binary junk";
1074 else
1075 description2 = "uncompressed";
1077 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1078 "but it seems to be %s.%s",
1079 conn->_base.address, conn->_base.port, description1,
1080 description2,
1081 (compression>0 && guessed>0)?" Trying both.":"");
1083 /* Try declared compression first if we can. */
1084 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1085 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1086 !allow_partial, LOG_PROTOCOL_WARN);
1087 /* Okay, if that didn't work, and we think that it was compressed
1088 * differently, try that. */
1089 if (!new_body &&
1090 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1091 compression != guessed)
1092 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1093 !allow_partial, LOG_PROTOCOL_WARN);
1094 /* If we're pretty sure that we have a compressed directory, and
1095 * we didn't manage to uncompress it, then warn and bail. */
1096 if (!plausible && !new_body) {
1097 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1098 "Unable to decompress HTTP body (server '%s:%d').",
1099 conn->_base.address, conn->_base.port);
1100 tor_free(body); tor_free(headers); tor_free(reason);
1101 return -1;
1103 if (new_body) {
1104 tor_free(body);
1105 body = new_body;
1106 body_len = new_len;
1107 was_compressed = 1;
1111 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
1112 /* fetch/process the directory to cache it. */
1113 log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
1114 (int)body_len, conn->_base.address, conn->_base.port);
1115 if (status_code != 200) {
1116 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1117 "'%s:%d' while fetching directory. I'll try again soon.",
1118 status_code, escaped(reason), conn->_base.address,
1119 conn->_base.port);
1120 tor_free(body); tor_free(headers); tor_free(reason);
1121 return -1;
1123 if (router_parse_directory(body) < 0) {
1124 log_notice(LD_DIR,"I failed to parse the directory I fetched from "
1125 "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
1127 note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
1130 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
1131 /* just update our list of running routers, if this list is new info */
1132 log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
1133 if (status_code != 200) {
1134 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1135 "'%s:%d' while fetching running-routers. I'll try again soon.",
1136 status_code, escaped(reason), conn->_base.address,
1137 conn->_base.port);
1138 tor_free(body); tor_free(headers); tor_free(reason);
1139 return -1;
1141 if (router_parse_runningrouters(body)<0) {
1142 log_warn(LD_DIR,
1143 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1144 conn->_base.address, conn->_base.port);
1145 tor_free(body); tor_free(headers); tor_free(reason);
1146 return -1;
1148 note_request(was_compressed?"dl/running-routers.z":
1149 "dl/running-routers", orig_len);
1152 if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
1153 smartlist_t *which = NULL;
1154 networkstatus_source_t source;
1155 char *cp;
1156 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1157 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1158 if (status_code != 200) {
1159 /* XXXX020 This warning tends to freak out clients who get a 403. */
1160 log_warn(LD_DIR,
1161 "Received http status code %d (%s) from server "
1162 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1163 status_code, escaped(reason), conn->_base.address,
1164 conn->_base.port, conn->requested_resource);
1165 tor_free(body); tor_free(headers); tor_free(reason);
1166 connection_dir_download_networkstatus_failed(conn, status_code);
1167 return -1;
1169 note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
1170 if (conn->requested_resource &&
1171 !strcmpstart(conn->requested_resource,"fp/")) {
1172 source = NS_FROM_DIR_BY_FP;
1173 which = smartlist_create();
1174 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1175 which, NULL, 0, 0);
1176 } else if (conn->requested_resource &&
1177 !strcmpstart(conn->requested_resource, "all")) {
1178 source = NS_FROM_DIR_ALL;
1179 which = smartlist_create();
1180 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1181 trusted_dir_server_t *, ds,
1183 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1184 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1185 smartlist_add(which, hex);
1187 } else {
1188 /* Can we even end up here? -- weasel*/
1189 source = NS_FROM_DIR_BY_FP;
1190 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1191 "for it by fp, nor did we ask for all.");
1193 cp = body;
1194 while (*cp) {
1195 char *next = strstr(cp, "\nnetwork-status-version");
1196 if (next)
1197 next[1] = '\0';
1198 /* learn from it, and then remove it from 'which' */
1199 if (router_set_networkstatus(cp, now, source, which)<0)
1200 break;
1201 if (next) {
1202 next[1] = 'n';
1203 cp = next+1;
1204 } else
1205 break;
1207 routers_update_all_from_networkstatus(now); /*launches router downloads*/
1208 directory_info_has_arrived(now, 0);
1209 if (which) {
1210 if (smartlist_len(which)) {
1211 dir_networkstatus_download_failed(which, status_code);
1213 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1214 smartlist_free(which);
1218 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1219 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1220 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1221 smartlist_t *which = NULL;
1222 int n_asked_for = 0;
1223 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1224 was_ei ? "server info" : "extra server info",
1225 (int)body_len, conn->_base.address, conn->_base.port);
1226 if (was_ei)
1227 note_request(was_compressed?"dl/extra.z":"dl/extra", orig_len);
1228 else
1229 note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
1230 if (conn->requested_resource &&
1231 !strcmpstart(conn->requested_resource,"d/")) {
1232 which = smartlist_create();
1233 dir_split_resource_into_fingerprints(conn->requested_resource+2,
1234 which, NULL, 0, 0);
1235 n_asked_for = smartlist_len(which);
1237 if (status_code != 200) {
1238 int dir_okay = status_code == 404 ||
1239 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1240 /* 404 means that it didn't have them; no big deal.
1241 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1242 /* XXXX020 This warning tends to freak out clients who get a 403. */
1243 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1244 "Received http status code %d (%s) from server '%s:%d' "
1245 "while fetching \"/tor/server/%s\". I'll try again soon.",
1246 status_code, escaped(reason), conn->_base.address,
1247 conn->_base.port, conn->requested_resource);
1248 if (!which) {
1249 connection_dir_download_routerdesc_failed(conn);
1250 } else {
1251 dir_routerdesc_download_failed(which, status_code, was_ei);
1252 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1253 smartlist_free(which);
1255 tor_free(body); tor_free(headers); tor_free(reason);
1256 return dir_okay ? 0 : -1;
1258 /* Learn the routers, assuming we requested by fingerprint or "all".
1259 * Right now, we only use "authority" to fetch ourself, so we don't want
1260 * to risk replacing ourself with a router running at the addr:port we
1261 * think we have.
1263 if (which || (conn->requested_resource &&
1264 !strcmpstart(conn->requested_resource, "all"))) {
1265 /* as we learn from them, we remove them from 'which' */
1266 if (was_ei) {
1267 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which);
1268 } else {
1269 router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1270 conn->router_purpose);
1271 directory_info_has_arrived(now, 0);
1274 if (which) { /* mark remaining ones as failed */
1275 log_info(LD_DIR, "Received %d/%d routers requested from %s:%d",
1276 n_asked_for-smartlist_len(which), n_asked_for,
1277 conn->_base.address, (int)conn->_base.port);
1278 if (smartlist_len(which)) {
1279 dir_routerdesc_download_failed(which, status_code, was_ei);
1281 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1282 smartlist_free(which);
1284 if (directory_conn_is_self_reachability_test(conn))
1285 router_dirport_found_reachable();
1288 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1289 switch (status_code) {
1290 case 200: {
1291 int all_done = 1;
1292 trusted_dir_server_t *ds =
1293 router_get_trusteddirserver_by_digest(conn->identity_digest);
1294 smartlist_t *servers;
1295 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1296 "descriptor: finished.");
1297 control_event_server_status(
1298 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1299 conn->_base.address, conn->_base.port);
1301 ds->has_accepted_serverdesc = 1;
1302 servers = router_get_trusted_dir_servers();
1303 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
1304 if ((d->type & (V1_AUTHORITY|V2_AUTHORITY)) &&
1305 !d->has_accepted_serverdesc) {
1306 all_done = 0;
1307 break;
1310 if (all_done)
1311 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1313 break;
1314 case 400:
1315 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1316 "dirserver '%s:%d'. Please correct.",
1317 escaped(reason), conn->_base.address, conn->_base.port);
1318 control_event_server_status(LOG_WARN,
1319 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1320 conn->_base.address, conn->_base.port, escaped(reason));
1321 break;
1322 case 403:
1323 log_warn(LD_GENERAL,
1324 "http status 403 (%s) response from dirserver "
1325 "'%s:%d'. Is your clock skewed? Have you mailed us your key "
1326 "fingerprint? Are you using the right key? Are you using a "
1327 "private IP address? See http://tor.eff.org/doc/"
1328 "tor-doc-server.html",escaped(reason), conn->_base.address,
1329 conn->_base.port);
1330 control_event_server_status(LOG_WARN,
1331 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1332 conn->_base.address, conn->_base.port, escaped(reason));
1333 break;
1334 default:
1335 log_warn(LD_GENERAL,
1336 "http status %d (%s) reason unexpected while uploading "
1337 "descriptor to server '%s:%d').",
1338 status_code, escaped(reason), conn->_base.address,
1339 conn->_base.port);
1340 break;
1342 /* return 0 in all cases, since we don't want to mark any
1343 * dirservers down just because they don't like us. */
1346 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1347 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1348 "(%s))",
1349 (int)body_len, status_code, escaped(reason));
1350 switch (status_code) {
1351 case 200:
1352 if (rend_cache_store(body, body_len, 0) < 0) {
1353 log_warn(LD_REND,"Failed to store rendezvous descriptor.");
1354 /* alice's ap_stream will notice when connection_mark_for_close
1355 * cleans it up */
1356 } else {
1357 /* success. notify pending connections about this. */
1358 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1359 rend_client_desc_here(conn->rend_query);
1361 break;
1362 case 404:
1363 /* not there. pending connections will be notified when
1364 * connection_mark_for_close cleans it up. */
1365 break;
1366 case 400:
1367 log_warn(LD_REND,
1368 "http status 400 (%s). Dirserver didn't like our "
1369 "rendezvous query?", escaped(reason));
1370 break;
1371 default:
1372 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1373 "fetching hidden service descriptor (server '%s:%d').",
1374 status_code, escaped(reason), conn->_base.address,
1375 conn->_base.port);
1376 break;
1380 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
1381 switch (status_code) {
1382 case 200:
1383 log_info(LD_REND,
1384 "Uploading rendezvous descriptor: finished with status "
1385 "200 (%s)", escaped(reason));
1386 break;
1387 case 400:
1388 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1389 "'%s:%d'. Malformed rendezvous descriptor?",
1390 escaped(reason), conn->_base.address, conn->_base.port);
1391 break;
1392 default:
1393 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1394 "'%s:%d').",
1395 status_code, escaped(reason), conn->_base.address,
1396 conn->_base.port);
1397 break;
1400 tor_free(body); tor_free(headers); tor_free(reason);
1401 return 0;
1404 /** Called when a directory connection reaches EOF */
1406 connection_dir_reached_eof(dir_connection_t *conn)
1408 int retval;
1409 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
1410 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
1411 conn->_base.state);
1412 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
1413 connection_mark_for_close(TO_CONN(conn));
1414 return -1;
1417 retval = connection_dir_client_reached_eof(conn);
1418 if (retval == 0) /* success */
1419 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
1420 connection_mark_for_close(TO_CONN(conn));
1421 return retval;
1424 /** If any directory object is arriving, and it's over 10MB large, we're
1425 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1426 * ask for more than 96 router descriptors at a time.)
1428 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1430 /** Read handler for directory connections. (That's connections <em>to</em>
1431 * directory servers and connections <em>at</em> directory servers.)
1434 connection_dir_process_inbuf(dir_connection_t *conn)
1436 tor_assert(conn);
1437 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1439 /* Directory clients write, then read data until they receive EOF;
1440 * directory servers read data until they get an HTTP command, then
1441 * write their response (when it's finished flushing, they mark for
1442 * close).
1445 /* If we're on the dirserver side, look for a command. */
1446 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1447 if (directory_handle_command(conn) < 0) {
1448 connection_mark_for_close(TO_CONN(conn));
1449 return -1;
1451 return 0;
1454 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
1455 log_warn(LD_HTTP, "Too much data received from directory connection: "
1456 "denial of service attempt, or you need to upgrade?");
1457 connection_mark_for_close(TO_CONN(conn));
1458 return -1;
1461 if (!conn->_base.inbuf_reached_eof)
1462 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1463 return 0;
1466 /** Create an http response for the client <b>conn</b> out of
1467 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1469 static void
1470 write_http_status_line(dir_connection_t *conn, int status,
1471 const char *reason_phrase)
1473 char buf[256];
1474 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1475 status, reason_phrase ? reason_phrase : "OK") < 0) {
1476 log_warn(LD_BUG,"status line too long.");
1477 return;
1479 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
1482 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1483 * with <b>type</b> as the Content-Type.
1485 * If <b>length</b> is nonnegative, it is the Content-Length.
1486 * If <b>encoding</b> is provided, it is the Content-Encoding.
1487 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1488 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1489 static void
1490 write_http_response_header(dir_connection_t *conn, ssize_t length,
1491 const char *type, const char *encoding,
1492 int cache_lifetime)
1494 char date[RFC1123_TIME_LEN+1];
1495 char tmp[1024];
1496 char *cp;
1497 time_t now = time(NULL);
1499 tor_assert(conn);
1500 tor_assert(type);
1502 format_rfc1123_time(date, now);
1503 cp = tmp;
1504 tor_snprintf(cp, sizeof(tmp),
1505 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n",
1506 date, type);
1507 cp += strlen(tmp);
1508 if (!is_internal_IP(conn->_base.addr, 0)) {
1509 /* Don't report the source address for a localhost/private connection. */
1510 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1511 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
1512 cp += strlen(cp);
1514 if (encoding) {
1515 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1516 "Content-Encoding: %s\r\n", encoding);
1517 cp += strlen(cp);
1519 if (length >= 0) {
1520 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1521 "Content-Length: %ld\r\n", (long)length);
1522 cp += strlen(cp);
1524 if (cache_lifetime > 0) {
1525 char expbuf[RFC1123_TIME_LEN+1];
1526 format_rfc1123_time(expbuf, now + cache_lifetime);
1527 /* We could say 'Cache-control: max-age=%d' here if we start doing
1528 * http/1.1 */
1529 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1530 "Expires: %s\r\n", expbuf);
1531 cp += strlen(cp);
1532 } else {
1533 /* We could say 'Cache-control: no-cache' here if we start doing
1534 * http/1.1 */
1535 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
1536 cp += strlen(cp);
1538 if (sizeof(tmp)-(cp-tmp) > 3)
1539 memcpy(cp, "\r\n", 3);
1540 else
1541 tor_assert(0);
1542 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
1545 /** Helper function: return 1 if there are any dir conns of purpose
1546 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1547 * Else return 0.
1549 static int
1550 already_fetching_directory(int purpose)
1552 smartlist_t *conns = get_connection_array();
1553 SMARTLIST_FOREACH(conns, connection_t *, conn,
1555 if (conn->type == CONN_TYPE_DIR &&
1556 conn->purpose == purpose &&
1557 !conn->marked_for_close &&
1558 !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
1559 return 1;
1561 return 0;
1564 #undef INSTRUMENT_DOWNLOADS
1566 #ifdef INSTRUMENT_DOWNLOADS
1567 /** Map used to keep track of how much data we've up/downloaded in what kind
1568 * of request. Maps from request type to pointer to uint64_t. */
1569 static strmap_t *request_bytes_map = NULL;
1571 /** Called when we just transmitted or received <b>bytes</b> worth of data
1572 * because of a request of type <b>key</b> (an arbitrary identifier): adds
1573 * <b>bytes</b> to the total associated with key. */
1574 static void
1575 note_request(const char *key, size_t bytes)
1577 uint64_t *n;
1578 if (!request_bytes_map)
1579 request_bytes_map = strmap_new();
1581 n = strmap_get(request_bytes_map, key);
1582 if (!n) {
1583 n = tor_malloc_zero(sizeof(uint64_t));
1584 strmap_set(request_bytes_map, key, n);
1586 *n += bytes;
1589 /** Return a newly allocated string holding a summary of bytes used per
1590 * request type. */
1591 char *
1592 directory_dump_request_log(void)
1594 smartlist_t *lines;
1595 char tmp[256];
1596 char *result;
1597 strmap_iter_t *iter;
1599 if (!request_bytes_map)
1600 request_bytes_map = strmap_new();
1602 lines = smartlist_create();
1604 for (iter = strmap_iter_init(request_bytes_map);
1605 !strmap_iter_done(iter);
1606 iter = strmap_iter_next(request_bytes_map, iter)) {
1607 const char *key;
1608 void *val;
1609 uint64_t *n;
1610 strmap_iter_get(iter, &key, &val);
1611 n = val;
1612 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT"\n",
1613 key, U64_PRINTF_ARG(*n));
1614 smartlist_add(lines, tor_strdup(tmp));
1616 smartlist_sort_strings(lines);
1617 result = smartlist_join_strings(lines, "", 0, NULL);
1618 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
1619 smartlist_free(lines);
1620 return result;
1622 #else
1623 static void
1624 note_request(const char *key, size_t bytes)
1626 (void)key;
1627 (void)bytes;
1630 char *
1631 directory_dump_request_log(void)
1633 return tor_strdup("Not supported.");
1635 #endif
1637 /** Helper function: called when a dirserver gets a complete HTTP GET
1638 * request. Look for a request for a directory or for a rendezvous
1639 * service descriptor. On finding one, write a response into
1640 * conn-\>outbuf. If the request is unrecognized, send a 400.
1641 * Always return 0. */
1642 static int
1643 directory_handle_command_get(dir_connection_t *conn, const char *headers,
1644 const char *body, size_t body_len)
1646 size_t dlen;
1647 char *url = NULL;
1648 or_options_t *options = get_options();
1649 time_t if_modified_since = 0;
1650 char *header;
1652 /* We ignore the body of a GET request. */
1653 (void)body;
1654 (void)body_len;
1656 log_debug(LD_DIRSERV,"Received GET command.");
1658 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
1660 if (parse_http_url(headers, &url) < 0) {
1661 write_http_status_line(conn, 400, "Bad request");
1662 return 0;
1664 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
1665 struct tm tm;
1666 if (parse_http_time(header, &tm) == 0) {
1667 if_modified_since = tor_timegm(&tm);
1669 /* The correct behavior on a malformed If-Modified-Since header is to
1670 * act as if no If-Modified-Since header had been given. */
1671 tor_free(header);
1673 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
1675 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir.z")) { /* dir fetch */
1676 int deflated = !strcmp(url,"/tor/dir.z");
1677 cached_dir_t *d = dirserv_get_directory();
1679 if (!d) {
1680 log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
1681 "don't have a good one yet. Sending 503 Dir not available.");
1682 write_http_status_line(conn, 503, "Directory unavailable");
1683 /* try to get a new one now */
1684 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR))
1685 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1);
1686 tor_free(url);
1687 return 0;
1689 if (d->published < if_modified_since) {
1690 write_http_status_line(conn, 304, "Not modified");
1691 tor_free(url);
1692 return 0;
1695 dlen = deflated ? d->dir_z_len : d->dir_len;
1697 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
1698 log_info(LD_DIRSERV,
1699 "Client asked for the mirrored directory, but we've been "
1700 "writing too many bytes lately. Sending 503 Dir busy.");
1701 write_http_status_line(conn, 503, "Directory busy, try again later");
1702 tor_free(url);
1703 return 0;
1706 note_request(url, dlen);
1707 tor_free(url);
1709 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
1710 deflated?"deflated ":"");
1711 write_http_response_header(conn, dlen,
1712 deflated?"application/octet-stream":"text/plain",
1713 deflated?"deflate":"identity",
1714 FULL_DIR_CACHE_LIFETIME);
1715 conn->cached_dir = d;
1716 conn->cached_dir_offset = 0;
1717 if (! deflated)
1718 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
1719 ++d->refcnt;
1721 /* Prime the connection with some data. */
1722 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
1723 connection_dirserv_flushed_some(conn);
1724 return 0;
1727 if (!strcmp(url,"/tor/running-routers") ||
1728 !strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
1729 int deflated = !strcmp(url,"/tor/running-routers.z");
1730 cached_dir_t *d = dirserv_get_runningrouters();
1731 if (!d) {
1732 write_http_status_line(conn, 503, "Directory unavailable");
1733 /* try to get a new one now */
1734 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST))
1735 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
1736 tor_free(url);
1737 return 0;
1739 if (d->published < if_modified_since) {
1740 write_http_status_line(conn, 304, "Not modified");
1741 tor_free(url);
1742 return 0;
1744 dlen = deflated ? d->dir_z_len : d->dir_len;
1746 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
1747 log_info(LD_DIRSERV,
1748 "Client asked for running-routers, but we've been "
1749 "writing too many bytes lately. Sending 503 Dir busy.");
1750 write_http_status_line(conn, 503, "Directory busy, try again later");
1751 tor_free(url);
1752 return 0;
1754 note_request(url, dlen);
1755 tor_free(url);
1756 write_http_response_header(conn, dlen,
1757 deflated?"application/octet-stream":"text/plain",
1758 deflated?"deflate":"identity",
1759 RUNNINGROUTERS_CACHE_LIFETIME);
1760 connection_write_to_buf(deflated ? d->dir_z : d->dir, dlen, TO_CONN(conn));
1761 return 0;
1764 if (!strcmpstart(url,"/tor/status/")) {
1765 /* v2 network status fetch. */
1766 size_t url_len = strlen(url);
1767 int deflated = !strcmp(url+url_len-2, ".z");
1768 smartlist_t *dir_fps = smartlist_create();
1769 const char *request_type = NULL;
1770 const char *key = url + strlen("/tor/status/");
1771 if (deflated)
1772 url[url_len-2] = '\0';
1773 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
1774 if (!strcmpstart(key, "fp/"))
1775 request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
1776 else if (!strcmpstart(key, "authority"))
1777 request_type = deflated?"/tor/status/authority.z":
1778 "/tor/status/authority";
1779 else if (!strcmpstart(key, "all"))
1780 request_type = deflated?"/tor/status/all.z":"/tor/status/all";
1781 else
1782 request_type = "/tor/status/?";
1783 tor_free(url);
1784 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
1785 write_http_status_line(conn, 503, "Network status object unavailable");
1786 smartlist_free(dir_fps);
1787 return 0;
1789 if (dirserv_statuses_are_old(dir_fps, if_modified_since)) {
1790 write_http_status_line(conn, 304, "Not modified");
1791 smartlist_free(dir_fps);
1792 return 0;
1795 dlen = dirserv_estimate_data_size(dir_fps, 0, deflated);
1796 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
1797 log_info(LD_DIRSERV,
1798 "Client asked for network status lists, but we've been "
1799 "writing too many bytes lately. Sending 503 Dir busy.");
1800 write_http_status_line(conn, 503, "Directory busy, try again later");
1801 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
1802 smartlist_free(dir_fps);
1803 return 0;
1806 // note_request(request_type,dlen);
1807 (void) request_type;
1808 write_http_response_header(conn, -1,
1809 deflated?"application/octet_stream":"text/plain",
1810 deflated?"deflate":NULL,
1811 smartlist_len(dir_fps) == 1 ? NETWORKSTATUS_CACHE_LIFETIME:0);
1812 conn->fingerprint_stack = dir_fps;
1813 if (! deflated)
1814 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
1816 /* Prime the connection with some data. */
1817 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
1818 connection_dirserv_flushed_some(conn);
1820 return 0;
1823 if (!strcmpstart(url,"/tor/server/") ||
1824 !strcmpstart(url,"/tor/extra/")) {
1825 char *url_mem = url;
1826 size_t url_len = strlen(url);
1827 int deflated = !strcmp(url+url_len-2, ".z");
1828 int res;
1829 const char *msg;
1830 const char *request_type = NULL;
1831 int cache_lifetime = 0;
1832 int is_extra = !strcmpstart(url,"/tor/extra/");
1833 if (deflated)
1834 url[url_len-2] = '\0';
1835 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
1836 conn->fingerprint_stack = smartlist_create();
1837 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
1838 &msg);
1840 if (!strcmpstart(url, "fp/")) {
1841 request_type = deflated?"/tor/server/fp.z":"/tor/server/fp";
1842 if (smartlist_len(conn->fingerprint_stack) == 1)
1843 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
1844 } else if (!strcmpstart(url, "authority")) {
1845 request_type = deflated?"/tor/server/authority.z":
1846 "/tor/server/authority";
1847 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
1848 } else if (!strcmpstart(url, "all")) {
1849 request_type = deflated?"/tor/server/all.z":"/tor/server/all";
1850 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
1851 } else if (!strcmpstart(url, "d/")) {
1852 request_type = deflated?"/tor/server/d.z":"/tor/server/d";
1853 if (smartlist_len(conn->fingerprint_stack) == 1)
1854 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
1855 } else {
1856 request_type = "/tor/server/?";
1858 (void) request_type; /* usable for note_request. */
1859 if (!strcmpstart(url, "d/"))
1860 conn->dir_spool_src =
1861 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
1862 else
1863 conn->dir_spool_src =
1864 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
1865 tor_free(url_mem);
1866 if (res < 0)
1867 write_http_status_line(conn, 404, msg);
1868 else {
1869 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
1870 1, deflated);
1871 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
1872 log_info(LD_DIRSERV,
1873 "Client asked for server descriptors, but we've been "
1874 "writing too many bytes lately. Sending 503 Dir busy.");
1875 write_http_status_line(conn, 503, "Directory busy, try again later");
1876 return 0;
1878 write_http_response_header(conn, -1,
1879 deflated?"application/octet_stream":"text/plain",
1880 deflated?"deflate":NULL, cache_lifetime);
1881 if (deflated)
1882 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
1883 /* Prime the connection with some data. */
1884 connection_dirserv_flushed_some(conn);
1886 return 0;
1889 if (options->HSAuthoritativeDir &&
1890 (!strcmpstart(url,"/tor/rendezvous/") ||
1891 !strcmpstart(url,"/tor/rendezvous1/"))) {
1892 /* rendezvous descriptor fetch */
1893 const char *descp;
1894 size_t desc_len;
1895 int versioned = !strcmpstart(url,"/tor/rendezvous1/");
1896 const char *query = url+strlen("/tor/rendezvous/")+(versioned?1:0);
1898 switch (rend_cache_lookup_desc(query, versioned?-1:0, &descp, &desc_len)) {
1899 case 1: /* valid */
1900 write_http_response_header(conn, desc_len, "application/octet-stream",
1901 NULL, 0);
1902 note_request("/tor/rendezvous?/", desc_len);
1903 /* need to send descp separately, because it may include nuls */
1904 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
1905 /* report successful fetch to statistic */
1906 if (options->HSAuthorityRecordStats) {
1907 hs_usage_note_fetch_total(query, time(NULL));
1908 hs_usage_note_fetch_successful(query, time(NULL));
1910 break;
1911 case 0: /* well-formed but not present */
1912 write_http_status_line(conn, 404, "Not found");
1913 /* report (unsuccessful) fetch to statistic */
1914 if (options->HSAuthorityRecordStats) {
1915 hs_usage_note_fetch_total(query, time(NULL));
1917 break;
1918 case -1: /* not well-formed */
1919 write_http_status_line(conn, 400, "Bad request");
1920 break;
1922 tor_free(url);
1923 return 0;
1926 if (!strcmpstart(url,"/tor/bytes.txt")) {
1927 char *bytes = directory_dump_request_log();
1928 size_t len = strlen(bytes);
1929 write_http_response_header(conn, len, "text/plain", NULL, 0);
1930 connection_write_to_buf(bytes, len, TO_CONN(conn));
1931 tor_free(bytes);
1932 tor_free(url);
1933 return 0;
1936 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
1937 rewritten to /tor/robots.txt */
1938 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
1939 size_t len = strlen(robots);
1940 write_http_response_header(conn, len, "text/plain", NULL,
1941 ROBOTS_CACHE_LIFETIME);
1942 connection_write_to_buf(robots, len, TO_CONN(conn));
1943 tor_free(url);
1944 return 0;
1947 if (!strcmp(url,"/tor/dir-all-weaselhack") &&
1948 (conn->_base.addr == 0x7f000001ul) &&
1949 authdir_mode_v2(options) &&
1950 !authdir_mode_bridge(options)) {
1951 /* until weasel rewrites his scripts at noreply */
1952 char *new_directory=NULL;
1954 if (dirserv_dump_directory_to_string(&new_directory,
1955 get_identity_key(), 1)) {
1956 log_warn(LD_BUG, "Error creating full v1 directory.");
1957 tor_free(new_directory);
1958 write_http_status_line(conn, 503, "Directory unavailable");
1959 return 0;
1962 dlen = strlen(new_directory);
1964 write_http_response_header(conn, dlen, "text/plain", "identity", 0);
1966 connection_write_to_buf(new_directory, dlen, TO_CONN(conn));
1967 tor_free(new_directory);
1968 tor_free(url);
1969 return 0;
1972 /* we didn't recognize the url */
1973 write_http_status_line(conn, 404, "Not found");
1974 tor_free(url);
1975 return 0;
1978 /** Helper function: called when a dirserver gets a complete HTTP POST
1979 * request. Look for an uploaded server descriptor or rendezvous
1980 * service descriptor. On finding one, process it and write a
1981 * response into conn-\>outbuf. If the request is unrecognized, send a
1982 * 400. Always return 0. */
1983 static int
1984 directory_handle_command_post(dir_connection_t *conn, const char *headers,
1985 const char *body, size_t body_len)
1987 char *url = NULL;
1988 or_options_t *options = get_options();
1990 log_debug(LD_DIRSERV,"Received POST command.");
1992 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
1994 if (!authdir_mode(options)) {
1995 /* we just provide cached directories; we don't want to
1996 * receive anything. */
1997 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
1998 "accept posted server descriptors");
1999 return 0;
2002 if (parse_http_url(headers, &url) < 0) {
2003 write_http_status_line(conn, 400, "Bad request");
2004 return 0;
2006 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2008 if (authdir_mode_handles_descs(options) &&
2009 !strcmp(url,"/tor/")) { /* server descriptor post */
2010 const char *msg = NULL;
2011 uint8_t purpose = authdir_mode_bridge(options) ?
2012 ROUTER_PURPOSE_CONTROLLER : ROUTER_PURPOSE_GENERAL;
2013 int r = dirserv_add_multiple_descriptors(body, purpose, &msg);
2014 tor_assert(msg);
2015 if (r > 0)
2016 dirserv_get_directory(); /* rebuild and write to disk */
2017 switch (r) {
2018 case -2:
2019 case -1:
2020 case 1:
2021 log_notice(LD_DIRSERV,
2022 "Rejected router descriptor or extra-info from %s.",
2023 conn->_base.address);
2024 /* malformed descriptor, or something wrong */
2025 write_http_status_line(conn, 400, msg);
2026 break;
2027 case 0: /* accepted but discarded */
2028 case 2: /* accepted */
2029 write_http_status_line(conn, 200, msg);
2030 break;
2032 goto done;
2035 if (options->HSAuthoritativeDir &&
2036 !strcmpstart(url,"/tor/rendezvous/publish")) {
2037 /* rendezvous descriptor post */
2038 if (rend_cache_store(body, body_len, 1) < 0) {
2039 // char tmp[1024*2+1];
2040 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
2041 "Rejected rend descriptor (length %d) from %s.",
2042 (int)body_len, conn->_base.address);
2043 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
2044 } else {
2045 write_http_status_line(conn, 200, "Service descriptor stored");
2047 goto done;
2050 /* we didn't recognize the url */
2051 write_http_status_line(conn, 404, "Not found");
2053 done:
2054 tor_free(url);
2055 return 0;
2058 /** Called when a dirserver receives data on a directory connection;
2059 * looks for an HTTP request. If the request is complete, remove it
2060 * from the inbuf, try to process it; otherwise, leave it on the
2061 * buffer. Return a 0 on success, or -1 on error.
2063 static int
2064 directory_handle_command(dir_connection_t *conn)
2066 char *headers=NULL, *body=NULL;
2067 size_t body_len=0;
2068 int r;
2070 tor_assert(conn);
2071 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2073 switch (fetch_from_buf_http(conn->_base.inbuf,
2074 &headers, MAX_HEADERS_SIZE,
2075 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
2076 case -1: /* overflow */
2077 log_warn(LD_DIRSERV,
2078 "Invalid input from address '%s'. Closing.",
2079 conn->_base.address);
2080 return -1;
2081 case 0:
2082 log_debug(LD_DIRSERV,"command not all here yet.");
2083 return 0;
2084 /* case 1, fall through */
2087 http_set_address_origin(headers, TO_CONN(conn));
2088 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
2090 if (!strncasecmp(headers,"GET",3))
2091 r = directory_handle_command_get(conn, headers, body, body_len);
2092 else if (!strncasecmp(headers,"POST",4))
2093 r = directory_handle_command_post(conn, headers, body, body_len);
2094 else {
2095 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
2096 "Got headers %s with unknown command. Closing.",
2097 escaped(headers));
2098 r = -1;
2101 tor_free(headers); tor_free(body);
2102 return r;
2105 /** Write handler for directory connections; called when all data has
2106 * been flushed. Close the connection or wait for a response as
2107 * appropriate.
2110 connection_dir_finished_flushing(dir_connection_t *conn)
2112 tor_assert(conn);
2113 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2115 switch (conn->_base.state) {
2116 case DIR_CONN_STATE_CLIENT_SENDING:
2117 log_debug(LD_DIR,"client finished sending command.");
2118 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
2119 connection_stop_writing(TO_CONN(conn));
2120 return 0;
2121 case DIR_CONN_STATE_SERVER_WRITING:
2122 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
2123 connection_mark_for_close(TO_CONN(conn));
2124 return 0;
2125 default:
2126 log_warn(LD_BUG,"called in unexpected state %d.",
2127 conn->_base.state);
2128 tor_fragile_assert();
2129 return -1;
2131 return 0;
2134 /** Connected handler for directory connections: begin sending data to the
2135 * server */
2137 connection_dir_finished_connecting(dir_connection_t *conn)
2139 tor_assert(conn);
2140 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2141 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
2143 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
2144 conn->_base.address,conn->_base.port);
2146 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
2147 return 0;
2150 /** Called when one or more networkstatus fetches have failed (with uppercase
2151 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
2152 * failed once, unless they failed with status code 503. */
2153 static void
2154 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
2156 if (status_code == 503)
2157 return;
2158 SMARTLIST_FOREACH(failed, const char *, fp,
2160 char digest[DIGEST_LEN];
2161 trusted_dir_server_t *dir;
2162 base16_decode(digest, DIGEST_LEN, fp, strlen(fp));
2163 dir = router_get_trusteddirserver_by_digest(digest);
2165 if (dir)
2166 ++dir->n_networkstatus_failures;
2170 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
2171 * fetches have failed (with uppercase fingerprints listed in
2172 * <b>failed</b>). */
2173 static void
2174 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
2175 int was_extrainfo)
2177 char digest[DIGEST_LEN];
2178 time_t now = time(NULL);
2179 int server = server_mode(get_options()) && get_options()->DirPort;
2180 SMARTLIST_FOREACH(failed, const char *, cp,
2182 download_status_t *dls = NULL;
2183 base16_decode(digest, DIGEST_LEN, cp, strlen(cp));
2184 if (was_extrainfo) {
2185 signed_descriptor_t *sd =
2186 router_get_by_extrainfo_digest(digest);
2187 if (sd)
2188 dls = &sd->ei_dl_status;
2189 } else {
2190 local_routerstatus_t *rs =
2191 router_get_combined_status_by_descriptor_digest(digest);
2192 if (rs)
2193 dls = &rs->dl_status;
2195 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
2196 continue;
2197 if (status_code != 503 || server)
2198 ++dls->n_download_failures;
2199 if (server) {
2200 switch (dls->n_download_failures) {
2201 case 0: dls->next_attempt_at = 0; break;
2202 case 1: dls->next_attempt_at = 0; break;
2203 case 2: dls->next_attempt_at = 0; break;
2204 case 3: dls->next_attempt_at = now+60; break;
2205 case 4: dls->next_attempt_at = now+60; break;
2206 case 5: dls->next_attempt_at = now+60*2; break;
2207 case 6: dls->next_attempt_at = now+60*5; break;
2208 case 7: dls->next_attempt_at = now+60*15; break;
2209 default: dls->next_attempt_at = TIME_MAX; break;
2211 } else {
2212 switch (dls->n_download_failures) {
2213 case 0: dls->next_attempt_at = 0; break;
2214 case 1: dls->next_attempt_at = 0; break;
2215 case 2: dls->next_attempt_at = now+60; break;
2216 case 3: dls->next_attempt_at = now+60*5; break;
2217 case 4: dls->next_attempt_at = now+60*10; break;
2218 default: dls->next_attempt_at = TIME_MAX; break;
2221 if (dls->next_attempt_at == 0)
2222 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
2223 cp, (int)dls->n_download_failures);
2224 else if (dls->next_attempt_at < TIME_MAX)
2225 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
2226 cp, (int)dls->n_download_failures,
2227 (int)(dls->next_attempt_at-now));
2228 else
2229 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
2230 cp, (int)dls->n_download_failures);
2233 /* No need to relaunch descriptor downloads here: we already do it
2234 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
2237 /** Given a directory <b>resource</b> request, containing zero
2238 * or more strings separated by plus signs, followed optionally by ".z", store
2239 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
2240 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
2241 * decode_hex is true, then delete all elements that aren't hex digests, and
2242 * decode the rest. If sort_uniq is true, then sort the list and remove
2243 * all duplicates.
2246 dir_split_resource_into_fingerprints(const char *resource,
2247 smartlist_t *fp_out, int *compressed_out,
2248 int decode_hex, int sort_uniq)
2250 smartlist_t *fp_tmp = smartlist_create();
2251 tor_assert(fp_out);
2252 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
2253 if (compressed_out)
2254 *compressed_out = 0;
2255 if (smartlist_len(fp_tmp)) {
2256 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
2257 size_t last_len = strlen(last);
2258 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
2259 last[last_len-2] = '\0';
2260 if (compressed_out)
2261 *compressed_out = 1;
2264 if (decode_hex) {
2265 int i;
2266 char *cp, *d = NULL;
2267 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
2268 cp = smartlist_get(fp_tmp, i);
2269 if (strlen(cp) != HEX_DIGEST_LEN) {
2270 log_info(LD_DIR,
2271 "Skipping digest %s with non-standard length.", escaped(cp));
2272 smartlist_del_keeporder(fp_tmp, i--);
2273 goto again;
2275 d = tor_malloc_zero(DIGEST_LEN);
2276 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
2277 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
2278 smartlist_del_keeporder(fp_tmp, i--);
2279 goto again;
2281 smartlist_set(fp_tmp, i, d);
2282 d = NULL;
2283 again:
2284 tor_free(cp);
2285 tor_free(d);
2288 if (sort_uniq) {
2289 smartlist_t *fp_tmp2 = smartlist_create();
2290 int i;
2291 if (decode_hex)
2292 smartlist_sort_digests(fp_tmp);
2293 else
2294 smartlist_sort_strings(fp_tmp);
2295 if (smartlist_len(fp_tmp))
2296 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
2297 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
2298 char *cp = smartlist_get(fp_tmp, i);
2299 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
2301 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
2302 || (!decode_hex && strcasecmp(cp, last)))
2303 smartlist_add(fp_tmp2, cp);
2304 else
2305 tor_free(cp);
2307 smartlist_free(fp_tmp);
2308 fp_tmp = fp_tmp2;
2310 smartlist_add_all(fp_out, fp_tmp);
2311 smartlist_free(fp_tmp);
2312 return 0;