Be clearer on the various roles for auth dir types.
[tor.git] / src / or / directory.c
bloba0ed7393ed1e46b9b1ea792ad724da21b495e997
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, post_via_tor,
181 NULL, payload, upload_len);
183 if (!found) {
184 char *s = authority_type_to_string(type);
185 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
186 "of type '%s', but no authorities of that type listed!", s);
187 tor_free(s);
191 /** Start a connection to a random running directory server, using
192 * connection purpose 'purpose' and requesting 'resource'.
193 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
194 * down, mark them up and try again.
196 void
197 directory_get_from_dirserver(uint8_t purpose, const char *resource,
198 int retry_if_no_servers)
200 routerstatus_t *rs = NULL;
201 or_options_t *options = get_options();
202 int prefer_authority = server_mode(options) && options->DirPort != 0;
203 int directconn = !purpose_needs_anonymity(purpose);
204 authority_type_t type;
206 /* FFFF we could break this switch into its own function, and call
207 * it elsewhere in directory.c. -RD */
208 switch (purpose) {
209 case DIR_PURPOSE_FETCH_EXTRAINFO:
210 type = EXTRAINFO_CACHE | V2_AUTHORITY;
211 break;
212 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
213 case DIR_PURPOSE_FETCH_SERVERDESC:
214 type = V2_AUTHORITY;
215 break;
216 case DIR_PURPOSE_FETCH_DIR:
217 case DIR_PURPOSE_FETCH_RUNNING_LIST:
218 type = V1_AUTHORITY;
219 break;
220 case DIR_PURPOSE_FETCH_RENDDESC:
221 type = HIDSERV_AUTHORITY;
222 break;
223 default:
224 log_warn(LD_BUG, "Unexpected purpose %d", (int)purpose);
225 return;
228 if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
229 return;
231 if (directconn) {
232 if (prefer_authority) {
233 /* only ask authdirservers, and don't ask myself */
234 rs = router_pick_trusteddirserver(type, 1, 1,
235 retry_if_no_servers);
237 if (!rs) {
238 /* anybody with a non-zero dirport will do */
239 rs = router_pick_directory_server(1, 1, type,
240 retry_if_no_servers);
241 if (!rs) {
242 const char *which;
243 if (purpose == DIR_PURPOSE_FETCH_DIR)
244 which = "directory";
245 else if (purpose == DIR_PURPOSE_FETCH_RUNNING_LIST)
246 which = "status list";
247 else if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
248 which = "network status";
249 else // if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
250 which = "server descriptors";
251 log_info(LD_DIR,
252 "No router found for %s; falling back to dirserver list",
253 which);
254 rs = router_pick_trusteddirserver(type, 1, 1,
255 retry_if_no_servers);
256 if (!rs)
257 directconn = 0; /* last resort: try routing it via Tor */
261 if (!directconn) {
262 /* Never use fascistfirewall; we're going via Tor. */
263 if (purpose == DIR_PURPOSE_FETCH_RENDDESC) {
264 /* only ask hidserv authorities, any of them will do */
265 rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, 0, 0,
266 retry_if_no_servers);
267 } else {
268 /* anybody with a non-zero dirport will do. Disregard firewalls. */
269 rs = router_pick_directory_server(1, 0, type,
270 retry_if_no_servers);
271 /* If we have any hope of building an indirect conn, we know some router
272 * descriptors. If (rs==NULL), we can't build circuits anyway, so
273 * there's no point in falling back to the authorities in this case. */
277 if (rs)
278 directory_initiate_command_routerstatus(rs, purpose, !directconn,
279 resource, NULL, 0);
280 else {
281 log_notice(LD_DIR,
282 "While fetching directory info, "
283 "no running dirservers known. Will try again later. "
284 "(purpose %d)", purpose);
285 if (!purpose_needs_anonymity(purpose)) {
286 /* remember we tried them all and failed. */
287 directory_all_unreachable(time(NULL));
292 /** Launch a new connection to the directory server <b>status</b> to upload or
293 * download a server or rendezvous descriptor. <b>purpose</b> determines what
294 * kind of directory connection we're launching, and must be one of
295 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
297 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
298 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
300 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
301 * want to fetch.
303 void
304 directory_initiate_command_routerstatus(routerstatus_t *status,
305 uint8_t purpose,
306 int anonymized_connection,
307 const char *resource,
308 const char *payload,
309 size_t payload_len)
311 routerinfo_t *router;
312 char address_buf[INET_NTOA_BUF_LEN+1];
313 struct in_addr in;
314 const char *address;
315 if ((router = router_get_by_digest(status->identity_digest))) {
316 address = router->address;
317 } else {
318 in.s_addr = htonl(status->addr);
319 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
320 address = address_buf;
322 directory_initiate_command(address, status->addr,
323 status->or_port, status->dir_port,
324 status->version_supports_begindir,
325 status->identity_digest,
326 purpose, anonymized_connection, resource,
327 payload, payload_len);
330 /** Return true iff <b>conn</b> is the client side of a directory connection
331 * we launched to ourself in order to determine the reachability of our
332 * dir_port. */
333 static int
334 directory_conn_is_self_reachability_test(dir_connection_t *conn)
336 if (conn->requested_resource &&
337 !strcmpstart(conn->requested_resource,"authority")) {
338 routerinfo_t *me = router_get_my_routerinfo();
339 if (me &&
340 router_digest_is_me(conn->identity_digest) &&
341 me->addr == conn->_base.addr &&
342 me->dir_port == conn->_base.port)
343 return 1;
345 return 0;
348 /** Called when we are unable to complete the client's request to a directory
349 * server due to a network error: Mark the router as down and try again if
350 * possible.
352 void
353 connection_dir_request_failed(dir_connection_t *conn)
355 if (directory_conn_is_self_reachability_test(conn)) {
356 routerinfo_t *me = router_get_my_routerinfo();
357 if (me)
358 control_event_server_status(LOG_WARN,
359 "REACHABILITY_FAILED DIRADDRESS=%s:%d",
360 me->address, me->dir_port);
361 return; /* this was a test fetch. don't retry. */
363 router_set_status(conn->identity_digest, 0); /* don't try him again */
364 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR ||
365 conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
366 log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
367 conn->_base.address, conn->_base.port);
368 directory_get_from_dirserver(conn->_base.purpose, NULL,
369 0 /* don't retry_if_no_servers */);
370 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
371 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
372 conn->_base.address);
373 connection_dir_download_networkstatus_failed(conn, -1);
374 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
375 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
376 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
377 conn->_base.address);
378 connection_dir_download_routerdesc_failed(conn);
382 /** Called when an attempt to download one or more network status
383 * documents on connection <b>conn</b> failed. Decide whether to
384 * retry the fetch now, later, or never.
386 static void
387 connection_dir_download_networkstatus_failed(dir_connection_t *conn,
388 int status_code)
390 if (!conn->requested_resource) {
391 /* We never reached directory_send_command, which means that we never
392 * opened a network connection. Either we're out of sockets, or the
393 * network is down. Either way, retrying would be pointless. */
394 return;
396 if (!strcmpstart(conn->requested_resource, "all")) {
397 /* We're a non-authoritative directory cache; try again. Ignore status
398 * code, since we don't want to keep trying forever in a tight loop
399 * if all the authorities are shutting us out. */
400 smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
401 SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
402 ++ds->n_networkstatus_failures);
403 directory_get_from_dirserver(conn->_base.purpose, "all.z",
404 0 /* don't retry_if_no_servers */);
405 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
406 /* We were trying to download by fingerprint; mark them all as having
407 * failed, and possibly retry them later.*/
408 smartlist_t *failed = smartlist_create();
409 dir_split_resource_into_fingerprints(conn->requested_resource+3,
410 failed, NULL, 0, 0);
411 if (smartlist_len(failed)) {
412 dir_networkstatus_download_failed(failed, status_code);
413 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
415 smartlist_free(failed);
419 /** Called when an attempt to download one or more router descriptors
420 * or extra-info documents on connection <b>conn</b> failed.
422 static void
423 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
425 /* No need to increment the failure count for routerdescs, since
426 * it's not their fault. */
428 /* No need to relaunch descriptor downloads here: we already do it
429 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
430 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
431 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
433 (void) conn;
436 /** Helper for directory_initiate_command_(router|trusted_dir): send the
437 * command to a server whose address is <b>address</b>, whose IP is
438 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
439 * <b>supports_begindir</b>, and whose identity key digest is
440 * <b>digest</b>. */
441 void
442 directory_initiate_command(const char *address, uint32_t addr,
443 uint16_t or_port, uint16_t dir_port,
444 int supports_begindir,
445 const char *digest, uint8_t purpose,
446 int anonymized_connection, const char *resource,
447 const char *payload, size_t payload_len)
449 dir_connection_t *conn;
450 or_options_t *options = get_options();
451 int want_to_tunnel = options->TunnelDirConns && supports_begindir &&
452 !anonymized_connection && or_port &&
453 fascist_firewall_allows_address_or(addr, or_port);
455 tor_assert(address);
456 tor_assert(addr);
457 tor_assert(dir_port);
458 tor_assert(digest);
460 log_debug(LD_DIR, "anonymized %d, want_to_tunnel %d.",
461 anonymized_connection, want_to_tunnel);
463 switch (purpose) {
464 case DIR_PURPOSE_FETCH_DIR:
465 log_debug(LD_DIR,"initiating directory fetch");
466 break;
467 case DIR_PURPOSE_FETCH_RENDDESC:
468 log_debug(LD_DIR,"initiating hidden-service descriptor fetch");
469 break;
470 case DIR_PURPOSE_UPLOAD_DIR:
471 log_debug(LD_OR,"initiating server descriptor upload");
472 break;
473 case DIR_PURPOSE_UPLOAD_RENDDESC:
474 log_debug(LD_REND,"initiating hidden-service descriptor upload");
475 break;
476 case DIR_PURPOSE_FETCH_RUNNING_LIST:
477 log_debug(LD_DIR,"initiating running-routers fetch");
478 break;
479 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
480 log_debug(LD_DIR,"initiating network-status fetch");
481 break;
482 case DIR_PURPOSE_FETCH_SERVERDESC:
483 log_debug(LD_DIR,"initiating server descriptor fetch");
484 break;
485 case DIR_PURPOSE_FETCH_EXTRAINFO:
486 log_debug(LD_DIR,"initiating extra-info fetch");
487 break;
488 default:
489 log_err(LD_BUG, "Unrecognized directory connection purpose.");
490 tor_assert(0);
493 conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
495 /* set up conn so it's got all the data we need to remember */
496 conn->_base.addr = addr;
497 conn->_base.port = want_to_tunnel ? or_port : dir_port;
498 conn->_base.address = tor_strdup(address);
499 memcpy(conn->identity_digest, digest, DIGEST_LEN);
501 conn->_base.purpose = purpose;
503 /* give it an initial state */
504 conn->_base.state = DIR_CONN_STATE_CONNECTING;
506 if (!anonymized_connection && !want_to_tunnel) {
507 /* then we want to connect directly */
509 conn->dirconn_direct = 1;
510 if (options->HttpProxy) {
511 addr = options->HttpProxyAddr;
512 dir_port = options->HttpProxyPort;
515 switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
516 dir_port)) {
517 case -1:
518 connection_dir_request_failed(conn); /* retry if we want */
519 connection_free(TO_CONN(conn));
520 return;
521 case 1:
522 /* start flushing conn */
523 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
524 /* fall through */
525 case 0:
526 /* queue the command on the outbuf */
527 directory_send_command(conn, purpose, 1, resource,
528 payload, payload_len);
529 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
530 /* writable indicates finish, readable indicates broken link,
531 error indicates broken link in windowsland. */
533 } else { /* we want to connect via tor */
534 edge_connection_t *linked_conn;
535 /* make an AP connection
536 * populate it and add it at the right state
537 * hook up both sides
539 conn->dirconn_direct = 0;
540 linked_conn =
541 connection_ap_make_link(conn->_base.address, conn->_base.port,
542 digest,
543 anonymized_connection ?
544 SOCKS_COMMAND_CONNECT :
545 SOCKS_COMMAND_CONNECT_DIR);
546 if (!linked_conn) {
547 log_warn(LD_NET,"Making tunnel to dirserver failed.");
548 connection_mark_for_close(TO_CONN(conn));
549 return;
551 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
553 if (connection_add(TO_CONN(conn)) < 0) {
554 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
555 connection_mark_for_close(TO_CONN(conn));
556 return;
558 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
559 /* queue the command on the outbuf */
560 directory_send_command(conn, purpose, 0, resource,
561 payload, payload_len);
562 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
563 connection_start_reading(TO_CONN(linked_conn));
567 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
568 * are as in directory_initiate_command.
570 static void
571 directory_send_command(dir_connection_t *conn,
572 int purpose, int direct, const char *resource,
573 const char *payload, size_t payload_len)
575 char proxystring[256];
576 char proxyauthstring[256];
577 char hoststring[128];
578 char *url;
579 char request[8192];
580 const char *httpcommand = NULL;
581 size_t len;
583 tor_assert(conn);
584 tor_assert(conn->_base.type == CONN_TYPE_DIR);
586 tor_free(conn->requested_resource);
587 if (resource)
588 conn->requested_resource = tor_strdup(resource);
590 /* come up with a string for which Host: we want */
591 if (conn->_base.port == 80) {
592 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
593 } else {
594 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
595 conn->_base.address, conn->_base.port);
598 /* come up with some proxy lines, if we're using one. */
599 if (direct && get_options()->HttpProxy) {
600 char *base64_authenticator=NULL;
601 const char *authenticator = get_options()->HttpProxyAuthenticator;
603 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
604 if (authenticator) {
605 base64_authenticator = alloc_http_authenticator(authenticator);
606 if (!base64_authenticator)
607 log_warn(LD_BUG, "Encoding http authenticator failed");
609 if (base64_authenticator) {
610 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
611 "\r\nProxy-Authorization: Basic %s",
612 base64_authenticator);
613 tor_free(base64_authenticator);
614 } else {
615 proxyauthstring[0] = 0;
617 } else {
618 proxystring[0] = 0;
619 proxyauthstring[0] = 0;
622 switch (purpose) {
623 case DIR_PURPOSE_FETCH_DIR:
624 tor_assert(!resource);
625 tor_assert(!payload);
626 httpcommand = "GET";
627 url = tor_strdup("/tor/dir.z");
628 break;
629 case DIR_PURPOSE_FETCH_RUNNING_LIST:
630 tor_assert(!resource);
631 tor_assert(!payload);
632 httpcommand = "GET";
633 url = tor_strdup("/tor/running-routers");
634 break;
635 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
636 httpcommand = "GET";
637 len = strlen(resource)+32;
638 url = tor_malloc(len);
639 tor_snprintf(url, len, "/tor/status/%s", resource);
640 break;
641 case DIR_PURPOSE_FETCH_SERVERDESC:
642 httpcommand = "GET";
643 len = strlen(resource)+32;
644 url = tor_malloc(len);
645 tor_snprintf(url, len, "/tor/server/%s", resource);
646 break;
647 case DIR_PURPOSE_FETCH_EXTRAINFO:
648 httpcommand = "GET";
649 len = strlen(resource)+32;
650 url = tor_malloc(len);
651 tor_snprintf(url, len, "/tor/extra/%s", resource);
652 break;
653 case DIR_PURPOSE_UPLOAD_DIR:
654 tor_assert(!resource);
655 tor_assert(payload);
656 httpcommand = "POST";
657 url = tor_strdup("/tor/");
658 break;
659 case DIR_PURPOSE_FETCH_RENDDESC:
660 tor_assert(resource);
661 tor_assert(!payload);
663 /* this must be true or we wouldn't be doing the lookup */
664 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN);
665 /* This breaks the function abstraction. */
666 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
668 httpcommand = "GET";
669 /* Request the most recent versioned descriptor. */
670 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
671 // but that never got testing, and it wasn't a good design.)
672 len = strlen(resource)+32;
673 url = tor_malloc(len);
674 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
675 break;
676 case DIR_PURPOSE_UPLOAD_RENDDESC:
677 tor_assert(!resource);
678 tor_assert(payload);
679 httpcommand = "POST";
680 url = tor_strdup("/tor/rendezvous/publish");
681 break;
682 default:
683 tor_assert(0);
684 return;
687 if (strlen(proxystring) + strlen(url) >= 4096) {
688 log_warn(LD_BUG,
689 "Squid does not like URLs longer than 4095 bytes, and this "
690 "one is %d bytes long: %s%s",
691 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
694 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
695 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
696 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
697 tor_free(url);
699 if (!strcmp(httpcommand, "GET") && !payload) {
700 tor_snprintf(request, sizeof(request),
701 " HTTP/1.0\r\nHost: %s%s\r\n\r\n",
702 hoststring,
703 proxyauthstring);
704 } else {
705 tor_snprintf(request, sizeof(request),
706 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
707 payload ? (unsigned long)payload_len : 0,
708 hoststring,
709 proxyauthstring);
711 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
713 if (payload) {
714 /* then send the payload afterwards too */
715 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
719 /** Parse an HTTP request string <b>headers</b> of the form
720 * \verbatim
721 * "\%s [http[s]://]\%s HTTP/1..."
722 * \endverbatim
723 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
724 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
725 * so it does. Return 0.
726 * Otherwise, return -1.
728 static int
729 parse_http_url(const char *headers, char **url)
731 char *s, *start, *tmp;
733 s = (char *)eat_whitespace_no_nl(headers);
734 if (!*s) return -1;
735 s = (char *)find_whitespace(s); /* get past GET/POST */
736 if (!*s) return -1;
737 s = (char *)eat_whitespace_no_nl(s);
738 if (!*s) return -1;
739 start = s; /* this is it, assuming it's valid */
740 s = (char *)find_whitespace(start);
741 if (!*s) return -1;
743 /* tolerate the http[s] proxy style of putting the hostname in the url */
744 if (s-start >= 4 && !strcmpstart(start,"http")) {
745 tmp = start + 4;
746 if (*tmp == 's')
747 tmp++;
748 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
749 tmp = strchr(tmp+3, '/');
750 if (tmp && tmp < s) {
751 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
752 start = tmp;
757 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
758 *url = tor_malloc(s - start + 5);
759 strlcpy(*url,"/tor", s-start+5);
760 strlcat((*url)+4, start, s-start+1);
761 } else {
762 *url = tor_strndup(start, s-start);
764 return 0;
767 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
768 * <b>which</b>. The key should be given with a terminating colon and space;
769 * this function copies everything after, up to but not including the
770 * following \\r\\n. */
771 static char *
772 http_get_header(const char *headers, const char *which)
774 const char *cp = headers;
775 while (cp) {
776 if (!strcmpstart(cp, which)) {
777 char *eos;
778 cp += strlen(which);
779 if ((eos = strchr(cp,'\r')))
780 return tor_strndup(cp, eos-cp);
781 else
782 return tor_strdup(cp);
784 cp = strchr(cp, '\n');
785 if (cp)
786 ++cp;
788 return NULL;
791 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
792 * <b>conn</b>-\>address to describe our best guess of the address that
793 * originated this HTTP request. */
794 static void
795 http_set_address_origin(const char *headers, connection_t *conn)
797 char *fwd;
799 fwd = http_get_header(headers, "Forwarded-For: ");
800 if (!fwd)
801 fwd = http_get_header(headers, "X-Forwarded-For: ");
802 if (fwd) {
803 struct in_addr in;
804 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
805 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
806 escaped(fwd));
807 tor_free(fwd);
808 return;
810 tor_free(conn->address);
811 conn->address = tor_strdup(fwd);
812 tor_free(fwd);
816 /** Parse an HTTP response string <b>headers</b> of the form
817 * \verbatim
818 * "HTTP/1.\%d \%d\%s\r\n...".
819 * \endverbatim
821 * If it's well-formed, assign the status code to *<b>code</b> and
822 * return 0. Otherwise, return -1.
824 * On success: If <b>date</b> is provided, set *date to the Date
825 * header in the http headers, or 0 if no such header is found. If
826 * <b>compression</b> is provided, set *<b>compression</b> to the
827 * compression method given in the Content-Encoding header, or 0 if no
828 * such header is found, or -1 if the value of the header is not
829 * recognized. If <b>reason</b> is provided, strdup the reason string
830 * into it.
833 parse_http_response(const char *headers, int *code, time_t *date,
834 compress_method_t *compression, char **reason)
836 int n1, n2;
837 char datestr[RFC1123_TIME_LEN+1];
838 smartlist_t *parsed_headers;
839 tor_assert(headers);
840 tor_assert(code);
842 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
844 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
845 (n1 != 0 && n1 != 1) ||
846 (n2 < 100 || n2 >= 600)) {
847 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
848 return -1;
850 *code = n2;
852 parsed_headers = smartlist_create();
853 smartlist_split_string(parsed_headers, headers, "\n",
854 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
855 if (reason) {
856 smartlist_t *status_line_elements = smartlist_create();
857 tor_assert(smartlist_len(parsed_headers));
858 smartlist_split_string(status_line_elements,
859 smartlist_get(parsed_headers, 0),
860 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
861 tor_assert(smartlist_len(status_line_elements) <= 3);
862 if (smartlist_len(status_line_elements) == 3) {
863 *reason = smartlist_get(status_line_elements, 2);
864 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
866 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
867 smartlist_free(status_line_elements);
869 if (date) {
870 *date = 0;
871 SMARTLIST_FOREACH(parsed_headers, const char *, s,
872 if (!strcmpstart(s, "Date: ")) {
873 strlcpy(datestr, s+6, sizeof(datestr));
874 /* This will do nothing on failure, so we don't need to check
875 the result. We shouldn't warn, since there are many other valid
876 date formats besides the one we use. */
877 parse_rfc1123_time(datestr, date);
878 break;
881 if (compression) {
882 const char *enc = NULL;
883 SMARTLIST_FOREACH(parsed_headers, const char *, s,
884 if (!strcmpstart(s, "Content-Encoding: ")) {
885 enc = s+18; break;
887 if (!enc || !strcmp(enc, "identity")) {
888 *compression = NO_METHOD;
889 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
890 *compression = ZLIB_METHOD;
891 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
892 *compression = GZIP_METHOD;
893 } else {
894 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
895 escaped(enc));
896 *compression = UNKNOWN_METHOD;
899 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
900 smartlist_free(parsed_headers);
902 return 0;
905 /** Return true iff <b>body</b> doesn't start with a plausible router or
906 * running-list or directory opening. This is a sign of possible compression.
908 static int
909 body_is_plausible(const char *body, size_t len, int purpose)
911 int i;
912 if (len == 0)
913 return 1; /* empty bodies don't need decompression */
914 if (len < 32)
915 return 0;
916 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
917 if (!strcmpstart(body,"router") ||
918 !strcmpstart(body,"signed-directory") ||
919 !strcmpstart(body,"network-status") ||
920 !strcmpstart(body,"running-routers"))
921 return 1;
922 for (i=0;i<32;++i) {
923 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
924 return 0;
926 return 1;
927 } else {
928 return 1;
932 /** We are a client, and we've finished reading the server's
933 * response. Parse and it and act appropriately.
935 * If we're still happy with using this directory server in the future, return
936 * 0. Otherwise return -1; and the caller should consider trying the request
937 * again.
939 * The caller will take care of marking the connection for close.
941 static int
942 connection_dir_client_reached_eof(dir_connection_t *conn)
944 char *body;
945 char *headers;
946 char *reason = NULL;
947 size_t body_len=0, orig_len=0;
948 int status_code;
949 time_t date_header=0;
950 int delta;
951 compress_method_t compression;
952 int plausible;
953 int skewed=0;
954 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
955 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
956 int was_compressed=0;
957 time_t now = time(NULL);
959 switch (fetch_from_buf_http(conn->_base.inbuf,
960 &headers, MAX_HEADERS_SIZE,
961 &body, &body_len, MAX_DIR_DL_SIZE,
962 allow_partial)) {
963 case -1: /* overflow */
964 log_warn(LD_PROTOCOL,
965 "'fetch' response too large (server '%s:%d'). Closing.",
966 conn->_base.address, conn->_base.port);
967 return -1;
968 case 0:
969 log_info(LD_HTTP,
970 "'fetch' response not all here, but we're at eof. Closing.");
971 return -1;
972 /* case 1, fall through */
974 orig_len = body_len;
976 if (parse_http_response(headers, &status_code, &date_header,
977 &compression, &reason) < 0) {
978 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
979 conn->_base.address, conn->_base.port);
980 tor_free(body); tor_free(headers);
981 return -1;
983 if (!reason) reason = tor_strdup("[no reason given]");
985 log_debug(LD_DIR,
986 "Received response from directory server '%s:%d': %d %s",
987 conn->_base.address, conn->_base.port, status_code,
988 escaped(reason));
990 /* now check if it's got any hints for us about our IP address. */
991 if (conn->dirconn_direct) {
992 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
993 if (guess) {
994 router_new_address_suggestion(guess);
995 tor_free(guess);
999 if (date_header > 0) {
1000 /* The date header was written very soon after we sent our request,
1001 * so compute the skew as the difference between sending the request
1002 * and the date header. (We used to check now-date_header, but that's
1003 * inaccurate if we spend a lot of time downloading.)
1005 delta = conn->_base.timestamp_lastwritten - date_header;
1006 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1007 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1008 log_fn(trusted ? LOG_WARN : LOG_INFO,
1009 LD_HTTP,
1010 "Received directory with skewed time (server '%s:%d'): "
1011 "we are %d minutes %s, or the directory is %d minutes %s.",
1012 conn->_base.address, conn->_base.port,
1013 abs(delta)/60, delta>0 ? "ahead" : "behind",
1014 abs(delta)/60, delta>0 ? "behind" : "ahead");
1015 skewed = 1; /* don't check the recommended-versions line */
1016 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1017 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
1018 delta, conn->_base.address, conn->_base.port);
1019 } else {
1020 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1021 "we are %d seconds skewed. (That's okay.)", delta);
1024 (void) skewed; /* skewed isn't used yet. */
1026 if (status_code == 503) {
1027 local_routerstatus_t *rs;
1028 trusted_dir_server_t *ds;
1029 log_info(LD_DIR,"Received http status code %d (%s) from server "
1030 "'%s:%d'. I'll try again soon.",
1031 status_code, escaped(reason), conn->_base.address,
1032 conn->_base.port);
1033 if ((rs = router_get_combined_status_by_digest(conn->identity_digest)))
1034 rs->last_dir_503_at = now;
1035 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1036 ds->fake_status.last_dir_503_at = now;
1038 tor_free(body); tor_free(headers); tor_free(reason);
1039 return -1;
1042 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1043 if (compression != NO_METHOD || !plausible) {
1044 char *new_body = NULL;
1045 size_t new_len = 0;
1046 compress_method_t guessed = detect_compression_method(body, body_len);
1047 if (compression == UNKNOWN_METHOD || guessed != compression) {
1048 /* Tell the user if we don't believe what we're told about compression.*/
1049 const char *description1, *description2;
1050 if (compression == ZLIB_METHOD)
1051 description1 = "as deflated";
1052 else if (compression == GZIP_METHOD)
1053 description1 = "as gzipped";
1054 else if (compression == NO_METHOD)
1055 description1 = "as uncompressed";
1056 else
1057 description1 = "with an unknown Content-Encoding";
1058 if (guessed == ZLIB_METHOD)
1059 description2 = "deflated";
1060 else if (guessed == GZIP_METHOD)
1061 description2 = "gzipped";
1062 else if (!plausible)
1063 description2 = "confusing binary junk";
1064 else
1065 description2 = "uncompressed";
1067 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1068 "but it seems to be %s.%s",
1069 conn->_base.address, conn->_base.port, description1,
1070 description2,
1071 (compression>0 && guessed>0)?" Trying both.":"");
1073 /* Try declared compression first if we can. */
1074 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1075 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1076 !allow_partial, LOG_PROTOCOL_WARN);
1077 /* Okay, if that didn't work, and we think that it was compressed
1078 * differently, try that. */
1079 if (!new_body &&
1080 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1081 compression != guessed)
1082 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1083 !allow_partial, LOG_PROTOCOL_WARN);
1084 /* If we're pretty sure that we have a compressed directory, and
1085 * we didn't manage to uncompress it, then warn and bail. */
1086 if (!plausible && !new_body) {
1087 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1088 "Unable to decompress HTTP body (server '%s:%d').",
1089 conn->_base.address, conn->_base.port);
1090 tor_free(body); tor_free(headers); tor_free(reason);
1091 return -1;
1093 if (new_body) {
1094 tor_free(body);
1095 body = new_body;
1096 body_len = new_len;
1097 was_compressed = 1;
1101 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
1102 /* fetch/process the directory to cache it. */
1103 log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
1104 (int)body_len, conn->_base.address, conn->_base.port);
1105 if (status_code != 200) {
1106 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1107 "'%s:%d' while fetching directory. I'll try again soon.",
1108 status_code, escaped(reason), conn->_base.address,
1109 conn->_base.port);
1110 tor_free(body); tor_free(headers); tor_free(reason);
1111 return -1;
1113 if (router_parse_directory(body) < 0) {
1114 log_notice(LD_DIR,"I failed to parse the directory I fetched from "
1115 "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
1117 note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
1120 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
1121 /* just update our list of running routers, if this list is new info */
1122 log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
1123 if (status_code != 200) {
1124 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1125 "'%s:%d' while fetching running-routers. I'll try again soon.",
1126 status_code, escaped(reason), conn->_base.address,
1127 conn->_base.port);
1128 tor_free(body); tor_free(headers); tor_free(reason);
1129 return -1;
1131 if (router_parse_runningrouters(body)<0) {
1132 log_warn(LD_DIR,
1133 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1134 conn->_base.address, conn->_base.port);
1135 tor_free(body); tor_free(headers); tor_free(reason);
1136 return -1;
1138 note_request(was_compressed?"dl/running-routers.z":
1139 "dl/running-routers", orig_len);
1142 if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
1143 smartlist_t *which = NULL;
1144 networkstatus_source_t source;
1145 char *cp;
1146 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1147 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1148 if (status_code != 200) {
1149 /* XXXX020 This warning tends to freak out clients who get a 403. */
1150 log_warn(LD_DIR,
1151 "Received http status code %d (%s) from server "
1152 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1153 status_code, escaped(reason), conn->_base.address,
1154 conn->_base.port, conn->requested_resource);
1155 tor_free(body); tor_free(headers); tor_free(reason);
1156 connection_dir_download_networkstatus_failed(conn, status_code);
1157 return -1;
1159 note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
1160 if (conn->requested_resource &&
1161 !strcmpstart(conn->requested_resource,"fp/")) {
1162 source = NS_FROM_DIR_BY_FP;
1163 which = smartlist_create();
1164 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1165 which, NULL, 0, 0);
1166 } else if (conn->requested_resource &&
1167 !strcmpstart(conn->requested_resource, "all")) {
1168 source = NS_FROM_DIR_ALL;
1169 which = smartlist_create();
1170 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1171 trusted_dir_server_t *, ds,
1173 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1174 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1175 smartlist_add(which, hex);
1177 } else {
1178 /* Can we even end up here? -- weasel*/
1179 source = NS_FROM_DIR_BY_FP;
1180 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1181 "for it by fp, nor did we ask for all.");
1183 cp = body;
1184 while (*cp) {
1185 char *next = strstr(cp, "\nnetwork-status-version");
1186 if (next)
1187 next[1] = '\0';
1188 /* learn from it, and then remove it from 'which' */
1189 if (router_set_networkstatus(cp, now, source, which)<0)
1190 break;
1191 if (next) {
1192 next[1] = 'n';
1193 cp = next+1;
1194 } else
1195 break;
1197 routers_update_all_from_networkstatus(now); /*launches router downloads*/
1198 directory_info_has_arrived(now, 0);
1199 if (which) {
1200 if (smartlist_len(which)) {
1201 dir_networkstatus_download_failed(which, status_code);
1203 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1204 smartlist_free(which);
1208 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1209 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1210 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1211 smartlist_t *which = NULL;
1212 int n_asked_for = 0;
1213 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1214 was_ei ? "server info" : "extra server info",
1215 (int)body_len, conn->_base.address, conn->_base.port);
1216 if (was_ei)
1217 note_request(was_compressed?"dl/extra.z":"dl/extra", orig_len);
1218 else
1219 note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
1220 if (conn->requested_resource &&
1221 !strcmpstart(conn->requested_resource,"d/")) {
1222 which = smartlist_create();
1223 dir_split_resource_into_fingerprints(conn->requested_resource+2,
1224 which, NULL, 0, 0);
1225 n_asked_for = smartlist_len(which);
1227 if (status_code != 200) {
1228 int dir_okay = status_code == 404 ||
1229 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1230 /* 404 means that it didn't have them; no big deal.
1231 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1232 /* XXXX020 This warning tends to freak out clients who get a 403. */
1233 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1234 "Received http status code %d (%s) from server '%s:%d' "
1235 "while fetching \"/tor/server/%s\". I'll try again soon.",
1236 status_code, escaped(reason), conn->_base.address,
1237 conn->_base.port, conn->requested_resource);
1238 if (!which) {
1239 connection_dir_download_routerdesc_failed(conn);
1240 } else {
1241 dir_routerdesc_download_failed(which, status_code, was_ei);
1242 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1243 smartlist_free(which);
1245 tor_free(body); tor_free(headers); tor_free(reason);
1246 return dir_okay ? 0 : -1;
1248 /* Learn the routers, assuming we requested by fingerprint or "all".
1249 * Right now, we only use "authority" to fetch ourself, so we don't want
1250 * to risk replacing ourself with a router running at the addr:port we
1251 * think we have.
1253 if (which || (conn->requested_resource &&
1254 !strcmpstart(conn->requested_resource, "all"))) {
1255 /* as we learn from them, we remove them from 'which' */
1256 if (was_ei) {
1257 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which);
1258 } else {
1259 router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which);
1260 directory_info_has_arrived(now, 0);
1263 if (which) { /* mark remaining ones as failed */
1264 log_info(LD_DIR, "Received %d/%d routers requested from %s:%d",
1265 n_asked_for-smartlist_len(which), n_asked_for,
1266 conn->_base.address, (int)conn->_base.port);
1267 if (smartlist_len(which)) {
1268 dir_routerdesc_download_failed(which, status_code, was_ei);
1270 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1271 smartlist_free(which);
1273 if (directory_conn_is_self_reachability_test(conn))
1274 router_dirport_found_reachable();
1277 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1278 switch (status_code) {
1279 case 200: {
1280 int all_done = 1;
1281 trusted_dir_server_t *ds =
1282 router_get_trusteddirserver_by_digest(conn->identity_digest);
1283 smartlist_t *servers;
1284 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1285 "descriptor: finished.");
1286 control_event_server_status(
1287 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1288 conn->_base.address, conn->_base.port);
1290 ds->has_accepted_serverdesc = 1;
1291 servers = router_get_trusted_dir_servers();
1292 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
1293 if ((d->type & (V1_AUTHORITY|V2_AUTHORITY)) &&
1294 !d->has_accepted_serverdesc) {
1295 all_done = 0;
1296 break;
1299 if (all_done)
1300 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1302 break;
1303 case 400:
1304 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1305 "dirserver '%s:%d'. Please correct.",
1306 escaped(reason), conn->_base.address, conn->_base.port);
1307 control_event_server_status(LOG_WARN,
1308 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1309 conn->_base.address, conn->_base.port, escaped(reason));
1310 break;
1311 case 403:
1312 log_warn(LD_GENERAL,
1313 "http status 403 (%s) response from dirserver "
1314 "'%s:%d'. Is your clock skewed? Have you mailed us your key "
1315 "fingerprint? Are you using the right key? Are you using a "
1316 "private IP address? See http://tor.eff.org/doc/"
1317 "tor-doc-server.html",escaped(reason), conn->_base.address,
1318 conn->_base.port);
1319 control_event_server_status(LOG_WARN,
1320 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1321 conn->_base.address, conn->_base.port, escaped(reason));
1322 break;
1323 default:
1324 log_warn(LD_GENERAL,
1325 "http status %d (%s) reason unexpected while uploading "
1326 "descriptor to server '%s:%d').",
1327 status_code, escaped(reason), conn->_base.address,
1328 conn->_base.port);
1329 break;
1331 /* return 0 in all cases, since we don't want to mark any
1332 * dirservers down just because they don't like us. */
1335 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1336 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1337 "(%s))",
1338 (int)body_len, status_code, escaped(reason));
1339 switch (status_code) {
1340 case 200:
1341 if (rend_cache_store(body, body_len, 0) < 0) {
1342 log_warn(LD_REND,"Failed to store rendezvous descriptor.");
1343 /* alice's ap_stream will notice when connection_mark_for_close
1344 * cleans it up */
1345 } else {
1346 /* success. notify pending connections about this. */
1347 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1348 rend_client_desc_here(conn->rend_query);
1350 break;
1351 case 404:
1352 /* not there. pending connections will be notified when
1353 * connection_mark_for_close cleans it up. */
1354 break;
1355 case 400:
1356 log_warn(LD_REND,
1357 "http status 400 (%s). Dirserver didn't like our "
1358 "rendezvous query?", escaped(reason));
1359 break;
1360 default:
1361 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1362 "fetching hidden service descriptor (server '%s:%d').",
1363 status_code, escaped(reason), conn->_base.address,
1364 conn->_base.port);
1365 break;
1369 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
1370 switch (status_code) {
1371 case 200:
1372 log_info(LD_REND,
1373 "Uploading rendezvous descriptor: finished with status "
1374 "200 (%s)", escaped(reason));
1375 break;
1376 case 400:
1377 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1378 "'%s:%d'. Malformed rendezvous descriptor?",
1379 escaped(reason), conn->_base.address, conn->_base.port);
1380 break;
1381 default:
1382 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1383 "'%s:%d').",
1384 status_code, escaped(reason), conn->_base.address,
1385 conn->_base.port);
1386 break;
1389 tor_free(body); tor_free(headers); tor_free(reason);
1390 return 0;
1393 /** Called when a directory connection reaches EOF */
1395 connection_dir_reached_eof(dir_connection_t *conn)
1397 int retval;
1398 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
1399 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
1400 conn->_base.state);
1401 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
1402 connection_mark_for_close(TO_CONN(conn));
1403 return -1;
1406 retval = connection_dir_client_reached_eof(conn);
1407 if (retval == 0) /* success */
1408 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
1409 connection_mark_for_close(TO_CONN(conn));
1410 return retval;
1413 /** If any directory object is arriving, and it's over 10MB large, we're
1414 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1415 * ask for more than 96 router descriptors at a time.)
1417 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1419 /** Read handler for directory connections. (That's connections <em>to</em>
1420 * directory servers and connections <em>at</em> directory servers.)
1423 connection_dir_process_inbuf(dir_connection_t *conn)
1425 tor_assert(conn);
1426 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1428 /* Directory clients write, then read data until they receive EOF;
1429 * directory servers read data until they get an HTTP command, then
1430 * write their response (when it's finished flushing, they mark for
1431 * close).
1434 /* If we're on the dirserver side, look for a command. */
1435 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1436 if (directory_handle_command(conn) < 0) {
1437 connection_mark_for_close(TO_CONN(conn));
1438 return -1;
1440 return 0;
1443 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
1444 log_warn(LD_HTTP, "Too much data received from directory connection: "
1445 "denial of service attempt, or you need to upgrade?");
1446 connection_mark_for_close(TO_CONN(conn));
1447 return -1;
1450 if (!conn->_base.inbuf_reached_eof)
1451 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1452 return 0;
1455 /** Create an http response for the client <b>conn</b> out of
1456 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1458 static void
1459 write_http_status_line(dir_connection_t *conn, int status,
1460 const char *reason_phrase)
1462 char buf[256];
1463 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1464 status, reason_phrase ? reason_phrase : "OK") < 0) {
1465 log_warn(LD_BUG,"status line too long.");
1466 return;
1468 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
1471 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1472 * with <b>type</b> as the Content-Type.
1474 * If <b>length</b> is nonnegative, it is the Content-Length.
1475 * If <b>encoding</b> is provided, it is the Content-Encoding.
1476 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1477 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1478 static void
1479 write_http_response_header(dir_connection_t *conn, ssize_t length,
1480 const char *type, const char *encoding,
1481 int cache_lifetime)
1483 char date[RFC1123_TIME_LEN+1];
1484 char tmp[1024];
1485 char *cp;
1486 time_t now = time(NULL);
1488 tor_assert(conn);
1489 tor_assert(type);
1491 format_rfc1123_time(date, now);
1492 cp = tmp;
1493 tor_snprintf(cp, sizeof(tmp),
1494 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n",
1495 date, type);
1496 cp += strlen(tmp);
1497 if (!is_internal_IP(conn->_base.addr, 0)) {
1498 /* Don't report the source address for a localhost/private connection. */
1499 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1500 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
1501 cp += strlen(cp);
1503 if (encoding) {
1504 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1505 "Content-Encoding: %s\r\n", encoding);
1506 cp += strlen(cp);
1508 if (length >= 0) {
1509 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1510 "Content-Length: %ld\r\n", (long)length);
1511 cp += strlen(cp);
1513 if (cache_lifetime > 0) {
1514 char expbuf[RFC1123_TIME_LEN+1];
1515 format_rfc1123_time(expbuf, now + cache_lifetime);
1516 /* We could say 'Cache-control: max-age=%d' here if we start doing
1517 * http/1.1 */
1518 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1519 "Expires: %s\r\n", expbuf);
1520 cp += strlen(cp);
1521 } else {
1522 /* We could say 'Cache-control: no-cache' here if we start doing
1523 * http/1.1 */
1524 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
1525 cp += strlen(cp);
1527 if (sizeof(tmp)-(cp-tmp) > 3)
1528 memcpy(cp, "\r\n", 3);
1529 else
1530 tor_assert(0);
1531 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
1534 /** Helper function: return 1 if there are any dir conns of purpose
1535 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1536 * Else return 0.
1538 static int
1539 already_fetching_directory(int purpose)
1541 smartlist_t *conns = get_connection_array();
1542 SMARTLIST_FOREACH(conns, connection_t *, conn,
1544 if (conn->type == CONN_TYPE_DIR &&
1545 conn->purpose == purpose &&
1546 !conn->marked_for_close &&
1547 !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
1548 return 1;
1550 return 0;
1553 #undef INSTRUMENT_DOWNLOADS
1555 #ifdef INSTRUMENT_DOWNLOADS
1556 /** Map used to keep track of how much data we've up/downloaded in what kind
1557 * of request. Maps from request type to pointer to uint64_t. */
1558 static strmap_t *request_bytes_map = NULL;
1560 /** Called when we just transmitted or received <b>bytes</b> worth of data
1561 * because of a request of type <b>key</b> (an arbitrary identifier): adds
1562 * <b>bytes</b> to the total associated with key. */
1563 static void
1564 note_request(const char *key, size_t bytes)
1566 uint64_t *n;
1567 if (!request_bytes_map)
1568 request_bytes_map = strmap_new();
1570 n = strmap_get(request_bytes_map, key);
1571 if (!n) {
1572 n = tor_malloc_zero(sizeof(uint64_t));
1573 strmap_set(request_bytes_map, key, n);
1575 *n += bytes;
1578 /** Return a newly allocated string holding a summary of bytes used per
1579 * request type. */
1580 char *
1581 directory_dump_request_log(void)
1583 smartlist_t *lines;
1584 char tmp[256];
1585 char *result;
1586 strmap_iter_t *iter;
1588 if (!request_bytes_map)
1589 request_bytes_map = strmap_new();
1591 lines = smartlist_create();
1593 for (iter = strmap_iter_init(request_bytes_map);
1594 !strmap_iter_done(iter);
1595 iter = strmap_iter_next(request_bytes_map, iter)) {
1596 const char *key;
1597 void *val;
1598 uint64_t *n;
1599 strmap_iter_get(iter, &key, &val);
1600 n = val;
1601 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT"\n",
1602 key, U64_PRINTF_ARG(*n));
1603 smartlist_add(lines, tor_strdup(tmp));
1605 smartlist_sort_strings(lines);
1606 result = smartlist_join_strings(lines, "", 0, NULL);
1607 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
1608 smartlist_free(lines);
1609 return result;
1611 #else
1612 static void
1613 note_request(const char *key, size_t bytes)
1615 (void)key;
1616 (void)bytes;
1619 char *
1620 directory_dump_request_log(void)
1622 return tor_strdup("Not supported.");
1624 #endif
1626 /** Helper function: called when a dirserver gets a complete HTTP GET
1627 * request. Look for a request for a directory or for a rendezvous
1628 * service descriptor. On finding one, write a response into
1629 * conn-\>outbuf. If the request is unrecognized, send a 400.
1630 * Always return 0. */
1631 static int
1632 directory_handle_command_get(dir_connection_t *conn, const char *headers,
1633 const char *body, size_t body_len)
1635 size_t dlen;
1636 char *url = NULL;
1637 or_options_t *options = get_options();
1638 time_t if_modified_since = 0;
1639 char *header;
1641 /* We ignore the body of a GET request. */
1642 (void)body;
1643 (void)body_len;
1645 log_debug(LD_DIRSERV,"Received GET command.");
1647 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
1649 if (parse_http_url(headers, &url) < 0) {
1650 write_http_status_line(conn, 400, "Bad request");
1651 return 0;
1653 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
1654 struct tm tm;
1655 if (parse_http_time(header, &tm) == 0) {
1656 if_modified_since = tor_timegm(&tm);
1658 /* The correct behavior on a malformed If-Modified-Since header is to
1659 * act as if no If-Modified-Since header had been given. */
1660 tor_free(header);
1662 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
1664 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir.z")) { /* dir fetch */
1665 int deflated = !strcmp(url,"/tor/dir.z");
1666 cached_dir_t *d = dirserv_get_directory();
1668 if (!d) {
1669 log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
1670 "don't have a good one yet. Sending 503 Dir not available.");
1671 write_http_status_line(conn, 503, "Directory unavailable");
1672 /* try to get a new one now */
1673 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR))
1674 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1);
1675 tor_free(url);
1676 return 0;
1678 if (d->published < if_modified_since) {
1679 write_http_status_line(conn, 304, "Not modified");
1680 tor_free(url);
1681 return 0;
1684 dlen = deflated ? d->dir_z_len : d->dir_len;
1686 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
1687 log_info(LD_DIRSERV,
1688 "Client asked for the mirrored directory, but we've been "
1689 "writing too many bytes lately. Sending 503 Dir busy.");
1690 write_http_status_line(conn, 503, "Directory busy, try again later");
1691 tor_free(url);
1692 return 0;
1695 note_request(url, dlen);
1696 tor_free(url);
1698 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
1699 deflated?"deflated ":"");
1700 write_http_response_header(conn, dlen,
1701 deflated?"application/octet-stream":"text/plain",
1702 deflated?"deflate":"identity",
1703 FULL_DIR_CACHE_LIFETIME);
1704 conn->cached_dir = d;
1705 conn->cached_dir_offset = 0;
1706 if (! deflated)
1707 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
1708 ++d->refcnt;
1710 /* Prime the connection with some data. */
1711 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
1712 connection_dirserv_flushed_some(conn);
1713 return 0;
1716 if (!strcmp(url,"/tor/running-routers") ||
1717 !strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
1718 int deflated = !strcmp(url,"/tor/running-routers.z");
1719 cached_dir_t *d = dirserv_get_runningrouters();
1720 if (!d) {
1721 write_http_status_line(conn, 503, "Directory unavailable");
1722 /* try to get a new one now */
1723 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST))
1724 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
1725 tor_free(url);
1726 return 0;
1728 if (d->published < if_modified_since) {
1729 write_http_status_line(conn, 304, "Not modified");
1730 tor_free(url);
1731 return 0;
1733 dlen = deflated ? d->dir_z_len : d->dir_len;
1735 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
1736 log_info(LD_DIRSERV,
1737 "Client asked for running-routers, but we've been "
1738 "writing too many bytes lately. Sending 503 Dir busy.");
1739 write_http_status_line(conn, 503, "Directory busy, try again later");
1740 tor_free(url);
1741 return 0;
1743 note_request(url, dlen);
1744 tor_free(url);
1745 write_http_response_header(conn, dlen,
1746 deflated?"application/octet-stream":"text/plain",
1747 deflated?"deflate":"identity",
1748 RUNNINGROUTERS_CACHE_LIFETIME);
1749 connection_write_to_buf(deflated ? d->dir_z : d->dir, dlen, TO_CONN(conn));
1750 return 0;
1753 if (!strcmpstart(url,"/tor/status/")) {
1754 /* v2 network status fetch. */
1755 size_t url_len = strlen(url);
1756 int deflated = !strcmp(url+url_len-2, ".z");
1757 smartlist_t *dir_fps = smartlist_create();
1758 const char *request_type = NULL;
1759 const char *key = url + strlen("/tor/status/");
1760 if (deflated)
1761 url[url_len-2] = '\0';
1762 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
1763 if (!strcmpstart(key, "fp/"))
1764 request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
1765 else if (!strcmpstart(key, "authority"))
1766 request_type = deflated?"/tor/status/authority.z":
1767 "/tor/status/authority";
1768 else if (!strcmpstart(key, "all"))
1769 request_type = deflated?"/tor/status/all.z":"/tor/status/all";
1770 else
1771 request_type = "/tor/status/?";
1772 tor_free(url);
1773 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
1774 write_http_status_line(conn, 503, "Network status object unavailable");
1775 smartlist_free(dir_fps);
1776 return 0;
1778 if (dirserv_statuses_are_old(dir_fps, if_modified_since)) {
1779 write_http_status_line(conn, 304, "Not modified");
1780 smartlist_free(dir_fps);
1781 return 0;
1784 dlen = dirserv_estimate_data_size(dir_fps, 0, deflated);
1785 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
1786 log_info(LD_DIRSERV,
1787 "Client asked for network status lists, but we've been "
1788 "writing too many bytes lately. Sending 503 Dir busy.");
1789 write_http_status_line(conn, 503, "Directory busy, try again later");
1790 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
1791 smartlist_free(dir_fps);
1792 return 0;
1795 // note_request(request_type,dlen);
1796 (void) request_type;
1797 write_http_response_header(conn, -1,
1798 deflated?"application/octet_stream":"text/plain",
1799 deflated?"deflate":NULL,
1800 smartlist_len(dir_fps) == 1 ? NETWORKSTATUS_CACHE_LIFETIME:0);
1801 conn->fingerprint_stack = dir_fps;
1802 if (! deflated)
1803 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
1805 /* Prime the connection with some data. */
1806 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
1807 connection_dirserv_flushed_some(conn);
1809 return 0;
1812 if (!strcmpstart(url,"/tor/server/") ||
1813 !strcmpstart(url,"/tor/extra/")) {
1814 char *url_mem = url;
1815 size_t url_len = strlen(url);
1816 int deflated = !strcmp(url+url_len-2, ".z");
1817 int res;
1818 const char *msg;
1819 const char *request_type = NULL;
1820 int cache_lifetime = 0;
1821 int is_extra = !strcmpstart(url,"/tor/extra/");
1822 if (deflated)
1823 url[url_len-2] = '\0';
1824 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
1825 conn->fingerprint_stack = smartlist_create();
1826 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
1827 &msg);
1829 if (!strcmpstart(url, "fp/")) {
1830 request_type = deflated?"/tor/server/fp.z":"/tor/server/fp";
1831 if (smartlist_len(conn->fingerprint_stack) == 1)
1832 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
1833 } else if (!strcmpstart(url, "authority")) {
1834 request_type = deflated?"/tor/server/authority.z":
1835 "/tor/server/authority";
1836 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
1837 } else if (!strcmpstart(url, "all")) {
1838 request_type = deflated?"/tor/server/all.z":"/tor/server/all";
1839 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
1840 } else if (!strcmpstart(url, "d/")) {
1841 request_type = deflated?"/tor/server/d.z":"/tor/server/d";
1842 if (smartlist_len(conn->fingerprint_stack) == 1)
1843 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
1844 } else {
1845 request_type = "/tor/server/?";
1847 (void) request_type; /* usable for note_request. */
1848 if (!strcmpstart(url, "d/"))
1849 conn->dir_spool_src =
1850 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
1851 else
1852 conn->dir_spool_src =
1853 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
1854 tor_free(url_mem);
1855 if (res < 0)
1856 write_http_status_line(conn, 404, msg);
1857 else {
1858 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
1859 1, deflated);
1860 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
1861 log_info(LD_DIRSERV,
1862 "Client asked for server descriptors, but we've been "
1863 "writing too many bytes lately. Sending 503 Dir busy.");
1864 write_http_status_line(conn, 503, "Directory busy, try again later");
1865 return 0;
1867 write_http_response_header(conn, -1,
1868 deflated?"application/octet_stream":"text/plain",
1869 deflated?"deflate":NULL, cache_lifetime);
1870 if (deflated)
1871 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
1872 /* Prime the connection with some data. */
1873 connection_dirserv_flushed_some(conn);
1875 return 0;
1878 if (options->HSAuthoritativeDir &&
1879 (!strcmpstart(url,"/tor/rendezvous/") ||
1880 !strcmpstart(url,"/tor/rendezvous1/"))) {
1881 /* rendezvous descriptor fetch */
1882 const char *descp;
1883 size_t desc_len;
1884 int versioned = !strcmpstart(url,"/tor/rendezvous1/");
1885 const char *query = url+strlen("/tor/rendezvous/")+(versioned?1:0);
1887 switch (rend_cache_lookup_desc(query, versioned?-1:0, &descp, &desc_len)) {
1888 case 1: /* valid */
1889 write_http_response_header(conn, desc_len, "application/octet-stream",
1890 NULL, 0);
1891 note_request("/tor/rendezvous?/", desc_len);
1892 /* need to send descp separately, because it may include nuls */
1893 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
1894 /* report successful fetch to statistic */
1895 if (options->HSAuthorityRecordStats) {
1896 hs_usage_note_fetch_total(query, time(NULL));
1897 hs_usage_note_fetch_successful(query, time(NULL));
1899 break;
1900 case 0: /* well-formed but not present */
1901 write_http_status_line(conn, 404, "Not found");
1902 /* report (unsuccessful) fetch to statistic */
1903 if (options->HSAuthorityRecordStats) {
1904 hs_usage_note_fetch_total(query, time(NULL));
1906 break;
1907 case -1: /* not well-formed */
1908 write_http_status_line(conn, 400, "Bad request");
1909 break;
1911 tor_free(url);
1912 return 0;
1915 if (!strcmpstart(url,"/tor/bytes.txt")) {
1916 char *bytes = directory_dump_request_log();
1917 size_t len = strlen(bytes);
1918 write_http_response_header(conn, len, "text/plain", NULL, 0);
1919 connection_write_to_buf(bytes, len, TO_CONN(conn));
1920 tor_free(bytes);
1921 tor_free(url);
1922 return 0;
1925 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
1926 rewritten to /tor/robots.txt */
1927 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
1928 size_t len = strlen(robots);
1929 write_http_response_header(conn, len, "text/plain", NULL,
1930 ROBOTS_CACHE_LIFETIME);
1931 connection_write_to_buf(robots, len, TO_CONN(conn));
1932 tor_free(url);
1933 return 0;
1936 if (!strcmp(url,"/tor/dir-all-weaselhack") &&
1937 (conn->_base.addr == 0x7f000001ul) &&
1938 authdir_mode_v2(options) &&
1939 !authdir_mode_bridge(options)) {
1940 /* until weasel rewrites his scripts at noreply */
1941 char *new_directory=NULL;
1943 if (dirserv_dump_directory_to_string(&new_directory,
1944 get_identity_key(), 1)) {
1945 log_warn(LD_BUG, "Error creating full v1 directory.");
1946 tor_free(new_directory);
1947 write_http_status_line(conn, 503, "Directory unavailable");
1948 return 0;
1951 dlen = strlen(new_directory);
1953 write_http_response_header(conn, dlen, "text/plain", "identity", 0);
1955 connection_write_to_buf(new_directory, dlen, TO_CONN(conn));
1956 tor_free(new_directory);
1957 tor_free(url);
1958 return 0;
1961 /* we didn't recognize the url */
1962 write_http_status_line(conn, 404, "Not found");
1963 tor_free(url);
1964 return 0;
1967 /** Helper function: called when a dirserver gets a complete HTTP POST
1968 * request. Look for an uploaded server descriptor or rendezvous
1969 * service descriptor. On finding one, process it and write a
1970 * response into conn-\>outbuf. If the request is unrecognized, send a
1971 * 400. Always return 0. */
1972 static int
1973 directory_handle_command_post(dir_connection_t *conn, const char *headers,
1974 const char *body, size_t body_len)
1976 char *url = NULL;
1977 or_options_t *options = get_options();
1979 log_debug(LD_DIRSERV,"Received POST command.");
1981 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
1983 if (!authdir_mode(options)) {
1984 /* we just provide cached directories; we don't want to
1985 * receive anything. */
1986 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
1987 "accept posted server descriptors");
1988 return 0;
1991 if (parse_http_url(headers, &url) < 0) {
1992 write_http_status_line(conn, 400, "Bad request");
1993 return 0;
1995 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
1997 if (authdir_mode_handles_descs(options) &&
1998 !strcmp(url,"/tor/")) { /* server descriptor post */
1999 const char *msg = NULL;
2000 uint8_t purpose = authdir_mode_bridge(options) ?
2001 ROUTER_PURPOSE_CONTROLLER : ROUTER_PURPOSE_GENERAL;
2002 int r = dirserv_add_multiple_descriptors(body, purpose, &msg);
2003 tor_assert(msg);
2004 if (r > 0)
2005 dirserv_get_directory(); /* rebuild and write to disk */
2006 switch (r) {
2007 case -2:
2008 case -1:
2009 case 1:
2010 log_notice(LD_DIRSERV,
2011 "Rejected router descriptor or extra-info from %s.",
2012 conn->_base.address);
2013 /* malformed descriptor, or something wrong */
2014 write_http_status_line(conn, 400, msg);
2015 break;
2016 case 0: /* accepted but discarded */
2017 case 2: /* accepted */
2018 write_http_status_line(conn, 200, msg);
2019 break;
2021 goto done;
2024 if (options->HSAuthoritativeDir &&
2025 !strcmpstart(url,"/tor/rendezvous/publish")) {
2026 /* rendezvous descriptor post */
2027 if (rend_cache_store(body, body_len, 1) < 0) {
2028 // char tmp[1024*2+1];
2029 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
2030 "Rejected rend descriptor (length %d) from %s.",
2031 (int)body_len, conn->_base.address);
2032 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
2033 } else {
2034 write_http_status_line(conn, 200, "Service descriptor stored");
2036 goto done;
2039 /* we didn't recognize the url */
2040 write_http_status_line(conn, 404, "Not found");
2042 done:
2043 tor_free(url);
2044 return 0;
2047 /** Called when a dirserver receives data on a directory connection;
2048 * looks for an HTTP request. If the request is complete, remove it
2049 * from the inbuf, try to process it; otherwise, leave it on the
2050 * buffer. Return a 0 on success, or -1 on error.
2052 static int
2053 directory_handle_command(dir_connection_t *conn)
2055 char *headers=NULL, *body=NULL;
2056 size_t body_len=0;
2057 int r;
2059 tor_assert(conn);
2060 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2062 switch (fetch_from_buf_http(conn->_base.inbuf,
2063 &headers, MAX_HEADERS_SIZE,
2064 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
2065 case -1: /* overflow */
2066 log_warn(LD_DIRSERV,
2067 "Invalid input from address '%s'. Closing.",
2068 conn->_base.address);
2069 return -1;
2070 case 0:
2071 log_debug(LD_DIRSERV,"command not all here yet.");
2072 return 0;
2073 /* case 1, fall through */
2076 http_set_address_origin(headers, TO_CONN(conn));
2077 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
2079 if (!strncasecmp(headers,"GET",3))
2080 r = directory_handle_command_get(conn, headers, body, body_len);
2081 else if (!strncasecmp(headers,"POST",4))
2082 r = directory_handle_command_post(conn, headers, body, body_len);
2083 else {
2084 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
2085 "Got headers %s with unknown command. Closing.",
2086 escaped(headers));
2087 r = -1;
2090 tor_free(headers); tor_free(body);
2091 return r;
2094 /** Write handler for directory connections; called when all data has
2095 * been flushed. Close the connection or wait for a response as
2096 * appropriate.
2099 connection_dir_finished_flushing(dir_connection_t *conn)
2101 tor_assert(conn);
2102 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2104 switch (conn->_base.state) {
2105 case DIR_CONN_STATE_CLIENT_SENDING:
2106 log_debug(LD_DIR,"client finished sending command.");
2107 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
2108 connection_stop_writing(TO_CONN(conn));
2109 return 0;
2110 case DIR_CONN_STATE_SERVER_WRITING:
2111 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
2112 connection_mark_for_close(TO_CONN(conn));
2113 return 0;
2114 default:
2115 log_warn(LD_BUG,"called in unexpected state %d.",
2116 conn->_base.state);
2117 tor_fragile_assert();
2118 return -1;
2120 return 0;
2123 /** Connected handler for directory connections: begin sending data to the
2124 * server */
2126 connection_dir_finished_connecting(dir_connection_t *conn)
2128 tor_assert(conn);
2129 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2130 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
2132 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
2133 conn->_base.address,conn->_base.port);
2135 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
2136 return 0;
2139 /** Called when one or more networkstatus fetches have failed (with uppercase
2140 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
2141 * failed once, unless they failed with status code 503. */
2142 static void
2143 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
2145 if (status_code == 503)
2146 return;
2147 SMARTLIST_FOREACH(failed, const char *, fp,
2149 char digest[DIGEST_LEN];
2150 trusted_dir_server_t *dir;
2151 base16_decode(digest, DIGEST_LEN, fp, strlen(fp));
2152 dir = router_get_trusteddirserver_by_digest(digest);
2154 if (dir)
2155 ++dir->n_networkstatus_failures;
2159 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
2160 * fetches have failed (with uppercase fingerprints listed in
2161 * <b>failed</b>). */
2162 static void
2163 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
2164 int was_extrainfo)
2166 char digest[DIGEST_LEN];
2167 time_t now = time(NULL);
2168 int server = server_mode(get_options()) && get_options()->DirPort;
2169 SMARTLIST_FOREACH(failed, const char *, cp,
2171 download_status_t *dls = NULL;
2172 base16_decode(digest, DIGEST_LEN, cp, strlen(cp));
2173 if (was_extrainfo) {
2174 signed_descriptor_t *sd =
2175 router_get_by_extrainfo_digest(digest);
2176 if (sd)
2177 dls = &sd->ei_dl_status;
2178 } else {
2179 local_routerstatus_t *rs =
2180 router_get_combined_status_by_descriptor_digest(digest);
2181 if (rs)
2182 dls = &rs->dl_status;
2184 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
2185 continue;
2186 if (status_code != 503 || server)
2187 ++dls->n_download_failures;
2188 if (server) {
2189 switch (dls->n_download_failures) {
2190 case 0: dls->next_attempt_at = 0; break;
2191 case 1: dls->next_attempt_at = 0; break;
2192 case 2: dls->next_attempt_at = 0; break;
2193 case 3: dls->next_attempt_at = now+60; break;
2194 case 4: dls->next_attempt_at = now+60; break;
2195 case 5: dls->next_attempt_at = now+60*2; break;
2196 case 6: dls->next_attempt_at = now+60*5; break;
2197 case 7: dls->next_attempt_at = now+60*15; break;
2198 default: dls->next_attempt_at = TIME_MAX; break;
2200 } else {
2201 switch (dls->n_download_failures) {
2202 case 0: dls->next_attempt_at = 0; break;
2203 case 1: dls->next_attempt_at = 0; break;
2204 case 2: dls->next_attempt_at = now+60; break;
2205 case 3: dls->next_attempt_at = now+60*5; break;
2206 case 4: dls->next_attempt_at = now+60*10; break;
2207 default: dls->next_attempt_at = TIME_MAX; break;
2210 if (dls->next_attempt_at == 0)
2211 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
2212 cp, (int)dls->n_download_failures);
2213 else if (dls->next_attempt_at < TIME_MAX)
2214 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
2215 cp, (int)dls->n_download_failures,
2216 (int)(dls->next_attempt_at-now));
2217 else
2218 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
2219 cp, (int)dls->n_download_failures);
2222 /* No need to relaunch descriptor downloads here: we already do it
2223 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
2226 /** Given a directory <b>resource</b> request, containing zero
2227 * or more strings separated by plus signs, followed optionally by ".z", store
2228 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
2229 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
2230 * decode_hex is true, then delete all elements that aren't hex digests, and
2231 * decode the rest. If sort_uniq is true, then sort the list and remove
2232 * all duplicates.
2235 dir_split_resource_into_fingerprints(const char *resource,
2236 smartlist_t *fp_out, int *compressed_out,
2237 int decode_hex, int sort_uniq)
2239 smartlist_t *fp_tmp = smartlist_create();
2240 tor_assert(fp_out);
2241 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
2242 if (compressed_out)
2243 *compressed_out = 0;
2244 if (smartlist_len(fp_tmp)) {
2245 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
2246 size_t last_len = strlen(last);
2247 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
2248 last[last_len-2] = '\0';
2249 if (compressed_out)
2250 *compressed_out = 1;
2253 if (decode_hex) {
2254 int i;
2255 char *cp, *d = NULL;
2256 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
2257 cp = smartlist_get(fp_tmp, i);
2258 if (strlen(cp) != HEX_DIGEST_LEN) {
2259 log_info(LD_DIR,
2260 "Skipping digest %s with non-standard length.", escaped(cp));
2261 smartlist_del_keeporder(fp_tmp, i--);
2262 goto again;
2264 d = tor_malloc_zero(DIGEST_LEN);
2265 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
2266 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
2267 smartlist_del_keeporder(fp_tmp, i--);
2268 goto again;
2270 smartlist_set(fp_tmp, i, d);
2271 d = NULL;
2272 again:
2273 tor_free(cp);
2274 tor_free(d);
2277 if (sort_uniq) {
2278 smartlist_t *fp_tmp2 = smartlist_create();
2279 int i;
2280 if (decode_hex)
2281 smartlist_sort_digests(fp_tmp);
2282 else
2283 smartlist_sort_strings(fp_tmp);
2284 if (smartlist_len(fp_tmp))
2285 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
2286 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
2287 char *cp = smartlist_get(fp_tmp, i);
2288 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
2290 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
2291 || (!decode_hex && strcasecmp(cp, last)))
2292 smartlist_add(fp_tmp2, cp);
2293 else
2294 tor_free(cp);
2296 smartlist_free(fp_tmp);
2297 fp_tmp = fp_tmp2;
2299 smartlist_add_all(fp_out, fp_tmp);
2300 smartlist_free(fp_tmp);
2301 return 0;