Refine r10571: more work on bridge stuff.
[tor.git] / src / or / directory.c
blob83a7a7b0b26d48c22647b62f30cdaacc37e863ee
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 && options->UseBridges) {
234 /* want to pick a bridge for which we have a descriptor. */
235 routerinfo_t *ri = choose_random_entry(NULL);
236 if (ri) {
237 directory_initiate_command(ri->address, ri->addr,
238 ri->or_port, 0,
239 1, ri->cache_info.identity_digest,
240 dir_purpose,
241 ROUTER_PURPOSE_GENERAL,
242 0, resource, NULL, 0);
243 } else
244 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
245 "nodes are available yet.");
246 return;
247 } else if (directconn) {
248 if (prefer_authority) {
249 /* only ask authdirservers, and don't ask myself */
250 rs = router_pick_trusteddirserver(type, 1, 1,
251 retry_if_no_servers);
253 if (!rs) {
254 /* anybody with a non-zero dirport will do */
255 rs = router_pick_directory_server(1, 1, type,
256 retry_if_no_servers);
257 if (!rs) {
258 const char *which;
259 if (dir_purpose == DIR_PURPOSE_FETCH_DIR)
260 which = "directory";
261 else if (dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST)
262 which = "status list";
263 else if (dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
264 which = "network status";
265 else // if (dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
266 which = "server descriptors";
267 log_info(LD_DIR,
268 "No router found for %s; falling back to dirserver list",
269 which);
270 rs = router_pick_trusteddirserver(type, 1, 1,
271 retry_if_no_servers);
272 if (!rs)
273 directconn = 0; /* last resort: try routing it via Tor */
276 } else { /* !directconn */
277 /* Never use fascistfirewall; we're going via Tor. */
278 if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
279 /* only ask hidserv authorities, any of them will do */
280 rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, 0, 0,
281 retry_if_no_servers);
282 } else {
283 /* anybody with a non-zero dirport will do. Disregard firewalls. */
284 rs = router_pick_directory_server(1, 0, type,
285 retry_if_no_servers);
286 /* If we have any hope of building an indirect conn, we know some router
287 * descriptors. If (rs==NULL), we can't build circuits anyway, so
288 * there's no point in falling back to the authorities in this case. */
292 if (rs)
293 directory_initiate_command_routerstatus(rs, dir_purpose,
294 ROUTER_PURPOSE_GENERAL,
295 !directconn,
296 resource, NULL, 0);
297 else {
298 log_notice(LD_DIR,
299 "While fetching directory info, "
300 "no running dirservers known. Will try again later. "
301 "(purpose %d)", dir_purpose);
302 if (!purpose_needs_anonymity(dir_purpose)) {
303 /* remember we tried them all and failed. */
304 directory_all_unreachable(time(NULL));
309 /** Launch a new connection to the directory server <b>status</b> to
310 * upload or download a server or rendezvous
311 * descriptor. <b>dir_purpose</b> determines what
312 * kind of directory connection we're launching, and must be one of
313 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}. <b>router_purpose</b>
314 * specifies the descriptor purposes we have in mind (currently only
315 * used for FETCH_DIR).
317 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
318 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
320 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
321 * want to fetch.
323 void
324 directory_initiate_command_routerstatus(routerstatus_t *status,
325 uint8_t dir_purpose,
326 uint8_t router_purpose,
327 int anonymized_connection,
328 const char *resource,
329 const char *payload,
330 size_t payload_len)
332 routerinfo_t *router;
333 char address_buf[INET_NTOA_BUF_LEN+1];
334 struct in_addr in;
335 const char *address;
336 if ((router = router_get_by_digest(status->identity_digest))) {
337 address = router->address;
338 } else {
339 in.s_addr = htonl(status->addr);
340 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
341 address = address_buf;
343 directory_initiate_command(address, status->addr,
344 status->or_port, status->dir_port,
345 status->version_supports_begindir,
346 status->identity_digest,
347 dir_purpose, router_purpose,
348 anonymized_connection, resource,
349 payload, payload_len);
352 /** Return true iff <b>conn</b> is the client side of a directory connection
353 * we launched to ourself in order to determine the reachability of our
354 * dir_port. */
355 static int
356 directory_conn_is_self_reachability_test(dir_connection_t *conn)
358 if (conn->requested_resource &&
359 !strcmpstart(conn->requested_resource,"authority")) {
360 routerinfo_t *me = router_get_my_routerinfo();
361 if (me &&
362 router_digest_is_me(conn->identity_digest) &&
363 me->addr == conn->_base.addr &&
364 me->dir_port == conn->_base.port)
365 return 1;
367 return 0;
370 /** Called when we are unable to complete the client's request to a directory
371 * server due to a network error: Mark the router as down and try again if
372 * possible.
374 void
375 connection_dir_request_failed(dir_connection_t *conn)
377 if (directory_conn_is_self_reachability_test(conn)) {
378 routerinfo_t *me = router_get_my_routerinfo();
379 if (me)
380 control_event_server_status(LOG_WARN,
381 "REACHABILITY_FAILED DIRADDRESS=%s:%d",
382 me->address, me->dir_port);
383 return; /* this was a test fetch. don't retry. */
385 router_set_status(conn->identity_digest, 0); /* don't try him again */
386 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR ||
387 conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
388 log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
389 conn->_base.address, conn->_base.port);
390 directory_get_from_dirserver(conn->_base.purpose, NULL,
391 0 /* don't retry_if_no_servers */);
392 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
393 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
394 conn->_base.address);
395 connection_dir_download_networkstatus_failed(conn, -1);
396 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
397 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
398 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
399 conn->_base.address);
400 connection_dir_download_routerdesc_failed(conn);
404 /** Called when an attempt to download one or more network status
405 * documents on connection <b>conn</b> failed. Decide whether to
406 * retry the fetch now, later, or never.
408 static void
409 connection_dir_download_networkstatus_failed(dir_connection_t *conn,
410 int status_code)
412 if (!conn->requested_resource) {
413 /* We never reached directory_send_command, which means that we never
414 * opened a network connection. Either we're out of sockets, or the
415 * network is down. Either way, retrying would be pointless. */
416 return;
418 if (!strcmpstart(conn->requested_resource, "all")) {
419 /* We're a non-authoritative directory cache; try again. Ignore status
420 * code, since we don't want to keep trying forever in a tight loop
421 * if all the authorities are shutting us out. */
422 smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
423 SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
424 ++ds->n_networkstatus_failures);
425 directory_get_from_dirserver(conn->_base.purpose, "all.z",
426 0 /* don't retry_if_no_servers */);
427 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
428 /* We were trying to download by fingerprint; mark them all as having
429 * failed, and possibly retry them later.*/
430 smartlist_t *failed = smartlist_create();
431 dir_split_resource_into_fingerprints(conn->requested_resource+3,
432 failed, NULL, 0, 0);
433 if (smartlist_len(failed)) {
434 dir_networkstatus_download_failed(failed, status_code);
435 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
437 smartlist_free(failed);
441 /** Called when an attempt to download one or more router descriptors
442 * or extra-info documents on connection <b>conn</b> failed.
444 static void
445 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
447 /* No need to increment the failure count for routerdescs, since
448 * it's not their fault. */
450 /* No need to relaunch descriptor downloads here: we already do it
451 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
452 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
453 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
455 (void) conn;
458 /** Helper for directory_initiate_command_(router|trusted_dir): send the
459 * command to a server whose address is <b>address</b>, whose IP is
460 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
461 * <b>supports_begindir</b>, and whose identity key digest is
462 * <b>digest</b>. */
463 void
464 directory_initiate_command(const char *address, uint32_t addr,
465 uint16_t or_port, uint16_t dir_port,
466 int supports_begindir, const char *digest,
467 uint8_t dir_purpose, uint8_t router_purpose,
468 int anonymized_connection, const char *resource,
469 const char *payload, size_t payload_len)
471 dir_connection_t *conn;
472 or_options_t *options = get_options();
473 int want_to_tunnel = options->TunnelDirConns && supports_begindir &&
474 !anonymized_connection && or_port &&
475 fascist_firewall_allows_address_or(addr, or_port);
477 tor_assert(address);
478 tor_assert(addr);
479 tor_assert(or_port || dir_port);
480 tor_assert(digest);
482 log_debug(LD_DIR, "anonymized %d, want_to_tunnel %d.",
483 anonymized_connection, want_to_tunnel);
485 switch (dir_purpose) {
486 case DIR_PURPOSE_FETCH_DIR:
487 log_debug(LD_DIR,"initiating directory fetch");
488 break;
489 case DIR_PURPOSE_FETCH_RENDDESC:
490 log_debug(LD_DIR,"initiating hidden-service descriptor fetch");
491 break;
492 case DIR_PURPOSE_UPLOAD_DIR:
493 log_debug(LD_OR,"initiating server descriptor upload");
494 break;
495 case DIR_PURPOSE_UPLOAD_RENDDESC:
496 log_debug(LD_REND,"initiating hidden-service descriptor upload");
497 break;
498 case DIR_PURPOSE_FETCH_RUNNING_LIST:
499 log_debug(LD_DIR,"initiating running-routers fetch");
500 break;
501 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
502 log_debug(LD_DIR,"initiating network-status fetch");
503 break;
504 case DIR_PURPOSE_FETCH_SERVERDESC:
505 log_debug(LD_DIR,"initiating server descriptor fetch");
506 break;
507 case DIR_PURPOSE_FETCH_EXTRAINFO:
508 log_debug(LD_DIR,"initiating extra-info fetch");
509 break;
510 default:
511 log_err(LD_BUG, "Unrecognized directory connection purpose.");
512 tor_assert(0);
515 conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
517 /* set up conn so it's got all the data we need to remember */
518 conn->_base.addr = addr;
519 conn->_base.port = want_to_tunnel ? or_port : dir_port;
520 conn->_base.address = tor_strdup(address);
521 memcpy(conn->identity_digest, digest, DIGEST_LEN);
523 conn->_base.purpose = dir_purpose;
524 conn->router_purpose = router_purpose;
526 /* give it an initial state */
527 conn->_base.state = DIR_CONN_STATE_CONNECTING;
529 if (!anonymized_connection && !want_to_tunnel) {
530 /* then we want to connect directly */
532 conn->dirconn_direct = 1;
533 if (options->HttpProxy) {
534 addr = options->HttpProxyAddr;
535 dir_port = options->HttpProxyPort;
538 switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
539 dir_port)) {
540 case -1:
541 connection_dir_request_failed(conn); /* retry if we want */
542 connection_free(TO_CONN(conn));
543 return;
544 case 1:
545 /* start flushing conn */
546 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
547 /* fall through */
548 case 0:
549 /* queue the command on the outbuf */
550 directory_send_command(conn, dir_purpose, 1, resource,
551 payload, payload_len);
552 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
553 /* writable indicates finish, readable indicates broken link,
554 error indicates broken link in windowsland. */
556 } else { /* we want to connect via tor */
557 edge_connection_t *linked_conn;
558 /* make an AP connection
559 * populate it and add it at the right state
560 * hook up both sides
562 conn->dirconn_direct = 0;
563 linked_conn =
564 connection_ap_make_link(conn->_base.address, conn->_base.port,
565 digest,
566 anonymized_connection ?
567 SOCKS_COMMAND_CONNECT :
568 SOCKS_COMMAND_CONNECT_DIR);
569 if (!linked_conn) {
570 log_warn(LD_NET,"Making tunnel to dirserver failed.");
571 connection_mark_for_close(TO_CONN(conn));
572 return;
574 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
576 if (connection_add(TO_CONN(conn)) < 0) {
577 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
578 connection_mark_for_close(TO_CONN(conn));
579 return;
581 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
582 /* queue the command on the outbuf */
583 directory_send_command(conn, dir_purpose, 0, resource,
584 payload, payload_len);
585 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
586 connection_start_reading(TO_CONN(linked_conn));
590 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
591 * are as in directory_initiate_command.
593 static void
594 directory_send_command(dir_connection_t *conn,
595 int purpose, int direct, const char *resource,
596 const char *payload, size_t payload_len)
598 char proxystring[256];
599 char proxyauthstring[256];
600 char hoststring[128];
601 char *url;
602 char request[8192];
603 const char *httpcommand = NULL;
604 size_t len;
606 tor_assert(conn);
607 tor_assert(conn->_base.type == CONN_TYPE_DIR);
609 tor_free(conn->requested_resource);
610 if (resource)
611 conn->requested_resource = tor_strdup(resource);
613 /* come up with a string for which Host: we want */
614 if (conn->_base.port == 80) {
615 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
616 } else {
617 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
618 conn->_base.address, conn->_base.port);
621 /* come up with some proxy lines, if we're using one. */
622 if (direct && get_options()->HttpProxy) {
623 char *base64_authenticator=NULL;
624 const char *authenticator = get_options()->HttpProxyAuthenticator;
626 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
627 if (authenticator) {
628 base64_authenticator = alloc_http_authenticator(authenticator);
629 if (!base64_authenticator)
630 log_warn(LD_BUG, "Encoding http authenticator failed");
632 if (base64_authenticator) {
633 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
634 "\r\nProxy-Authorization: Basic %s",
635 base64_authenticator);
636 tor_free(base64_authenticator);
637 } else {
638 proxyauthstring[0] = 0;
640 } else {
641 proxystring[0] = 0;
642 proxyauthstring[0] = 0;
645 switch (purpose) {
646 case DIR_PURPOSE_FETCH_DIR:
647 tor_assert(!resource);
648 tor_assert(!payload);
649 httpcommand = "GET";
650 url = tor_strdup("/tor/dir.z");
651 break;
652 case DIR_PURPOSE_FETCH_RUNNING_LIST:
653 tor_assert(!resource);
654 tor_assert(!payload);
655 httpcommand = "GET";
656 url = tor_strdup("/tor/running-routers");
657 break;
658 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
659 httpcommand = "GET";
660 len = strlen(resource)+32;
661 url = tor_malloc(len);
662 tor_snprintf(url, len, "/tor/status/%s", resource);
663 break;
664 case DIR_PURPOSE_FETCH_SERVERDESC:
665 httpcommand = "GET";
666 len = strlen(resource)+32;
667 url = tor_malloc(len);
668 tor_snprintf(url, len, "/tor/server/%s", resource);
669 break;
670 case DIR_PURPOSE_FETCH_EXTRAINFO:
671 httpcommand = "GET";
672 len = strlen(resource)+32;
673 url = tor_malloc(len);
674 tor_snprintf(url, len, "/tor/extra/%s", resource);
675 break;
676 case DIR_PURPOSE_UPLOAD_DIR:
677 tor_assert(!resource);
678 tor_assert(payload);
679 httpcommand = "POST";
680 url = tor_strdup("/tor/");
681 break;
682 case DIR_PURPOSE_FETCH_RENDDESC:
683 tor_assert(resource);
684 tor_assert(!payload);
686 /* this must be true or we wouldn't be doing the lookup */
687 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN);
688 /* This breaks the function abstraction. */
689 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
691 httpcommand = "GET";
692 /* Request the most recent versioned descriptor. */
693 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
694 // but that never got testing, and it wasn't a good design.)
695 len = strlen(resource)+32;
696 url = tor_malloc(len);
697 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
698 break;
699 case DIR_PURPOSE_UPLOAD_RENDDESC:
700 tor_assert(!resource);
701 tor_assert(payload);
702 httpcommand = "POST";
703 url = tor_strdup("/tor/rendezvous/publish");
704 break;
705 default:
706 tor_assert(0);
707 return;
710 if (strlen(proxystring) + strlen(url) >= 4096) {
711 log_warn(LD_BUG,
712 "Squid does not like URLs longer than 4095 bytes, and this "
713 "one is %d bytes long: %s%s",
714 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
717 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
718 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
719 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
720 tor_free(url);
722 if (!strcmp(httpcommand, "GET") && !payload) {
723 tor_snprintf(request, sizeof(request),
724 " HTTP/1.0\r\nHost: %s%s\r\n\r\n",
725 hoststring,
726 proxyauthstring);
727 } else {
728 tor_snprintf(request, sizeof(request),
729 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
730 payload ? (unsigned long)payload_len : 0,
731 hoststring,
732 proxyauthstring);
734 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
736 if (payload) {
737 /* then send the payload afterwards too */
738 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
742 /** Parse an HTTP request string <b>headers</b> of the form
743 * \verbatim
744 * "\%s [http[s]://]\%s HTTP/1..."
745 * \endverbatim
746 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
747 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
748 * so it does. Return 0.
749 * Otherwise, return -1.
751 static int
752 parse_http_url(const char *headers, char **url)
754 char *s, *start, *tmp;
756 s = (char *)eat_whitespace_no_nl(headers);
757 if (!*s) return -1;
758 s = (char *)find_whitespace(s); /* get past GET/POST */
759 if (!*s) return -1;
760 s = (char *)eat_whitespace_no_nl(s);
761 if (!*s) return -1;
762 start = s; /* this is it, assuming it's valid */
763 s = (char *)find_whitespace(start);
764 if (!*s) return -1;
766 /* tolerate the http[s] proxy style of putting the hostname in the url */
767 if (s-start >= 4 && !strcmpstart(start,"http")) {
768 tmp = start + 4;
769 if (*tmp == 's')
770 tmp++;
771 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
772 tmp = strchr(tmp+3, '/');
773 if (tmp && tmp < s) {
774 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
775 start = tmp;
780 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
781 *url = tor_malloc(s - start + 5);
782 strlcpy(*url,"/tor", s-start+5);
783 strlcat((*url)+4, start, s-start+1);
784 } else {
785 *url = tor_strndup(start, s-start);
787 return 0;
790 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
791 * <b>which</b>. The key should be given with a terminating colon and space;
792 * this function copies everything after, up to but not including the
793 * following \\r\\n. */
794 static char *
795 http_get_header(const char *headers, const char *which)
797 const char *cp = headers;
798 while (cp) {
799 if (!strcmpstart(cp, which)) {
800 char *eos;
801 cp += strlen(which);
802 if ((eos = strchr(cp,'\r')))
803 return tor_strndup(cp, eos-cp);
804 else
805 return tor_strdup(cp);
807 cp = strchr(cp, '\n');
808 if (cp)
809 ++cp;
811 return NULL;
814 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
815 * <b>conn</b>-\>address to describe our best guess of the address that
816 * originated this HTTP request. */
817 static void
818 http_set_address_origin(const char *headers, connection_t *conn)
820 char *fwd;
822 fwd = http_get_header(headers, "Forwarded-For: ");
823 if (!fwd)
824 fwd = http_get_header(headers, "X-Forwarded-For: ");
825 if (fwd) {
826 struct in_addr in;
827 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
828 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
829 escaped(fwd));
830 tor_free(fwd);
831 return;
833 tor_free(conn->address);
834 conn->address = tor_strdup(fwd);
835 tor_free(fwd);
839 /** Parse an HTTP response string <b>headers</b> of the form
840 * \verbatim
841 * "HTTP/1.\%d \%d\%s\r\n...".
842 * \endverbatim
844 * If it's well-formed, assign the status code to *<b>code</b> and
845 * return 0. Otherwise, return -1.
847 * On success: If <b>date</b> is provided, set *date to the Date
848 * header in the http headers, or 0 if no such header is found. If
849 * <b>compression</b> is provided, set *<b>compression</b> to the
850 * compression method given in the Content-Encoding header, or 0 if no
851 * such header is found, or -1 if the value of the header is not
852 * recognized. If <b>reason</b> is provided, strdup the reason string
853 * into it.
856 parse_http_response(const char *headers, int *code, time_t *date,
857 compress_method_t *compression, char **reason)
859 int n1, n2;
860 char datestr[RFC1123_TIME_LEN+1];
861 smartlist_t *parsed_headers;
862 tor_assert(headers);
863 tor_assert(code);
865 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
867 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
868 (n1 != 0 && n1 != 1) ||
869 (n2 < 100 || n2 >= 600)) {
870 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
871 return -1;
873 *code = n2;
875 parsed_headers = smartlist_create();
876 smartlist_split_string(parsed_headers, headers, "\n",
877 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
878 if (reason) {
879 smartlist_t *status_line_elements = smartlist_create();
880 tor_assert(smartlist_len(parsed_headers));
881 smartlist_split_string(status_line_elements,
882 smartlist_get(parsed_headers, 0),
883 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
884 tor_assert(smartlist_len(status_line_elements) <= 3);
885 if (smartlist_len(status_line_elements) == 3) {
886 *reason = smartlist_get(status_line_elements, 2);
887 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
889 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
890 smartlist_free(status_line_elements);
892 if (date) {
893 *date = 0;
894 SMARTLIST_FOREACH(parsed_headers, const char *, s,
895 if (!strcmpstart(s, "Date: ")) {
896 strlcpy(datestr, s+6, sizeof(datestr));
897 /* This will do nothing on failure, so we don't need to check
898 the result. We shouldn't warn, since there are many other valid
899 date formats besides the one we use. */
900 parse_rfc1123_time(datestr, date);
901 break;
904 if (compression) {
905 const char *enc = NULL;
906 SMARTLIST_FOREACH(parsed_headers, const char *, s,
907 if (!strcmpstart(s, "Content-Encoding: ")) {
908 enc = s+18; break;
910 if (!enc || !strcmp(enc, "identity")) {
911 *compression = NO_METHOD;
912 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
913 *compression = ZLIB_METHOD;
914 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
915 *compression = GZIP_METHOD;
916 } else {
917 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
918 escaped(enc));
919 *compression = UNKNOWN_METHOD;
922 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
923 smartlist_free(parsed_headers);
925 return 0;
928 /** Return true iff <b>body</b> doesn't start with a plausible router or
929 * running-list or directory opening. This is a sign of possible compression.
931 static int
932 body_is_plausible(const char *body, size_t len, int purpose)
934 int i;
935 if (len == 0)
936 return 1; /* empty bodies don't need decompression */
937 if (len < 32)
938 return 0;
939 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
940 if (!strcmpstart(body,"router") ||
941 !strcmpstart(body,"signed-directory") ||
942 !strcmpstart(body,"network-status") ||
943 !strcmpstart(body,"running-routers"))
944 return 1;
945 for (i=0;i<32;++i) {
946 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
947 return 0;
949 return 1;
950 } else {
951 return 1;
955 /** We are a client, and we've finished reading the server's
956 * response. Parse and it and act appropriately.
958 * If we're still happy with using this directory server in the future, return
959 * 0. Otherwise return -1; and the caller should consider trying the request
960 * again.
962 * The caller will take care of marking the connection for close.
964 static int
965 connection_dir_client_reached_eof(dir_connection_t *conn)
967 char *body;
968 char *headers;
969 char *reason = NULL;
970 size_t body_len=0, orig_len=0;
971 int status_code;
972 time_t date_header=0;
973 int delta;
974 compress_method_t compression;
975 int plausible;
976 int skewed=0;
977 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
978 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
979 int was_compressed=0;
980 time_t now = time(NULL);
982 switch (fetch_from_buf_http(conn->_base.inbuf,
983 &headers, MAX_HEADERS_SIZE,
984 &body, &body_len, MAX_DIR_DL_SIZE,
985 allow_partial)) {
986 case -1: /* overflow */
987 log_warn(LD_PROTOCOL,
988 "'fetch' response too large (server '%s:%d'). Closing.",
989 conn->_base.address, conn->_base.port);
990 return -1;
991 case 0:
992 log_info(LD_HTTP,
993 "'fetch' response not all here, but we're at eof. Closing.");
994 return -1;
995 /* case 1, fall through */
997 orig_len = body_len;
999 if (parse_http_response(headers, &status_code, &date_header,
1000 &compression, &reason) < 0) {
1001 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1002 conn->_base.address, conn->_base.port);
1003 tor_free(body); tor_free(headers);
1004 return -1;
1006 if (!reason) reason = tor_strdup("[no reason given]");
1008 log_debug(LD_DIR,
1009 "Received response from directory server '%s:%d': %d %s",
1010 conn->_base.address, conn->_base.port, status_code,
1011 escaped(reason));
1013 /* now check if it's got any hints for us about our IP address. */
1014 if (conn->dirconn_direct) {
1015 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1016 if (guess) {
1017 router_new_address_suggestion(guess);
1018 tor_free(guess);
1022 if (date_header > 0) {
1023 /* The date header was written very soon after we sent our request,
1024 * so compute the skew as the difference between sending the request
1025 * and the date header. (We used to check now-date_header, but that's
1026 * inaccurate if we spend a lot of time downloading.)
1028 delta = conn->_base.timestamp_lastwritten - date_header;
1029 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1030 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1031 log_fn(trusted ? LOG_WARN : LOG_INFO,
1032 LD_HTTP,
1033 "Received directory with skewed time (server '%s:%d'): "
1034 "we are %d minutes %s, or the directory is %d minutes %s.",
1035 conn->_base.address, conn->_base.port,
1036 abs(delta)/60, delta>0 ? "ahead" : "behind",
1037 abs(delta)/60, delta>0 ? "behind" : "ahead");
1038 skewed = 1; /* don't check the recommended-versions line */
1039 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1040 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
1041 delta, conn->_base.address, conn->_base.port);
1042 } else {
1043 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1044 "we are %d seconds skewed. (That's okay.)", delta);
1047 (void) skewed; /* skewed isn't used yet. */
1049 if (status_code == 503) {
1050 local_routerstatus_t *rs;
1051 trusted_dir_server_t *ds;
1052 log_info(LD_DIR,"Received http status code %d (%s) from server "
1053 "'%s:%d'. I'll try again soon.",
1054 status_code, escaped(reason), conn->_base.address,
1055 conn->_base.port);
1056 if ((rs = router_get_combined_status_by_digest(conn->identity_digest)))
1057 rs->last_dir_503_at = now;
1058 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1059 ds->fake_status.last_dir_503_at = now;
1061 tor_free(body); tor_free(headers); tor_free(reason);
1062 return -1;
1065 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1066 if (compression != NO_METHOD || !plausible) {
1067 char *new_body = NULL;
1068 size_t new_len = 0;
1069 compress_method_t guessed = detect_compression_method(body, body_len);
1070 if (compression == UNKNOWN_METHOD || guessed != compression) {
1071 /* Tell the user if we don't believe what we're told about compression.*/
1072 const char *description1, *description2;
1073 if (compression == ZLIB_METHOD)
1074 description1 = "as deflated";
1075 else if (compression == GZIP_METHOD)
1076 description1 = "as gzipped";
1077 else if (compression == NO_METHOD)
1078 description1 = "as uncompressed";
1079 else
1080 description1 = "with an unknown Content-Encoding";
1081 if (guessed == ZLIB_METHOD)
1082 description2 = "deflated";
1083 else if (guessed == GZIP_METHOD)
1084 description2 = "gzipped";
1085 else if (!plausible)
1086 description2 = "confusing binary junk";
1087 else
1088 description2 = "uncompressed";
1090 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1091 "but it seems to be %s.%s",
1092 conn->_base.address, conn->_base.port, description1,
1093 description2,
1094 (compression>0 && guessed>0)?" Trying both.":"");
1096 /* Try declared compression first if we can. */
1097 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1098 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1099 !allow_partial, LOG_PROTOCOL_WARN);
1100 /* Okay, if that didn't work, and we think that it was compressed
1101 * differently, try that. */
1102 if (!new_body &&
1103 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1104 compression != guessed)
1105 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1106 !allow_partial, LOG_PROTOCOL_WARN);
1107 /* If we're pretty sure that we have a compressed directory, and
1108 * we didn't manage to uncompress it, then warn and bail. */
1109 if (!plausible && !new_body) {
1110 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1111 "Unable to decompress HTTP body (server '%s:%d').",
1112 conn->_base.address, conn->_base.port);
1113 tor_free(body); tor_free(headers); tor_free(reason);
1114 return -1;
1116 if (new_body) {
1117 tor_free(body);
1118 body = new_body;
1119 body_len = new_len;
1120 was_compressed = 1;
1124 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
1125 /* fetch/process the directory to cache it. */
1126 log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
1127 (int)body_len, conn->_base.address, conn->_base.port);
1128 if (status_code != 200) {
1129 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1130 "'%s:%d' while fetching directory. I'll try again soon.",
1131 status_code, escaped(reason), conn->_base.address,
1132 conn->_base.port);
1133 tor_free(body); tor_free(headers); tor_free(reason);
1134 return -1;
1136 if (router_parse_directory(body) < 0) {
1137 log_notice(LD_DIR,"I failed to parse the directory I fetched from "
1138 "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
1140 note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
1143 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
1144 /* just update our list of running routers, if this list is new info */
1145 log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
1146 if (status_code != 200) {
1147 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1148 "'%s:%d' while fetching running-routers. I'll try again soon.",
1149 status_code, escaped(reason), conn->_base.address,
1150 conn->_base.port);
1151 tor_free(body); tor_free(headers); tor_free(reason);
1152 return -1;
1154 if (router_parse_runningrouters(body)<0) {
1155 log_warn(LD_DIR,
1156 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1157 conn->_base.address, conn->_base.port);
1158 tor_free(body); tor_free(headers); tor_free(reason);
1159 return -1;
1161 note_request(was_compressed?"dl/running-routers.z":
1162 "dl/running-routers", orig_len);
1165 if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
1166 smartlist_t *which = NULL;
1167 networkstatus_source_t source;
1168 char *cp;
1169 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1170 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1171 if (status_code != 200) {
1172 /* XXXX020 This warning tends to freak out clients who get a 403. */
1173 log_warn(LD_DIR,
1174 "Received http status code %d (%s) from server "
1175 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1176 status_code, escaped(reason), conn->_base.address,
1177 conn->_base.port, conn->requested_resource);
1178 tor_free(body); tor_free(headers); tor_free(reason);
1179 connection_dir_download_networkstatus_failed(conn, status_code);
1180 return -1;
1182 note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
1183 if (conn->requested_resource &&
1184 !strcmpstart(conn->requested_resource,"fp/")) {
1185 source = NS_FROM_DIR_BY_FP;
1186 which = smartlist_create();
1187 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1188 which, NULL, 0, 0);
1189 } else if (conn->requested_resource &&
1190 !strcmpstart(conn->requested_resource, "all")) {
1191 source = NS_FROM_DIR_ALL;
1192 which = smartlist_create();
1193 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1194 trusted_dir_server_t *, ds,
1196 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1197 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1198 smartlist_add(which, hex);
1200 } else {
1201 /* Can we even end up here? -- weasel*/
1202 source = NS_FROM_DIR_BY_FP;
1203 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1204 "for it by fp, nor did we ask for all.");
1206 cp = body;
1207 while (*cp) {
1208 char *next = strstr(cp, "\nnetwork-status-version");
1209 if (next)
1210 next[1] = '\0';
1211 /* learn from it, and then remove it from 'which' */
1212 if (router_set_networkstatus(cp, now, source, which)<0)
1213 break;
1214 if (next) {
1215 next[1] = 'n';
1216 cp = next+1;
1217 } else
1218 break;
1220 routers_update_all_from_networkstatus(now); /*launches router downloads*/
1221 directory_info_has_arrived(now, 0);
1222 if (which) {
1223 if (smartlist_len(which)) {
1224 dir_networkstatus_download_failed(which, status_code);
1226 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1227 smartlist_free(which);
1231 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1232 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1233 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1234 smartlist_t *which = NULL;
1235 int n_asked_for = 0;
1236 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1237 was_ei ? "extra server info" : "server info",
1238 (int)body_len, conn->_base.address, conn->_base.port);
1239 if (was_ei)
1240 note_request(was_compressed?"dl/extra.z":"dl/extra", orig_len);
1241 else
1242 note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
1243 if (conn->requested_resource &&
1244 !strcmpstart(conn->requested_resource,"d/")) {
1245 which = smartlist_create();
1246 dir_split_resource_into_fingerprints(conn->requested_resource+2,
1247 which, NULL, 0, 0);
1248 n_asked_for = smartlist_len(which);
1250 if (status_code != 200) {
1251 int dir_okay = status_code == 404 ||
1252 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1253 /* 404 means that it didn't have them; no big deal.
1254 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1255 /* XXXX020 This warning tends to freak out clients who get a 403. */
1256 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1257 "Received http status code %d (%s) from server '%s:%d' "
1258 "while fetching \"/tor/server/%s\". I'll try again soon.",
1259 status_code, escaped(reason), conn->_base.address,
1260 conn->_base.port, conn->requested_resource);
1261 if (!which) {
1262 connection_dir_download_routerdesc_failed(conn);
1263 } else {
1264 dir_routerdesc_download_failed(which, status_code, was_ei);
1265 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1266 smartlist_free(which);
1268 tor_free(body); tor_free(headers); tor_free(reason);
1269 return dir_okay ? 0 : -1;
1271 /* Learn the routers, assuming we requested by fingerprint or "all"
1272 * or "authority".
1274 * We use "authority" to fetch our own descriptor for
1275 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1276 * the output of "authority" requests unless we are using bridges,
1277 * since otherwise they'll be the response from reachability tests,
1278 * and we don't really want to add that to our routerlist. */
1279 if (which || (conn->requested_resource &&
1280 (!strcmpstart(conn->requested_resource, "all") ||
1281 (!strcmpstart(conn->requested_resource, "authority") &&
1282 get_options()->UseBridges)))) {
1283 /* as we learn from them, we remove them from 'which' */
1284 if (was_ei) {
1285 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which);
1286 } else {
1287 router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1288 conn->router_purpose);
1289 directory_info_has_arrived(now, 0);
1292 if (which) { /* mark remaining ones as failed */
1293 log_info(LD_DIR, "Received %d/%d routers requested from %s:%d",
1294 n_asked_for-smartlist_len(which), n_asked_for,
1295 conn->_base.address, (int)conn->_base.port);
1296 if (smartlist_len(which)) {
1297 dir_routerdesc_download_failed(which, status_code, was_ei);
1299 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1300 smartlist_free(which);
1302 if (directory_conn_is_self_reachability_test(conn))
1303 router_dirport_found_reachable();
1306 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1307 switch (status_code) {
1308 case 200: {
1309 int all_done = 1;
1310 trusted_dir_server_t *ds =
1311 router_get_trusteddirserver_by_digest(conn->identity_digest);
1312 smartlist_t *servers;
1313 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1314 "descriptor: finished.");
1315 control_event_server_status(
1316 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1317 conn->_base.address, conn->_base.port);
1319 ds->has_accepted_serverdesc = 1;
1320 servers = router_get_trusted_dir_servers();
1321 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
1322 if ((d->type & (V1_AUTHORITY|V2_AUTHORITY)) &&
1323 !d->has_accepted_serverdesc) {
1324 all_done = 0;
1325 break;
1328 if (all_done)
1329 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1331 break;
1332 case 400:
1333 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1334 "dirserver '%s:%d'. Please correct.",
1335 escaped(reason), conn->_base.address, conn->_base.port);
1336 control_event_server_status(LOG_WARN,
1337 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1338 conn->_base.address, conn->_base.port, escaped(reason));
1339 break;
1340 case 403:
1341 log_warn(LD_GENERAL,
1342 "http status 403 (%s) response from dirserver "
1343 "'%s:%d'. Is your clock skewed? Have you mailed us your key "
1344 "fingerprint? Are you using the right key? Are you using a "
1345 "private IP address? See http://tor.eff.org/doc/"
1346 "tor-doc-server.html",escaped(reason), conn->_base.address,
1347 conn->_base.port);
1348 control_event_server_status(LOG_WARN,
1349 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1350 conn->_base.address, conn->_base.port, escaped(reason));
1351 break;
1352 default:
1353 log_warn(LD_GENERAL,
1354 "http status %d (%s) reason unexpected while uploading "
1355 "descriptor to server '%s:%d').",
1356 status_code, escaped(reason), conn->_base.address,
1357 conn->_base.port);
1358 break;
1360 /* return 0 in all cases, since we don't want to mark any
1361 * dirservers down just because they don't like us. */
1364 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1365 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1366 "(%s))",
1367 (int)body_len, status_code, escaped(reason));
1368 switch (status_code) {
1369 case 200:
1370 if (rend_cache_store(body, body_len, 0) < 0) {
1371 log_warn(LD_REND,"Failed to store rendezvous descriptor.");
1372 /* alice's ap_stream will notice when connection_mark_for_close
1373 * cleans it up */
1374 } else {
1375 /* success. notify pending connections about this. */
1376 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1377 rend_client_desc_here(conn->rend_query);
1379 break;
1380 case 404:
1381 /* not there. pending connections will be notified when
1382 * connection_mark_for_close cleans it up. */
1383 break;
1384 case 400:
1385 log_warn(LD_REND,
1386 "http status 400 (%s). Dirserver didn't like our "
1387 "rendezvous query?", escaped(reason));
1388 break;
1389 default:
1390 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1391 "fetching hidden service descriptor (server '%s:%d').",
1392 status_code, escaped(reason), conn->_base.address,
1393 conn->_base.port);
1394 break;
1398 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
1399 switch (status_code) {
1400 case 200:
1401 log_info(LD_REND,
1402 "Uploading rendezvous descriptor: finished with status "
1403 "200 (%s)", escaped(reason));
1404 break;
1405 case 400:
1406 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1407 "'%s:%d'. Malformed rendezvous descriptor?",
1408 escaped(reason), conn->_base.address, conn->_base.port);
1409 break;
1410 default:
1411 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1412 "'%s:%d').",
1413 status_code, escaped(reason), conn->_base.address,
1414 conn->_base.port);
1415 break;
1418 tor_free(body); tor_free(headers); tor_free(reason);
1419 return 0;
1422 /** Called when a directory connection reaches EOF */
1424 connection_dir_reached_eof(dir_connection_t *conn)
1426 int retval;
1427 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
1428 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
1429 conn->_base.state);
1430 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
1431 connection_mark_for_close(TO_CONN(conn));
1432 return -1;
1435 retval = connection_dir_client_reached_eof(conn);
1436 if (retval == 0) /* success */
1437 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
1438 connection_mark_for_close(TO_CONN(conn));
1439 return retval;
1442 /** If any directory object is arriving, and it's over 10MB large, we're
1443 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1444 * ask for more than 96 router descriptors at a time.)
1446 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1448 /** Read handler for directory connections. (That's connections <em>to</em>
1449 * directory servers and connections <em>at</em> directory servers.)
1452 connection_dir_process_inbuf(dir_connection_t *conn)
1454 tor_assert(conn);
1455 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1457 /* Directory clients write, then read data until they receive EOF;
1458 * directory servers read data until they get an HTTP command, then
1459 * write their response (when it's finished flushing, they mark for
1460 * close).
1463 /* If we're on the dirserver side, look for a command. */
1464 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1465 if (directory_handle_command(conn) < 0) {
1466 connection_mark_for_close(TO_CONN(conn));
1467 return -1;
1469 return 0;
1472 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
1473 log_warn(LD_HTTP, "Too much data received from directory connection: "
1474 "denial of service attempt, or you need to upgrade?");
1475 connection_mark_for_close(TO_CONN(conn));
1476 return -1;
1479 if (!conn->_base.inbuf_reached_eof)
1480 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1481 return 0;
1484 /** Create an http response for the client <b>conn</b> out of
1485 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1487 static void
1488 write_http_status_line(dir_connection_t *conn, int status,
1489 const char *reason_phrase)
1491 char buf[256];
1492 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1493 status, reason_phrase ? reason_phrase : "OK") < 0) {
1494 log_warn(LD_BUG,"status line too long.");
1495 return;
1497 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
1500 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1501 * with <b>type</b> as the Content-Type.
1503 * If <b>length</b> is nonnegative, it is the Content-Length.
1504 * If <b>encoding</b> is provided, it is the Content-Encoding.
1505 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1506 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1507 static void
1508 write_http_response_header(dir_connection_t *conn, ssize_t length,
1509 const char *type, const char *encoding,
1510 int cache_lifetime)
1512 char date[RFC1123_TIME_LEN+1];
1513 char tmp[1024];
1514 char *cp;
1515 time_t now = time(NULL);
1517 tor_assert(conn);
1518 tor_assert(type);
1520 format_rfc1123_time(date, now);
1521 cp = tmp;
1522 tor_snprintf(cp, sizeof(tmp),
1523 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n",
1524 date, type);
1525 cp += strlen(tmp);
1526 if (!is_internal_IP(conn->_base.addr, 0)) {
1527 /* Don't report the source address for a localhost/private connection. */
1528 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1529 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
1530 cp += strlen(cp);
1532 if (encoding) {
1533 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1534 "Content-Encoding: %s\r\n", encoding);
1535 cp += strlen(cp);
1537 if (length >= 0) {
1538 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1539 "Content-Length: %ld\r\n", (long)length);
1540 cp += strlen(cp);
1542 if (cache_lifetime > 0) {
1543 char expbuf[RFC1123_TIME_LEN+1];
1544 format_rfc1123_time(expbuf, now + cache_lifetime);
1545 /* We could say 'Cache-control: max-age=%d' here if we start doing
1546 * http/1.1 */
1547 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1548 "Expires: %s\r\n", expbuf);
1549 cp += strlen(cp);
1550 } else {
1551 /* We could say 'Cache-control: no-cache' here if we start doing
1552 * http/1.1 */
1553 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
1554 cp += strlen(cp);
1556 if (sizeof(tmp)-(cp-tmp) > 3)
1557 memcpy(cp, "\r\n", 3);
1558 else
1559 tor_assert(0);
1560 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
1563 /** Helper function: return 1 if there are any dir conns of purpose
1564 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1565 * Else return 0.
1567 static int
1568 already_fetching_directory(int purpose)
1570 smartlist_t *conns = get_connection_array();
1571 SMARTLIST_FOREACH(conns, connection_t *, conn,
1573 if (conn->type == CONN_TYPE_DIR &&
1574 conn->purpose == purpose &&
1575 !conn->marked_for_close &&
1576 !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
1577 return 1;
1579 return 0;
1582 #ifdef INSTRUMENT_DOWNLOADS
1583 /** Map used to keep track of how much data we've up/downloaded in what kind
1584 * of request. Maps from request type to pointer to uint64_t. */
1585 static strmap_t *request_bytes_map = NULL;
1587 /** Called when we just transmitted or received <b>bytes</b> worth of data
1588 * because of a request of type <b>key</b> (an arbitrary identifier): adds
1589 * <b>bytes</b> to the total associated with key. */
1590 static void
1591 note_request(const char *key, size_t bytes)
1593 uint64_t *n;
1594 if (!request_bytes_map)
1595 request_bytes_map = strmap_new();
1597 n = strmap_get(request_bytes_map, key);
1598 if (!n) {
1599 n = tor_malloc_zero(sizeof(uint64_t));
1600 strmap_set(request_bytes_map, key, n);
1602 *n += bytes;
1605 /** Return a newly allocated string holding a summary of bytes used per
1606 * request type. */
1607 char *
1608 directory_dump_request_log(void)
1610 smartlist_t *lines;
1611 char tmp[256];
1612 char *result;
1613 strmap_iter_t *iter;
1615 if (!request_bytes_map)
1616 request_bytes_map = strmap_new();
1618 lines = smartlist_create();
1620 for (iter = strmap_iter_init(request_bytes_map);
1621 !strmap_iter_done(iter);
1622 iter = strmap_iter_next(request_bytes_map, iter)) {
1623 const char *key;
1624 void *val;
1625 uint64_t *n;
1626 strmap_iter_get(iter, &key, &val);
1627 n = val;
1628 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT"\n",
1629 key, U64_PRINTF_ARG(*n));
1630 smartlist_add(lines, tor_strdup(tmp));
1632 smartlist_sort_strings(lines);
1633 result = smartlist_join_strings(lines, "", 0, NULL);
1634 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
1635 smartlist_free(lines);
1636 return result;
1638 #else
1639 static void
1640 note_request(const char *key, size_t bytes)
1642 (void)key;
1643 (void)bytes;
1646 char *
1647 directory_dump_request_log(void)
1649 return tor_strdup("Not supported.");
1651 #endif
1653 /** Helper function: called when a dirserver gets a complete HTTP GET
1654 * request. Look for a request for a directory or for a rendezvous
1655 * service descriptor. On finding one, write a response into
1656 * conn-\>outbuf. If the request is unrecognized, send a 400.
1657 * Always return 0. */
1658 static int
1659 directory_handle_command_get(dir_connection_t *conn, const char *headers,
1660 const char *body, size_t body_len)
1662 size_t dlen;
1663 char *url = NULL;
1664 or_options_t *options = get_options();
1665 time_t if_modified_since = 0;
1666 char *header;
1668 /* We ignore the body of a GET request. */
1669 (void)body;
1670 (void)body_len;
1672 log_debug(LD_DIRSERV,"Received GET command.");
1674 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
1676 if (parse_http_url(headers, &url) < 0) {
1677 write_http_status_line(conn, 400, "Bad request");
1678 return 0;
1680 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
1681 struct tm tm;
1682 if (parse_http_time(header, &tm) == 0) {
1683 if_modified_since = tor_timegm(&tm);
1685 /* The correct behavior on a malformed If-Modified-Since header is to
1686 * act as if no If-Modified-Since header had been given. */
1687 tor_free(header);
1689 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
1691 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir.z")) { /* dir fetch */
1692 int deflated = !strcmp(url,"/tor/dir.z");
1693 cached_dir_t *d = dirserv_get_directory();
1695 if (!d) {
1696 log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
1697 "don't have a good one yet. Sending 503 Dir not available.");
1698 write_http_status_line(conn, 503, "Directory unavailable");
1699 /* try to get a new one now */
1700 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR) &&
1701 !should_delay_dir_fetches(options))
1702 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1);
1703 tor_free(url);
1704 return 0;
1706 if (d->published < if_modified_since) {
1707 write_http_status_line(conn, 304, "Not modified");
1708 tor_free(url);
1709 return 0;
1712 dlen = deflated ? d->dir_z_len : d->dir_len;
1714 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
1715 log_info(LD_DIRSERV,
1716 "Client asked for the mirrored directory, but we've been "
1717 "writing too many bytes lately. Sending 503 Dir busy.");
1718 write_http_status_line(conn, 503, "Directory busy, try again later");
1719 tor_free(url);
1720 return 0;
1723 note_request(url, dlen);
1724 tor_free(url);
1726 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
1727 deflated?"deflated ":"");
1728 write_http_response_header(conn, dlen,
1729 deflated?"application/octet-stream":"text/plain",
1730 deflated?"deflate":"identity",
1731 FULL_DIR_CACHE_LIFETIME);
1732 conn->cached_dir = d;
1733 conn->cached_dir_offset = 0;
1734 if (! deflated)
1735 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
1736 ++d->refcnt;
1738 /* Prime the connection with some data. */
1739 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
1740 connection_dirserv_flushed_some(conn);
1741 return 0;
1744 if (!strcmp(url,"/tor/running-routers") ||
1745 !strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
1746 int deflated = !strcmp(url,"/tor/running-routers.z");
1747 cached_dir_t *d = dirserv_get_runningrouters();
1748 if (!d) {
1749 write_http_status_line(conn, 503, "Directory unavailable");
1750 /* try to get a new one now */
1751 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST) &&
1752 !should_delay_dir_fetches(options))
1753 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
1754 tor_free(url);
1755 return 0;
1757 if (d->published < if_modified_since) {
1758 write_http_status_line(conn, 304, "Not modified");
1759 tor_free(url);
1760 return 0;
1762 dlen = deflated ? d->dir_z_len : d->dir_len;
1764 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
1765 log_info(LD_DIRSERV,
1766 "Client asked for running-routers, but we've been "
1767 "writing too many bytes lately. Sending 503 Dir busy.");
1768 write_http_status_line(conn, 503, "Directory busy, try again later");
1769 tor_free(url);
1770 return 0;
1772 note_request(url, dlen);
1773 tor_free(url);
1774 write_http_response_header(conn, dlen,
1775 deflated?"application/octet-stream":"text/plain",
1776 deflated?"deflate":"identity",
1777 RUNNINGROUTERS_CACHE_LIFETIME);
1778 connection_write_to_buf(deflated ? d->dir_z : d->dir, dlen, TO_CONN(conn));
1779 return 0;
1782 if (!strcmpstart(url,"/tor/status/")) {
1783 /* v2 network status fetch. */
1784 size_t url_len = strlen(url);
1785 int deflated = !strcmp(url+url_len-2, ".z");
1786 smartlist_t *dir_fps = smartlist_create();
1787 const char *request_type = NULL;
1788 const char *key = url + strlen("/tor/status/");
1789 if (deflated)
1790 url[url_len-2] = '\0';
1791 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
1792 if (!strcmpstart(key, "fp/"))
1793 request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
1794 else if (!strcmpstart(key, "authority"))
1795 request_type = deflated?"/tor/status/authority.z":
1796 "/tor/status/authority";
1797 else if (!strcmpstart(key, "all"))
1798 request_type = deflated?"/tor/status/all.z":"/tor/status/all";
1799 else
1800 request_type = "/tor/status/?";
1801 tor_free(url);
1802 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
1803 write_http_status_line(conn, 503, "Network status object unavailable");
1804 smartlist_free(dir_fps);
1805 return 0;
1807 if (dirserv_statuses_are_old(dir_fps, if_modified_since)) {
1808 write_http_status_line(conn, 304, "Not modified");
1809 smartlist_free(dir_fps);
1810 return 0;
1813 dlen = dirserv_estimate_data_size(dir_fps, 0, deflated);
1814 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
1815 log_info(LD_DIRSERV,
1816 "Client asked for network status lists, but we've been "
1817 "writing too many bytes lately. Sending 503 Dir busy.");
1818 write_http_status_line(conn, 503, "Directory busy, try again later");
1819 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
1820 smartlist_free(dir_fps);
1821 return 0;
1824 // note_request(request_type,dlen);
1825 (void) request_type;
1826 write_http_response_header(conn, -1,
1827 deflated?"application/octet_stream":"text/plain",
1828 deflated?"deflate":NULL,
1829 smartlist_len(dir_fps) == 1 ? NETWORKSTATUS_CACHE_LIFETIME:0);
1830 conn->fingerprint_stack = dir_fps;
1831 if (! deflated)
1832 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
1834 /* Prime the connection with some data. */
1835 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
1836 connection_dirserv_flushed_some(conn);
1838 return 0;
1841 if (!strcmpstart(url,"/tor/server/") ||
1842 !strcmpstart(url,"/tor/extra/")) {
1843 char *url_mem = url;
1844 size_t url_len = strlen(url);
1845 int deflated = !strcmp(url+url_len-2, ".z");
1846 int res;
1847 const char *msg;
1848 const char *request_type = NULL;
1849 int cache_lifetime = 0;
1850 int is_extra = !strcmpstart(url,"/tor/extra/");
1851 if (deflated)
1852 url[url_len-2] = '\0';
1853 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
1854 conn->fingerprint_stack = smartlist_create();
1855 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
1856 &msg);
1858 if (!strcmpstart(url, "fp/")) {
1859 request_type = deflated?"/tor/server/fp.z":"/tor/server/fp";
1860 if (smartlist_len(conn->fingerprint_stack) == 1)
1861 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
1862 } else if (!strcmpstart(url, "authority")) {
1863 request_type = deflated?"/tor/server/authority.z":
1864 "/tor/server/authority";
1865 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
1866 } else if (!strcmpstart(url, "all")) {
1867 request_type = deflated?"/tor/server/all.z":"/tor/server/all";
1868 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
1869 } else if (!strcmpstart(url, "d/")) {
1870 request_type = deflated?"/tor/server/d.z":"/tor/server/d";
1871 if (smartlist_len(conn->fingerprint_stack) == 1)
1872 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
1873 } else {
1874 request_type = "/tor/server/?";
1876 (void) request_type; /* usable for note_request. */
1877 if (!strcmpstart(url, "d/"))
1878 conn->dir_spool_src =
1879 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
1880 else
1881 conn->dir_spool_src =
1882 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
1883 tor_free(url_mem);
1884 if (res < 0)
1885 write_http_status_line(conn, 404, msg);
1886 else {
1887 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
1888 1, deflated);
1889 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
1890 log_info(LD_DIRSERV,
1891 "Client asked for server descriptors, but we've been "
1892 "writing too many bytes lately. Sending 503 Dir busy.");
1893 write_http_status_line(conn, 503, "Directory busy, try again later");
1894 return 0;
1896 write_http_response_header(conn, -1,
1897 deflated?"application/octet_stream":"text/plain",
1898 deflated?"deflate":NULL, cache_lifetime);
1899 if (deflated)
1900 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
1901 /* Prime the connection with some data. */
1902 connection_dirserv_flushed_some(conn);
1904 return 0;
1907 if (options->HSAuthoritativeDir &&
1908 (!strcmpstart(url,"/tor/rendezvous/") ||
1909 !strcmpstart(url,"/tor/rendezvous1/"))) {
1910 /* rendezvous descriptor fetch */
1911 const char *descp;
1912 size_t desc_len;
1913 int versioned = !strcmpstart(url,"/tor/rendezvous1/");
1914 const char *query = url+strlen("/tor/rendezvous/")+(versioned?1:0);
1916 switch (rend_cache_lookup_desc(query, versioned?-1:0, &descp, &desc_len)) {
1917 case 1: /* valid */
1918 write_http_response_header(conn, desc_len, "application/octet-stream",
1919 NULL, 0);
1920 note_request("/tor/rendezvous?/", desc_len);
1921 /* need to send descp separately, because it may include nuls */
1922 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
1923 /* report successful fetch to statistic */
1924 if (options->HSAuthorityRecordStats) {
1925 hs_usage_note_fetch_total(query, time(NULL));
1926 hs_usage_note_fetch_successful(query, time(NULL));
1928 break;
1929 case 0: /* well-formed but not present */
1930 write_http_status_line(conn, 404, "Not found");
1931 /* report (unsuccessful) fetch to statistic */
1932 if (options->HSAuthorityRecordStats) {
1933 hs_usage_note_fetch_total(query, time(NULL));
1935 break;
1936 case -1: /* not well-formed */
1937 write_http_status_line(conn, 400, "Bad request");
1938 break;
1940 tor_free(url);
1941 return 0;
1944 if (!strcmpstart(url,"/tor/bytes.txt")) {
1945 char *bytes = directory_dump_request_log();
1946 size_t len = strlen(bytes);
1947 write_http_response_header(conn, len, "text/plain", NULL, 0);
1948 connection_write_to_buf(bytes, len, TO_CONN(conn));
1949 tor_free(bytes);
1950 tor_free(url);
1951 return 0;
1954 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
1955 rewritten to /tor/robots.txt */
1956 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
1957 size_t len = strlen(robots);
1958 write_http_response_header(conn, len, "text/plain", NULL,
1959 ROBOTS_CACHE_LIFETIME);
1960 connection_write_to_buf(robots, len, TO_CONN(conn));
1961 tor_free(url);
1962 return 0;
1965 if (!strcmp(url,"/tor/dir-all-weaselhack") &&
1966 (conn->_base.addr == 0x7f000001ul) &&
1967 authdir_mode_v2(options) &&
1968 !authdir_mode_bridge(options)) {
1969 /* until weasel rewrites his scripts at noreply */
1970 char *new_directory=NULL;
1972 if (dirserv_dump_directory_to_string(&new_directory,
1973 get_identity_key(), 1)) {
1974 log_warn(LD_BUG, "Error creating full v1 directory.");
1975 tor_free(new_directory);
1976 write_http_status_line(conn, 503, "Directory unavailable");
1977 return 0;
1980 dlen = strlen(new_directory);
1982 write_http_response_header(conn, dlen, "text/plain", "identity", 0);
1984 connection_write_to_buf(new_directory, dlen, TO_CONN(conn));
1985 tor_free(new_directory);
1986 tor_free(url);
1987 return 0;
1990 /* we didn't recognize the url */
1991 write_http_status_line(conn, 404, "Not found");
1992 tor_free(url);
1993 return 0;
1996 /** Helper function: called when a dirserver gets a complete HTTP POST
1997 * request. Look for an uploaded server descriptor or rendezvous
1998 * service descriptor. On finding one, process it and write a
1999 * response into conn-\>outbuf. If the request is unrecognized, send a
2000 * 400. Always return 0. */
2001 static int
2002 directory_handle_command_post(dir_connection_t *conn, const char *headers,
2003 const char *body, size_t body_len)
2005 char *url = NULL;
2006 or_options_t *options = get_options();
2008 log_debug(LD_DIRSERV,"Received POST command.");
2010 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2012 if (!authdir_mode(options)) {
2013 /* we just provide cached directories; we don't want to
2014 * receive anything. */
2015 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
2016 "accept posted server descriptors");
2017 return 0;
2020 if (parse_http_url(headers, &url) < 0) {
2021 write_http_status_line(conn, 400, "Bad request");
2022 return 0;
2024 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2026 if (authdir_mode_handles_descs(options) &&
2027 !strcmp(url,"/tor/")) { /* server descriptor post */
2028 const char *msg = NULL;
2029 uint8_t purpose = authdir_mode_bridge(options) ?
2030 ROUTER_PURPOSE_CONTROLLER : ROUTER_PURPOSE_GENERAL;
2031 int r = dirserv_add_multiple_descriptors(body, purpose, &msg);
2032 tor_assert(msg);
2033 if (r > 0)
2034 dirserv_get_directory(); /* rebuild and write to disk */
2035 switch (r) {
2036 case -2:
2037 case -1:
2038 case 1:
2039 log_notice(LD_DIRSERV,
2040 "Rejected router descriptor or extra-info from %s.",
2041 conn->_base.address);
2042 /* malformed descriptor, or something wrong */
2043 write_http_status_line(conn, 400, msg);
2044 break;
2045 case 0: /* accepted but discarded */
2046 case 2: /* accepted */
2047 write_http_status_line(conn, 200, msg);
2048 break;
2050 goto done;
2053 if (options->HSAuthoritativeDir &&
2054 !strcmpstart(url,"/tor/rendezvous/publish")) {
2055 /* rendezvous descriptor post */
2056 if (rend_cache_store(body, body_len, 1) < 0) {
2057 // char tmp[1024*2+1];
2058 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
2059 "Rejected rend descriptor (length %d) from %s.",
2060 (int)body_len, conn->_base.address);
2061 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
2062 } else {
2063 write_http_status_line(conn, 200, "Service descriptor stored");
2065 goto done;
2068 /* we didn't recognize the url */
2069 write_http_status_line(conn, 404, "Not found");
2071 done:
2072 tor_free(url);
2073 return 0;
2076 /** Called when a dirserver receives data on a directory connection;
2077 * looks for an HTTP request. If the request is complete, remove it
2078 * from the inbuf, try to process it; otherwise, leave it on the
2079 * buffer. Return a 0 on success, or -1 on error.
2081 static int
2082 directory_handle_command(dir_connection_t *conn)
2084 char *headers=NULL, *body=NULL;
2085 size_t body_len=0;
2086 int r;
2088 tor_assert(conn);
2089 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2091 switch (fetch_from_buf_http(conn->_base.inbuf,
2092 &headers, MAX_HEADERS_SIZE,
2093 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
2094 case -1: /* overflow */
2095 log_warn(LD_DIRSERV,
2096 "Invalid input from address '%s'. Closing.",
2097 conn->_base.address);
2098 return -1;
2099 case 0:
2100 log_debug(LD_DIRSERV,"command not all here yet.");
2101 return 0;
2102 /* case 1, fall through */
2105 http_set_address_origin(headers, TO_CONN(conn));
2106 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
2108 if (!strncasecmp(headers,"GET",3))
2109 r = directory_handle_command_get(conn, headers, body, body_len);
2110 else if (!strncasecmp(headers,"POST",4))
2111 r = directory_handle_command_post(conn, headers, body, body_len);
2112 else {
2113 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
2114 "Got headers %s with unknown command. Closing.",
2115 escaped(headers));
2116 r = -1;
2119 tor_free(headers); tor_free(body);
2120 return r;
2123 /** Write handler for directory connections; called when all data has
2124 * been flushed. Close the connection or wait for a response as
2125 * appropriate.
2128 connection_dir_finished_flushing(dir_connection_t *conn)
2130 tor_assert(conn);
2131 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2133 switch (conn->_base.state) {
2134 case DIR_CONN_STATE_CLIENT_SENDING:
2135 log_debug(LD_DIR,"client finished sending command.");
2136 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
2137 connection_stop_writing(TO_CONN(conn));
2138 return 0;
2139 case DIR_CONN_STATE_SERVER_WRITING:
2140 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
2141 connection_mark_for_close(TO_CONN(conn));
2142 return 0;
2143 default:
2144 log_warn(LD_BUG,"called in unexpected state %d.",
2145 conn->_base.state);
2146 tor_fragile_assert();
2147 return -1;
2149 return 0;
2152 /** Connected handler for directory connections: begin sending data to the
2153 * server */
2155 connection_dir_finished_connecting(dir_connection_t *conn)
2157 tor_assert(conn);
2158 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2159 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
2161 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
2162 conn->_base.address,conn->_base.port);
2164 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
2165 return 0;
2168 /** Called when one or more networkstatus fetches have failed (with uppercase
2169 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
2170 * failed once, unless they failed with status code 503. */
2171 static void
2172 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
2174 if (status_code == 503)
2175 return;
2176 SMARTLIST_FOREACH(failed, const char *, fp,
2178 char digest[DIGEST_LEN];
2179 trusted_dir_server_t *dir;
2180 base16_decode(digest, DIGEST_LEN, fp, strlen(fp));
2181 dir = router_get_trusteddirserver_by_digest(digest);
2183 if (dir)
2184 ++dir->n_networkstatus_failures;
2188 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
2189 * fetches have failed (with uppercase fingerprints listed in
2190 * <b>failed</b>). */
2191 static void
2192 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
2193 int was_extrainfo)
2195 char digest[DIGEST_LEN];
2196 time_t now = time(NULL);
2197 int server = server_mode(get_options()) && get_options()->DirPort;
2198 SMARTLIST_FOREACH(failed, const char *, cp,
2200 download_status_t *dls = NULL;
2201 base16_decode(digest, DIGEST_LEN, cp, strlen(cp));
2202 if (was_extrainfo) {
2203 signed_descriptor_t *sd =
2204 router_get_by_extrainfo_digest(digest);
2205 if (sd)
2206 dls = &sd->ei_dl_status;
2207 } else {
2208 local_routerstatus_t *rs =
2209 router_get_combined_status_by_descriptor_digest(digest);
2210 if (rs)
2211 dls = &rs->dl_status;
2213 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
2214 continue;
2215 if (status_code != 503 || server)
2216 ++dls->n_download_failures;
2217 if (server) {
2218 switch (dls->n_download_failures) {
2219 case 0: dls->next_attempt_at = 0; break;
2220 case 1: dls->next_attempt_at = 0; break;
2221 case 2: dls->next_attempt_at = 0; break;
2222 case 3: dls->next_attempt_at = now+60; break;
2223 case 4: dls->next_attempt_at = now+60; break;
2224 case 5: dls->next_attempt_at = now+60*2; break;
2225 case 6: dls->next_attempt_at = now+60*5; break;
2226 case 7: dls->next_attempt_at = now+60*15; break;
2227 default: dls->next_attempt_at = TIME_MAX; break;
2229 } else {
2230 switch (dls->n_download_failures) {
2231 case 0: dls->next_attempt_at = 0; break;
2232 case 1: dls->next_attempt_at = 0; break;
2233 case 2: dls->next_attempt_at = now+60; break;
2234 case 3: dls->next_attempt_at = now+60*5; break;
2235 case 4: dls->next_attempt_at = now+60*10; break;
2236 default: dls->next_attempt_at = TIME_MAX; break;
2239 if (dls->next_attempt_at == 0)
2240 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
2241 cp, (int)dls->n_download_failures);
2242 else if (dls->next_attempt_at < TIME_MAX)
2243 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
2244 cp, (int)dls->n_download_failures,
2245 (int)(dls->next_attempt_at-now));
2246 else
2247 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
2248 cp, (int)dls->n_download_failures);
2251 /* No need to relaunch descriptor downloads here: we already do it
2252 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
2255 /** Given a directory <b>resource</b> request, containing zero
2256 * or more strings separated by plus signs, followed optionally by ".z", store
2257 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
2258 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
2259 * decode_hex is true, then delete all elements that aren't hex digests, and
2260 * decode the rest. If sort_uniq is true, then sort the list and remove
2261 * all duplicates.
2264 dir_split_resource_into_fingerprints(const char *resource,
2265 smartlist_t *fp_out, int *compressed_out,
2266 int decode_hex, int sort_uniq)
2268 smartlist_t *fp_tmp = smartlist_create();
2269 tor_assert(fp_out);
2270 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
2271 if (compressed_out)
2272 *compressed_out = 0;
2273 if (smartlist_len(fp_tmp)) {
2274 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
2275 size_t last_len = strlen(last);
2276 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
2277 last[last_len-2] = '\0';
2278 if (compressed_out)
2279 *compressed_out = 1;
2282 if (decode_hex) {
2283 int i;
2284 char *cp, *d = NULL;
2285 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
2286 cp = smartlist_get(fp_tmp, i);
2287 if (strlen(cp) != HEX_DIGEST_LEN) {
2288 log_info(LD_DIR,
2289 "Skipping digest %s with non-standard length.", escaped(cp));
2290 smartlist_del_keeporder(fp_tmp, i--);
2291 goto again;
2293 d = tor_malloc_zero(DIGEST_LEN);
2294 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
2295 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
2296 smartlist_del_keeporder(fp_tmp, i--);
2297 goto again;
2299 smartlist_set(fp_tmp, i, d);
2300 d = NULL;
2301 again:
2302 tor_free(cp);
2303 tor_free(d);
2306 if (sort_uniq) {
2307 smartlist_t *fp_tmp2 = smartlist_create();
2308 int i;
2309 if (decode_hex)
2310 smartlist_sort_digests(fp_tmp);
2311 else
2312 smartlist_sort_strings(fp_tmp);
2313 if (smartlist_len(fp_tmp))
2314 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
2315 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
2316 char *cp = smartlist_get(fp_tmp, i);
2317 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
2319 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
2320 || (!decode_hex && strcasecmp(cp, last)))
2321 smartlist_add(fp_tmp2, cp);
2322 else
2323 tor_free(cp);
2325 smartlist_free(fp_tmp);
2326 fp_tmp = fp_tmp2;
2328 smartlist_add_all(fp_out, fp_tmp);
2329 smartlist_free(fp_tmp);
2330 return 0;