r13715@catbus: nickm | 2007-07-12 12:11:09 -0400
[tor.git] / src / or / directory.c
blob6bed668ea5e631baca75f63a747d3dd984c23c60
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_is_private(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 static void note_request(const char *key, size_t bytes);
51 /********* START VARIABLES **********/
53 /** How far in the future do we allow a directory server to tell us it is
54 * before deciding that one of us has the wrong time? */
55 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
57 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
59 /** HTTP cache control: how long do we tell proxies they can cache each
60 * kind of document we serve? */
61 #define FULL_DIR_CACHE_LIFETIME (60*60)
62 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
63 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
64 #define ROUTERDESC_CACHE_LIFETIME (30*60)
65 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
66 #define ROBOTS_CACHE_LIFETIME (24*60*60)
68 /********* END VARIABLES ************/
70 /** Return true iff the directory purpose 'purpose' must use an
71 * anonymous connection to a directory. */
72 static int
73 purpose_is_private(uint8_t purpose)
75 if (get_options()->AllDirActionsPrivate)
76 return 1;
77 if (purpose == DIR_PURPOSE_FETCH_DIR ||
78 purpose == DIR_PURPOSE_UPLOAD_DIR ||
79 purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
80 purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
81 purpose == DIR_PURPOSE_FETCH_SERVERDESC)
82 return 0;
83 return 1;
86 /** Start a connection to every known directory server, using
87 * connection purpose 'purpose' and uploading the payload 'payload'
88 * (length 'payload_len'). The purpose should be one of
89 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
91 void
92 directory_post_to_dirservers(uint8_t purpose, const char *payload,
93 size_t payload_len)
95 smartlist_t *dirservers;
96 int post_via_tor;
97 int post_to_hidserv_only;
99 dirservers = router_get_trusted_dir_servers();
100 tor_assert(dirservers);
101 /* Only old dirservers handle rendezvous descriptor publishing. */
102 post_to_hidserv_only = (purpose == DIR_PURPOSE_UPLOAD_RENDDESC);
103 /* This tries dirservers which we believe to be down, but ultimately, that's
104 * harmless, and we may as well err on the side of getting things uploaded.
106 SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
108 routerstatus_t *rs = &(ds->fake_status.status);
109 if (post_to_hidserv_only && !ds->is_hidserv_authority)
110 continue;
111 if (!post_to_hidserv_only &&
112 !(ds->is_v1_authority || ds->is_v2_authority))
113 continue;
114 if (purpose == DIR_PURPOSE_UPLOAD_DIR)
115 ds->has_accepted_serverdesc = 0;
116 post_via_tor = purpose_is_private(purpose) ||
117 !fascist_firewall_allows_address_dir(ds->addr, ds->dir_port);
118 directory_initiate_command_routerstatus(rs, purpose, post_via_tor,
119 NULL, payload, payload_len);
123 /** Start a connection to a random running directory server, using
124 * connection purpose 'purpose' and requesting 'resource'.
125 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
126 * down, mark them up and try again.
128 void
129 directory_get_from_dirserver(uint8_t purpose, const char *resource,
130 int retry_if_no_servers)
132 routerstatus_t *rs = NULL;
133 or_options_t *options = get_options();
134 int prefer_authority = server_mode(options) && options->DirPort != 0;
135 int directconn = !purpose_is_private(purpose);
136 authority_type_t type;
138 /* FFFF we could break this switch into its own function, and call
139 * it elsewhere in directory.c. -RD */
140 switch (purpose) {
141 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
142 case DIR_PURPOSE_FETCH_SERVERDESC:
143 type = V2_AUTHORITY;
144 break;
145 case DIR_PURPOSE_FETCH_DIR:
146 case DIR_PURPOSE_FETCH_RUNNING_LIST:
147 type = V1_AUTHORITY;
148 break;
149 case DIR_PURPOSE_FETCH_RENDDESC:
150 type = HIDSERV_AUTHORITY;
151 break;
152 default:
153 log_warn(LD_BUG, "Unexpected purpose %d", (int)purpose);
154 return;
157 if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
158 return;
160 if (directconn) {
161 if (prefer_authority) {
162 /* only ask authdirservers, and don't ask myself */
163 rs = router_pick_trusteddirserver(type, 1, 1,
164 retry_if_no_servers);
166 if (!rs) {
167 /* anybody with a non-zero dirport will do */
168 rs = router_pick_directory_server(1, 1, type==V2_AUTHORITY,
169 retry_if_no_servers);
170 if (!rs) {
171 const char *which;
172 if (purpose == DIR_PURPOSE_FETCH_DIR)
173 which = "directory";
174 else if (purpose == DIR_PURPOSE_FETCH_RUNNING_LIST)
175 which = "status list";
176 else if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
177 which = "network status";
178 else // if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
179 which = "server descriptors";
180 log_info(LD_DIR,
181 "No router found for %s; falling back to dirserver list",
182 which);
183 rs = router_pick_trusteddirserver(type, 1, 1,
184 retry_if_no_servers);
185 if (!rs)
186 directconn = 0; /* last resort: try routing it via Tor */
190 if (!directconn) {
191 /* Never use fascistfirewall; we're going via Tor. */
192 if (purpose == DIR_PURPOSE_FETCH_RENDDESC) {
193 /* only ask hidserv authorities, any of them will do */
194 rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, 0, 0,
195 retry_if_no_servers);
196 } else {
197 /* anybody with a non-zero dirport will do. Disregard firewalls. */
198 rs = router_pick_directory_server(1, 0, type == V2_AUTHORITY,
199 retry_if_no_servers);
200 /* If we have any hope of building an indirect conn, we know some router
201 * descriptors. If (rs==NULL), we can't build circuits anyway, so
202 * there's no point in falling back to the authorities in this case. */
206 if (rs)
207 directory_initiate_command_routerstatus(rs, purpose, !directconn,
208 resource, NULL, 0);
209 else {
210 log_notice(LD_DIR,
211 "While fetching directory info, "
212 "no running dirservers known. Will try again later. "
213 "(purpose %d)", purpose);
214 if (!purpose_is_private(purpose)) {
215 /* remember we tried them all and failed. */
216 directory_all_unreachable(time(NULL));
221 /** Launch a new connection to the directory server <b>status</b> to upload or
222 * download a server or rendezvous descriptor. <b>purpose</b> determines what
223 * kind of directory connection we're launching, and must be one of
224 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
226 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
227 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
229 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
230 * want to fetch.
232 void
233 directory_initiate_command_routerstatus(routerstatus_t *status,
234 uint8_t purpose,
235 int private_connection,
236 const char *resource,
237 const char *payload,
238 size_t payload_len)
240 routerinfo_t *router;
241 char address_buf[INET_NTOA_BUF_LEN+1];
242 struct in_addr in;
243 const char *address;
244 if ((router = router_get_by_digest(status->identity_digest))) {
245 address = router->address;
246 } else {
247 in.s_addr = htonl(status->addr);
248 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
249 address = address_buf;
251 directory_initiate_command(address, status->addr, status->dir_port,
252 status->version_supports_begindir,
253 status->identity_digest,
254 purpose, private_connection, resource,
255 payload, payload_len);
258 /** Return true iff <b>conn</b> is the client side of a directory connection
259 * we launched to ourself in order to determine the reachability of our
260 * dir_port. */
261 static int
262 directory_conn_is_self_reachability_test(dir_connection_t *conn)
264 if (conn->requested_resource &&
265 !strcmpstart(conn->requested_resource,"authority")) {
266 routerinfo_t *me = router_get_my_routerinfo();
267 if (me &&
268 router_digest_is_me(conn->identity_digest) &&
269 me->addr == conn->_base.addr &&
270 me->dir_port == conn->_base.port)
271 return 1;
273 return 0;
276 /** Called when we are unable to complete the client's request to a directory
277 * server due to a network error: Mark the router as down and try again if
278 * possible.
280 void
281 connection_dir_request_failed(dir_connection_t *conn)
283 if (directory_conn_is_self_reachability_test(conn)) {
284 routerinfo_t *me = router_get_my_routerinfo();
285 if (me)
286 control_event_server_status(LOG_WARN,
287 "REACHABILITY_FAILED DIRADDRESS=%s:%d",
288 me->address, me->dir_port);
289 return; /* this was a test fetch. don't retry. */
291 router_set_status(conn->identity_digest, 0); /* don't try him again */
292 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR ||
293 conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
294 log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
295 conn->_base.address, conn->_base.port);
296 directory_get_from_dirserver(conn->_base.purpose, NULL,
297 0 /* don't retry_if_no_servers */);
298 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
299 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
300 conn->_base.address);
301 connection_dir_download_networkstatus_failed(conn, -1);
302 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
303 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
304 conn->_base.address);
305 connection_dir_download_routerdesc_failed(conn);
309 /** Called when an attempt to download one or more network status
310 * documents on connection <b>conn</b> failed. Decide whether to
311 * retry the fetch now, later, or never.
313 static void
314 connection_dir_download_networkstatus_failed(dir_connection_t *conn,
315 int status_code)
317 if (!conn->requested_resource) {
318 /* We never reached directory_send_command, which means that we never
319 * opened a network connection. Either we're out of sockets, or the
320 * network is down. Either way, retrying would be pointless. */
321 return;
323 if (!strcmpstart(conn->requested_resource, "all")) {
324 /* We're a non-authoritative directory cache; try again. Ignore status
325 * code, since we don't want to keep trying forever in a tight loop
326 * if all the authorities are shutting us out. */
327 smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
328 SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
329 ++ds->n_networkstatus_failures);
330 directory_get_from_dirserver(conn->_base.purpose, "all.z",
331 0 /* don't retry_if_no_servers */);
332 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
333 /* We were trying to download by fingerprint; mark them all as having
334 * failed, and possibly retry them later.*/
335 smartlist_t *failed = smartlist_create();
336 dir_split_resource_into_fingerprints(conn->requested_resource+3,
337 failed, NULL, 0, 0);
338 if (smartlist_len(failed)) {
339 dir_networkstatus_download_failed(failed, status_code);
340 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
342 smartlist_free(failed);
346 /** Called when an attempt to download one or more router descriptors
347 * on connection <b>conn</b> failed.
349 static void
350 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
352 /* No need to increment the failure count for routerdescs, since
353 * it's not their fault. */
355 /* No need to relaunch descriptor downloads here: we already do it
356 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
358 (void) conn;
361 /** Helper for directory_initiate_command_(router|trusted_dir): send the
362 * command to a server whose address is <b>address</b>, whose IP is
363 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
364 * <b>supports_begindir</b>, and whose identity key digest is
365 * <b>digest</b>. */
366 void
367 directory_initiate_command(const char *address, uint32_t addr,
368 uint16_t dir_port, int supports_begindir,
369 const char *digest, uint8_t purpose,
370 int private_connection, const char *resource,
371 const char *payload, size_t payload_len)
373 dir_connection_t *conn;
374 or_options_t *options = get_options();
375 int want_to_tunnel = options->TunnelDirConns && supports_begindir &&
376 router_get_by_digest(digest);
378 tor_assert(address);
379 tor_assert(addr);
380 tor_assert(dir_port);
381 tor_assert(digest);
383 log_debug(LD_DIR, "private %d, want_to_tunnel %d.",
384 private_connection, want_to_tunnel);
386 switch (purpose) {
387 case DIR_PURPOSE_FETCH_DIR:
388 log_debug(LD_DIR,"initiating directory fetch");
389 break;
390 case DIR_PURPOSE_FETCH_RENDDESC:
391 log_debug(LD_DIR,"initiating hidden-service descriptor fetch");
392 break;
393 case DIR_PURPOSE_UPLOAD_DIR:
394 log_debug(LD_OR,"initiating server descriptor upload");
395 break;
396 case DIR_PURPOSE_UPLOAD_RENDDESC:
397 log_debug(LD_REND,"initiating hidden-service descriptor upload");
398 break;
399 case DIR_PURPOSE_FETCH_RUNNING_LIST:
400 log_debug(LD_DIR,"initiating running-routers fetch");
401 break;
402 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
403 log_debug(LD_DIR,"initiating network-status fetch");
404 break;
405 case DIR_PURPOSE_FETCH_SERVERDESC:
406 log_debug(LD_DIR,"initiating server descriptor fetch");
407 break;
408 default:
409 log_err(LD_BUG, "Unrecognized directory connection purpose.");
410 tor_assert(0);
413 conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR));
415 /* set up conn so it's got all the data we need to remember */
416 conn->_base.addr = addr;
417 conn->_base.port = dir_port;
418 conn->_base.address = tor_strdup(address);
419 memcpy(conn->identity_digest, digest, DIGEST_LEN);
421 conn->_base.purpose = purpose;
423 /* give it an initial state */
424 conn->_base.state = DIR_CONN_STATE_CONNECTING;
426 if (!private_connection && !want_to_tunnel) {
427 /* then we want to connect directly */
429 conn->dirconn_direct = 1;
430 if (options->HttpProxy) {
431 addr = options->HttpProxyAddr;
432 dir_port = options->HttpProxyPort;
435 switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
436 dir_port)) {
437 case -1:
438 connection_dir_request_failed(conn); /* retry if we want */
439 connection_free(TO_CONN(conn));
440 return;
441 case 1:
442 /* start flushing conn */
443 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
444 /* fall through */
445 case 0:
446 /* queue the command on the outbuf */
447 directory_send_command(conn, purpose, 1, resource,
448 payload, payload_len);
449 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
450 /* writable indicates finish, readable indicates broken link,
451 error indicates broken link in windowsland. */
453 } else { /* we want to connect via tor */
454 /* make an AP connection
455 * populate it and add it at the right state
456 * socketpair and hook up both sides
458 conn->dirconn_direct = 0;
459 conn->_base.s =
460 connection_ap_make_bridge(conn->_base.address, conn->_base.port,
461 digest,
462 private_connection ?
463 SOCKS_COMMAND_CONNECT :
464 SOCKS_COMMAND_CONNECT_DIR);
465 if (conn->_base.s < 0) {
466 log_warn(LD_NET,"Making AP bridge to dirserver failed.");
467 connection_mark_for_close(TO_CONN(conn));
468 return;
471 if (connection_add(TO_CONN(conn)) < 0) {
472 log_warn(LD_NET,"Unable to add AP bridge to dirserver.");
473 connection_mark_for_close(TO_CONN(conn));
474 return;
476 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
477 /* queue the command on the outbuf */
478 directory_send_command(conn, purpose, 0, resource,
479 payload, payload_len);
480 connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
484 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
485 * are as in directory_initiate_command.
487 static void
488 directory_send_command(dir_connection_t *conn,
489 int purpose, int direct, const char *resource,
490 const char *payload, size_t payload_len)
492 char proxystring[256];
493 char proxyauthstring[256];
494 char hoststring[128];
495 char *url;
496 char request[8192];
497 const char *httpcommand = NULL;
498 size_t len;
500 tor_assert(conn);
501 tor_assert(conn->_base.type == CONN_TYPE_DIR);
503 tor_free(conn->requested_resource);
504 if (resource)
505 conn->requested_resource = tor_strdup(resource);
507 /* come up with a string for which Host: we want */
508 if (conn->_base.port == 80) {
509 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
510 } else {
511 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
512 conn->_base.address, conn->_base.port);
515 /* come up with some proxy lines, if we're using one. */
516 if (direct && get_options()->HttpProxy) {
517 char *base64_authenticator=NULL;
518 const char *authenticator = get_options()->HttpProxyAuthenticator;
520 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
521 if (authenticator) {
522 base64_authenticator = alloc_http_authenticator(authenticator);
523 if (!base64_authenticator)
524 log_warn(LD_BUG, "Encoding http authenticator failed");
526 if (base64_authenticator) {
527 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
528 "\r\nProxy-Authorization: Basic %s",
529 base64_authenticator);
530 tor_free(base64_authenticator);
531 } else {
532 proxyauthstring[0] = 0;
534 } else {
535 proxystring[0] = 0;
536 proxyauthstring[0] = 0;
539 switch (purpose) {
540 case DIR_PURPOSE_FETCH_DIR:
541 tor_assert(!resource);
542 tor_assert(!payload);
543 httpcommand = "GET";
544 url = tor_strdup("/tor/dir.z");
545 break;
546 case DIR_PURPOSE_FETCH_RUNNING_LIST:
547 tor_assert(!resource);
548 tor_assert(!payload);
549 httpcommand = "GET";
550 url = tor_strdup("/tor/running-routers");
551 break;
552 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
553 httpcommand = "GET";
554 len = strlen(resource)+32;
555 url = tor_malloc(len);
556 tor_snprintf(url, len, "/tor/status/%s", resource);
557 break;
558 case DIR_PURPOSE_FETCH_SERVERDESC:
559 httpcommand = "GET";
560 len = strlen(resource)+32;
561 url = tor_malloc(len);
562 tor_snprintf(url, len, "/tor/server/%s", resource);
563 break;
564 case DIR_PURPOSE_UPLOAD_DIR:
565 tor_assert(!resource);
566 tor_assert(payload);
567 httpcommand = "POST";
568 url = tor_strdup("/tor/");
569 break;
570 case DIR_PURPOSE_FETCH_RENDDESC:
571 tor_assert(resource);
572 tor_assert(!payload);
574 /* this must be true or we wouldn't be doing the lookup */
575 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN);
576 /* This breaks the function abstraction. */
577 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
579 httpcommand = "GET";
580 /* Request the most recent versioned descriptor. */
581 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
582 // but that never got testing, and it wasn't a good design.)
583 len = strlen(resource)+32;
584 url = tor_malloc(len);
585 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
586 break;
587 case DIR_PURPOSE_UPLOAD_RENDDESC:
588 tor_assert(!resource);
589 tor_assert(payload);
590 httpcommand = "POST";
591 url = tor_strdup("/tor/rendezvous/publish");
592 break;
593 default:
594 tor_assert(0);
595 return;
598 if (strlen(proxystring) + strlen(url) >= 4096) {
599 log_warn(LD_BUG,
600 "Bug: squid does not like URLs longer than 4095 bytes, this "
601 "one is %d bytes long: %s%s",
602 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
605 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
606 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
607 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
608 tor_free(url);
610 if (!strcmp(httpcommand, "GET") && !payload) {
611 tor_snprintf(request, sizeof(request),
612 " HTTP/1.0\r\nHost: %s%s\r\n\r\n",
613 hoststring,
614 proxyauthstring);
615 } else {
616 tor_snprintf(request, sizeof(request),
617 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
618 payload ? (unsigned long)payload_len : 0,
619 hoststring,
620 proxyauthstring);
622 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
624 if (payload) {
625 /* then send the payload afterwards too */
626 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
630 /** Parse an HTTP request string <b>headers</b> of the form
631 * \verbatim
632 * "\%s [http[s]://]\%s HTTP/1..."
633 * \endverbatim
634 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
635 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
636 * so it does. Return 0.
637 * Otherwise, return -1.
639 static int
640 parse_http_url(const char *headers, char **url)
642 char *s, *start, *tmp;
644 s = (char *)eat_whitespace_no_nl(headers);
645 if (!*s) return -1;
646 s = (char *)find_whitespace(s); /* get past GET/POST */
647 if (!*s) return -1;
648 s = (char *)eat_whitespace_no_nl(s);
649 if (!*s) return -1;
650 start = s; /* this is it, assuming it's valid */
651 s = (char *)find_whitespace(start);
652 if (!*s) return -1;
654 /* tolerate the http[s] proxy style of putting the hostname in the url */
655 if (s-start >= 4 && !strcmpstart(start,"http")) {
656 tmp = start + 4;
657 if (*tmp == 's')
658 tmp++;
659 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
660 tmp = strchr(tmp+3, '/');
661 if (tmp && tmp < s) {
662 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
663 start = tmp;
668 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
669 *url = tor_malloc(s - start + 5);
670 strlcpy(*url,"/tor", s-start+5);
671 strlcat((*url)+4, start, s-start+1);
672 } else {
673 *url = tor_strndup(start, s-start);
675 return 0;
678 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
679 * <b>which</b>. The key should be given with a terminating colon and space;
680 * this function copies everything after, up to but not including the
681 * following \\r\\n. */
682 static char *
683 http_get_header(const char *headers, const char *which)
685 const char *cp = headers;
686 while (cp) {
687 if (!strcmpstart(cp, which)) {
688 char *eos;
689 cp += strlen(which);
690 if ((eos = strchr(cp,'\r')))
691 return tor_strndup(cp, eos-cp);
692 else
693 return tor_strdup(cp);
695 cp = strchr(cp, '\n');
696 if (cp)
697 ++cp;
699 return NULL;
702 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
703 * <b>conn</b>-\>address to describe our best guess of the address that
704 * originated this HTTP request. */
705 static void
706 http_set_address_origin(const char *headers, connection_t *conn)
708 char *fwd;
710 fwd = http_get_header(headers, "Forwarded-For: ");
711 if (!fwd)
712 fwd = http_get_header(headers, "X-Forwarded-For: ");
713 if (fwd) {
714 struct in_addr in;
715 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
716 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
717 escaped(fwd));
718 tor_free(fwd);
719 return;
721 tor_free(conn->address);
722 conn->address = tor_strdup(fwd);
723 tor_free(fwd);
727 /** Parse an HTTP response string <b>headers</b> of the form
728 * \verbatim
729 * "HTTP/1.\%d \%d\%s\r\n...".
730 * \endverbatim
732 * If it's well-formed, assign the status code to *<b>code</b> and
733 * return 0. Otherwise, return -1.
735 * On success: If <b>date</b> is provided, set *date to the Date
736 * header in the http headers, or 0 if no such header is found. If
737 * <b>compression</b> is provided, set *<b>compression</b> to the
738 * compression method given in the Content-Encoding header, or 0 if no
739 * such header is found, or -1 if the value of the header is not
740 * recognized. If <b>reason</b> is provided, strdup the reason string
741 * into it.
744 parse_http_response(const char *headers, int *code, time_t *date,
745 compress_method_t *compression, char **reason)
747 int n1, n2;
748 char datestr[RFC1123_TIME_LEN+1];
749 smartlist_t *parsed_headers;
750 tor_assert(headers);
751 tor_assert(code);
753 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
755 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
756 (n1 != 0 && n1 != 1) ||
757 (n2 < 100 || n2 >= 600)) {
758 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
759 return -1;
761 *code = n2;
763 parsed_headers = smartlist_create();
764 smartlist_split_string(parsed_headers, headers, "\n",
765 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
766 if (reason) {
767 smartlist_t *status_line_elements = smartlist_create();
768 tor_assert(smartlist_len(parsed_headers));
769 smartlist_split_string(status_line_elements,
770 smartlist_get(parsed_headers, 0),
771 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
772 tor_assert(smartlist_len(status_line_elements) <= 3);
773 if (smartlist_len(status_line_elements) == 3) {
774 *reason = smartlist_get(status_line_elements, 2);
775 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
777 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
778 smartlist_free(status_line_elements);
780 if (date) {
781 *date = 0;
782 SMARTLIST_FOREACH(parsed_headers, const char *, s,
783 if (!strcmpstart(s, "Date: ")) {
784 strlcpy(datestr, s+6, sizeof(datestr));
785 /* This will do nothing on failure, so we don't need to check
786 the result. We shouldn't warn, since there are many other valid
787 date formats besides the one we use. */
788 parse_rfc1123_time(datestr, date);
789 break;
792 if (compression) {
793 const char *enc = NULL;
794 SMARTLIST_FOREACH(parsed_headers, const char *, s,
795 if (!strcmpstart(s, "Content-Encoding: ")) {
796 enc = s+18; break;
798 if (!enc || !strcmp(enc, "identity")) {
799 *compression = NO_METHOD;
800 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
801 *compression = ZLIB_METHOD;
802 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
803 *compression = GZIP_METHOD;
804 } else {
805 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
806 escaped(enc));
807 *compression = UNKNOWN_METHOD;
810 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
811 smartlist_free(parsed_headers);
813 return 0;
816 /** Return true iff <b>body</b> doesn't start with a plausible router or
817 * running-list or directory opening. This is a sign of possible compression.
819 static int
820 body_is_plausible(const char *body, size_t len, int purpose)
822 int i;
823 if (len == 0)
824 return 1; /* empty bodies don't need decompression */
825 if (len < 32)
826 return 0;
827 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
828 if (!strcmpstart(body,"router") ||
829 !strcmpstart(body,"signed-directory") ||
830 !strcmpstart(body,"network-status") ||
831 !strcmpstart(body,"running-routers"))
832 return 1;
833 for (i=0;i<32;++i) {
834 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
835 return 0;
837 return 1;
838 } else {
839 return 1;
843 /** We are a client, and we've finished reading the server's
844 * response. Parse and it and act appropriately.
846 * If we're still happy with using this directory server in the future, return
847 * 0. Otherwise return -1; and the caller should consider trying the request
848 * again.
850 * The caller will take care of marking the connection for close.
852 static int
853 connection_dir_client_reached_eof(dir_connection_t *conn)
855 char *body;
856 char *headers;
857 char *reason = NULL;
858 size_t body_len=0, orig_len=0;
859 int status_code;
860 time_t date_header=0;
861 int delta;
862 compress_method_t compression;
863 int plausible;
864 int skewed=0;
865 int allow_partial = conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC;
866 int was_compressed=0;
868 switch (fetch_from_buf_http(conn->_base.inbuf,
869 &headers, MAX_HEADERS_SIZE,
870 &body, &body_len, MAX_DIR_DL_SIZE,
871 allow_partial)) {
872 case -1: /* overflow */
873 log_warn(LD_PROTOCOL,
874 "'fetch' response too large (server '%s:%d'). Closing.",
875 conn->_base.address, conn->_base.port);
876 return -1;
877 case 0:
878 log_info(LD_HTTP,
879 "'fetch' response not all here, but we're at eof. Closing.");
880 return -1;
881 /* case 1, fall through */
883 orig_len = body_len;
885 if (parse_http_response(headers, &status_code, &date_header,
886 &compression, &reason) < 0) {
887 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
888 conn->_base.address, conn->_base.port);
889 tor_free(body); tor_free(headers);
890 return -1;
892 if (!reason) reason = tor_strdup("[no reason given]");
894 log_debug(LD_DIR,
895 "Received response from directory server '%s:%d': %d %s",
896 conn->_base.address, conn->_base.port, status_code,
897 escaped(reason));
899 /* now check if it's got any hints for us about our IP address. */
900 if (conn->dirconn_direct) {
901 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
902 if (guess) {
903 router_new_address_suggestion(guess);
904 tor_free(guess);
908 if (date_header > 0) {
909 /* The date header was written very soon after we sent our request,
910 * so compute the skew as the difference between sending the request
911 * and the date header. (We used to check now-date_header, but that's
912 * inaccurate if we spend a lot of time downloading.)
914 delta = conn->_base.timestamp_lastwritten - date_header;
915 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
916 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
917 log_fn(trusted ? LOG_WARN : LOG_INFO,
918 LD_HTTP,
919 "Received directory with skewed time (server '%s:%d'): "
920 "we are %d minutes %s, or the directory is %d minutes %s.",
921 conn->_base.address, conn->_base.port,
922 abs(delta)/60, delta>0 ? "ahead" : "behind",
923 abs(delta)/60, delta>0 ? "behind" : "ahead");
924 skewed = 1; /* don't check the recommended-versions line */
925 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
926 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
927 delta, conn->_base.address, conn->_base.port);
928 } else {
929 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
930 "we are %d seconds skewed. (That's okay.)", delta);
933 (void) skewed; /* skewed isn't used yet. */
935 if (status_code == 503) {
936 local_routerstatus_t *rs;
937 trusted_dir_server_t *ds;
938 time_t now = time(NULL);
939 log_info(LD_DIR,"Received http status code %d (%s) from server "
940 "'%s:%d'. I'll try again soon.",
941 status_code, escaped(reason), conn->_base.address,
942 conn->_base.port);
943 if ((rs = router_get_combined_status_by_digest(conn->identity_digest)))
944 rs->last_dir_503_at = now;
945 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
946 ds->fake_status.last_dir_503_at = now;
948 tor_free(body); tor_free(headers); tor_free(reason);
949 return -1;
952 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
953 if (compression != NO_METHOD || !plausible) {
954 char *new_body = NULL;
955 size_t new_len = 0;
956 compress_method_t guessed = detect_compression_method(body, body_len);
957 if (compression == UNKNOWN_METHOD || guessed != compression) {
958 /* Tell the user if we don't believe what we're told about compression.*/
959 const char *description1, *description2;
960 if (compression == ZLIB_METHOD)
961 description1 = "as deflated";
962 else if (compression == GZIP_METHOD)
963 description1 = "as gzipped";
964 else if (compression == NO_METHOD)
965 description1 = "as uncompressed";
966 else
967 description1 = "with an unknown Content-Encoding";
968 if (guessed == ZLIB_METHOD)
969 description2 = "deflated";
970 else if (guessed == GZIP_METHOD)
971 description2 = "gzipped";
972 else if (!plausible)
973 description2 = "confusing binary junk";
974 else
975 description2 = "uncompressed";
977 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
978 "but it seems to be %s.%s",
979 conn->_base.address, conn->_base.port, description1,
980 description2,
981 (compression>0 && guessed>0)?" Trying both.":"");
983 /* Try declared compression first if we can. */
984 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
985 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
986 !allow_partial, LOG_PROTOCOL_WARN);
987 /* Okay, if that didn't work, and we think that it was compressed
988 * differently, try that. */
989 if (!new_body &&
990 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
991 compression != guessed)
992 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
993 !allow_partial, LOG_PROTOCOL_WARN);
994 /* If we're pretty sure that we have a compressed directory, and
995 * we didn't manage to uncompress it, then warn and bail. */
996 if (!plausible && !new_body) {
997 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
998 "Unable to decompress HTTP body (server '%s:%d').",
999 conn->_base.address, conn->_base.port);
1000 tor_free(body); tor_free(headers); tor_free(reason);
1001 return -1;
1003 if (new_body) {
1004 tor_free(body);
1005 body = new_body;
1006 body_len = new_len;
1007 was_compressed = 1;
1011 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
1012 /* fetch/process the directory to cache it. */
1013 log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
1014 (int)body_len, conn->_base.address, conn->_base.port);
1015 if (status_code != 200) {
1016 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1017 "'%s:%d' while fetching directory. I'll try again soon.",
1018 status_code, escaped(reason), conn->_base.address,
1019 conn->_base.port);
1020 tor_free(body); tor_free(headers); tor_free(reason);
1021 return -1;
1023 if (router_parse_directory(body) < 0) {
1024 log_notice(LD_DIR,"I failed to parse the directory I fetched from "
1025 "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
1027 note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
1030 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
1031 /* just update our list of running routers, if this list is new info */
1032 log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
1033 if (status_code != 200) {
1034 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1035 "'%s:%d' while fetching running-routers. I'll try again soon.",
1036 status_code, escaped(reason), conn->_base.address,
1037 conn->_base.port);
1038 tor_free(body); tor_free(headers); tor_free(reason);
1039 return -1;
1041 if (router_parse_runningrouters(body)<0) {
1042 log_warn(LD_DIR,
1043 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1044 conn->_base.address, conn->_base.port);
1045 tor_free(body); tor_free(headers); tor_free(reason);
1046 return -1;
1048 note_request(was_compressed?"dl/running-routers.z":
1049 "dl/running-routers", orig_len);
1052 if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
1053 smartlist_t *which = NULL;
1054 networkstatus_source_t source;
1055 char *cp;
1056 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1057 "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
1058 if (status_code != 200) {
1059 /* XXXX This warning tends to freak out clients who get a 403. */
1060 log_warn(LD_DIR,
1061 "Received http status code %d (%s) from server "
1062 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1063 status_code, escaped(reason), conn->_base.address,
1064 conn->_base.port, conn->requested_resource);
1065 tor_free(body); tor_free(headers); tor_free(reason);
1066 connection_dir_download_networkstatus_failed(conn, status_code);
1067 return -1;
1069 note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
1070 if (conn->requested_resource &&
1071 !strcmpstart(conn->requested_resource,"fp/")) {
1072 source = NS_FROM_DIR_BY_FP;
1073 which = smartlist_create();
1074 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1075 which, NULL, 0, 0);
1076 } else if (conn->requested_resource &&
1077 !strcmpstart(conn->requested_resource, "all")) {
1078 source = NS_FROM_DIR_ALL;
1079 which = smartlist_create();
1080 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1081 trusted_dir_server_t *, ds,
1083 char *cp = tor_malloc(HEX_DIGEST_LEN+1);
1084 base16_encode(cp, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1085 smartlist_add(which, cp);
1087 } else {
1088 /* Can we even end up here? -- weasel*/
1089 source = NS_FROM_DIR_BY_FP;
1090 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1091 "for it by fp, nor did we ask for all.");
1093 cp = body;
1094 while (*cp) {
1095 char *next = strstr(cp, "\nnetwork-status-version");
1096 if (next)
1097 next[1] = '\0';
1098 /* learn from it, and then remove it from 'which' */
1099 if (router_set_networkstatus(cp, time(NULL), source, which)<0)
1100 break;
1101 if (next) {
1102 next[1] = 'n';
1103 cp = next+1;
1105 else
1106 break;
1108 routers_update_all_from_networkstatus(); /*launches router downloads*/
1109 directory_info_has_arrived(time(NULL), 0);
1110 if (which) {
1111 if (smartlist_len(which)) {
1112 dir_networkstatus_download_failed(which, status_code);
1114 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1115 smartlist_free(which);
1119 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
1120 smartlist_t *which = NULL;
1121 int n_asked_for = 0;
1122 log_info(LD_DIR,"Received server info (size %d) from server '%s:%d'",
1123 (int)body_len, conn->_base.address, conn->_base.port);
1124 note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
1125 if (conn->requested_resource &&
1126 !strcmpstart(conn->requested_resource,"d/")) {
1127 which = smartlist_create();
1128 dir_split_resource_into_fingerprints(conn->requested_resource+2,
1129 which, NULL, 0, 0);
1130 n_asked_for = smartlist_len(which);
1132 if (status_code != 200) {
1133 int dir_okay = status_code == 404 ||
1134 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1135 /* 404 means that it didn't have them; no big deal.
1136 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1137 /* XXXX This warning tends to freak out clients who get a 403. */
1138 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1139 "Received http status code %d (%s) from server '%s:%d' "
1140 "while fetching \"/tor/server/%s\". I'll try again soon.",
1141 status_code, escaped(reason), conn->_base.address,
1142 conn->_base.port, conn->requested_resource);
1143 if (!which) {
1144 connection_dir_download_routerdesc_failed(conn);
1145 } else {
1146 dir_routerdesc_download_failed(which, status_code);
1147 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1148 smartlist_free(which);
1150 tor_free(body); tor_free(headers); tor_free(reason);
1151 return dir_okay ? 0 : -1;
1153 /* Learn the routers, assuming we requested by fingerprint or "all".
1154 * Right now, we only use "authority" to fetch ourself, so we don't want
1155 * to risk replacing ourself with a router running at the addr:port we
1156 * think we have.
1158 if (which || (conn->requested_resource &&
1159 !strcmpstart(conn->requested_resource, "all"))) {
1160 /* as we learn from them, we remove them from 'which' */
1161 router_load_routers_from_string(body, body_len, SAVED_NOWHERE, which);
1162 directory_info_has_arrived(time(NULL), 0);
1164 if (which) { /* mark remaining ones as failed */
1165 log_info(LD_DIR, "Received %d/%d routers requested from %s:%d",
1166 n_asked_for-smartlist_len(which), n_asked_for,
1167 conn->_base.address, (int)conn->_base.port);
1168 if (smartlist_len(which)) {
1169 dir_routerdesc_download_failed(which, status_code);
1171 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1172 smartlist_free(which);
1174 if (directory_conn_is_self_reachability_test(conn))
1175 router_dirport_found_reachable();
1178 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1179 switch (status_code) {
1180 case 200: {
1181 int all_done = 1;
1182 trusted_dir_server_t *ds =
1183 router_get_trusteddirserver_by_digest(conn->identity_digest);
1184 smartlist_t *servers;
1185 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1186 "descriptor: finished.");
1187 control_event_server_status(
1188 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1189 conn->_base.address, conn->_base.port);
1191 ds->has_accepted_serverdesc = 1;
1192 servers = router_get_trusted_dir_servers();
1193 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
1194 if ((d->is_v1_authority || d->is_v2_authority) &&
1195 !d->has_accepted_serverdesc) {
1196 all_done = 0;
1197 break;
1200 if (all_done)
1201 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1203 break;
1204 case 400:
1205 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1206 "dirserver '%s:%d'. Please correct.",
1207 escaped(reason), conn->_base.address, conn->_base.port);
1208 control_event_server_status(LOG_WARN,
1209 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1210 conn->_base.address, conn->_base.port, escaped(reason));
1211 break;
1212 case 403:
1213 log_warn(LD_GENERAL,
1214 "http status 403 (%s) response from dirserver "
1215 "'%s:%d'. Is your clock skewed? Have you mailed us your key "
1216 "fingerprint? Are you using the right key? Are you using a "
1217 "private IP address? See http://tor.eff.org/doc/"
1218 "tor-doc-server.html",escaped(reason), conn->_base.address,
1219 conn->_base.port);
1220 control_event_server_status(LOG_WARN,
1221 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1222 conn->_base.address, conn->_base.port, escaped(reason));
1223 break;
1224 default:
1225 log_warn(LD_GENERAL,
1226 "http status %d (%s) reason unexpected while uploading "
1227 "descriptor to server '%s:%d').",
1228 status_code, escaped(reason), conn->_base.address,
1229 conn->_base.port);
1230 break;
1232 /* return 0 in all cases, since we don't want to mark any
1233 * dirservers down just because they don't like us. */
1236 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1237 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1238 "(%s))",
1239 (int)body_len, status_code, escaped(reason));
1240 switch (status_code) {
1241 case 200:
1242 if (rend_cache_store(body, body_len) < 0) {
1243 log_warn(LD_REND,"Failed to store rendezvous descriptor.");
1244 /* alice's ap_stream will notice when connection_mark_for_close
1245 * cleans it up */
1246 } else {
1247 /* success. notify pending connections about this. */
1248 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1249 rend_client_desc_here(conn->rend_query);
1251 break;
1252 case 404:
1253 /* not there. pending connections will be notified when
1254 * connection_mark_for_close cleans it up. */
1255 break;
1256 case 400:
1257 log_warn(LD_REND,
1258 "http status 400 (%s). Dirserver didn't like our "
1259 "rendezvous query?", escaped(reason));
1260 break;
1261 default:
1262 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1263 "fetching hidden service descriptor (server '%s:%d').",
1264 status_code, escaped(reason), conn->_base.address,
1265 conn->_base.port);
1266 break;
1270 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
1271 switch (status_code) {
1272 case 200:
1273 log_info(LD_REND,
1274 "Uploading rendezvous descriptor: finished with status "
1275 "200 (%s)", escaped(reason));
1276 break;
1277 case 400:
1278 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1279 "'%s:%d'. Malformed rendezvous descriptor?",
1280 escaped(reason), conn->_base.address, conn->_base.port);
1281 break;
1282 default:
1283 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1284 "'%s:%d').",
1285 status_code, escaped(reason), conn->_base.address,
1286 conn->_base.port);
1287 break;
1290 tor_free(body); tor_free(headers); tor_free(reason);
1291 return 0;
1294 /** Called when a directory connection reaches EOF */
1296 connection_dir_reached_eof(dir_connection_t *conn)
1298 int retval;
1299 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
1300 log_info(LD_HTTP,"conn reached eof, not reading. Closing.");
1301 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
1302 connection_mark_for_close(TO_CONN(conn));
1303 return -1;
1306 retval = connection_dir_client_reached_eof(conn);
1307 if (retval == 0) /* success */
1308 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
1309 connection_mark_for_close(TO_CONN(conn));
1310 return retval;
1313 /** If any directory object is arriving, and it's over 10MB large, we're
1314 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1315 * ask for more than 96 router descriptors at a time.)
1317 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1319 /** Read handler for directory connections. (That's connections <em>to</em>
1320 * directory servers and connections <em>at</em> directory servers.)
1323 connection_dir_process_inbuf(dir_connection_t *conn)
1325 tor_assert(conn);
1326 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1328 /* Directory clients write, then read data until they receive EOF;
1329 * directory servers read data until they get an HTTP command, then
1330 * write their response (when it's finished flushing, they mark for
1331 * close).
1334 /* If we're on the dirserver side, look for a command. */
1335 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1336 if (directory_handle_command(conn) < 0) {
1337 connection_mark_for_close(TO_CONN(conn));
1338 return -1;
1340 return 0;
1343 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
1344 log_warn(LD_HTTP, "Too much data received from directory connection: "
1345 "denial of service attempt, or you need to upgrade?");
1346 connection_mark_for_close(TO_CONN(conn));
1347 return -1;
1350 if (!conn->_base.inbuf_reached_eof)
1351 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1352 return 0;
1355 /** Create an http response for the client <b>conn</b> out of
1356 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1358 static void
1359 write_http_status_line(dir_connection_t *conn, int status,
1360 const char *reason_phrase)
1362 char buf[256];
1363 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1364 status, reason_phrase ? reason_phrase : "OK") < 0) {
1365 log_warn(LD_BUG,"Bug: status line too long.");
1366 return;
1368 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
1371 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1372 * with <b>type</b> as the Content-Type.
1374 * If <b>length</b> is nonnegative, it is the Content-Length.
1375 * If <b>encoding</b> is provided, it is the Content-Encoding.
1376 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1377 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1378 static void
1379 write_http_response_header(dir_connection_t *conn, ssize_t length,
1380 const char *type, const char *encoding,
1381 int cache_lifetime)
1383 char date[RFC1123_TIME_LEN+1];
1384 char tmp[1024];
1385 char *cp;
1386 time_t now = time(NULL);
1388 tor_assert(conn);
1389 tor_assert(type);
1391 format_rfc1123_time(date, now);
1392 cp = tmp;
1393 tor_snprintf(cp, sizeof(tmp),
1394 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n",
1395 date, type);
1396 cp += strlen(tmp);
1397 if (!is_internal_IP(conn->_base.addr, 0)) {
1398 /* Don't report the source address for a localhost/private connection. */
1399 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1400 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
1401 cp += strlen(cp);
1403 if (encoding) {
1404 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1405 "Content-Encoding: %s\r\n", encoding);
1406 cp += strlen(cp);
1408 if (length >= 0) {
1409 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1410 "Content-Length: %ld\r\n", (long)length);
1411 cp += strlen(cp);
1413 if (cache_lifetime > 0) {
1414 char expbuf[RFC1123_TIME_LEN+1];
1415 format_rfc1123_time(expbuf, now + cache_lifetime);
1416 /* We could say 'Cache-control: max-age=%d' here if we start doing
1417 * http/1.1 */
1418 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1419 "Expires: %s\r\n", expbuf);
1420 cp += strlen(cp);
1421 } else {
1422 /* We could say 'Cache-control: no-cache' here if we start doing
1423 * http/1.1 */
1424 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
1425 cp += strlen(cp);
1427 if (sizeof(tmp)-(cp-tmp) > 3)
1428 memcpy(cp, "\r\n", 3);
1429 else
1430 tor_assert(0);
1431 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
1434 /** Helper function: return 1 if there are any dir conns of purpose
1435 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1436 * Else return 0.
1438 static int
1439 already_fetching_directory(int purpose)
1441 int i, n;
1442 connection_t *conn;
1443 connection_t **carray;
1445 get_connection_array(&carray,&n);
1446 for (i=0;i<n;i++) {
1447 conn = carray[i];
1448 if (conn->type == CONN_TYPE_DIR &&
1449 conn->purpose == purpose &&
1450 !conn->marked_for_close &&
1451 !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
1452 return 1;
1454 return 0;
1457 #undef INSTRUMENT_DOWNLOADS
1459 #ifdef INSTRUMENT_DOWNLOADS
1460 /** Map used to keep track of how much data we've up/downloaded in what kind
1461 * of request. Maps from request type to pointer to uint64_t. */
1462 static strmap_t *request_bytes_map = NULL;
1464 /** Called when we just transmitted or received <b>bytes</b> worth of data
1465 * because of a request of type <b>key</b> (an arbitrary identifier): adds
1466 * <b>bytes</b> to the total associated with key. */
1467 static void
1468 note_request(const char *key, size_t bytes)
1470 uint64_t *n;
1471 if (!request_bytes_map)
1472 request_bytes_map = strmap_new();
1474 n = strmap_get(request_bytes_map, key);
1475 if (!n) {
1476 n = tor_malloc_zero(sizeof(uint64_t));
1477 strmap_set(request_bytes_map, key, n);
1479 *n += bytes;
1482 /** Return a newly allocated string holding a summary of bytes used per
1483 * request type. */
1484 char *
1485 directory_dump_request_log(void)
1487 smartlist_t *lines;
1488 char tmp[256];
1489 char *result;
1490 strmap_iter_t *iter;
1492 if (!request_bytes_map)
1493 request_bytes_map = strmap_new();
1495 lines = smartlist_create();
1497 for (iter = strmap_iter_init(request_bytes_map);
1498 !strmap_iter_done(iter);
1499 iter = strmap_iter_next(request_bytes_map, iter)) {
1500 const char *key;
1501 void *val;
1502 uint64_t *n;
1503 strmap_iter_get(iter, &key, &val);
1504 n = val;
1505 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT"\n",
1506 key, U64_PRINTF_ARG(*n));
1507 smartlist_add(lines, tor_strdup(tmp));
1509 smartlist_sort_strings(lines);
1510 result = smartlist_join_strings(lines, "", 0, NULL);
1511 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
1512 smartlist_free(lines);
1513 return result;
1515 #else
1516 static void
1517 note_request(const char *key, size_t bytes)
1519 (void)key;
1520 (void)bytes;
1523 char *
1524 directory_dump_request_log(void)
1526 return tor_strdup("Not supported.");
1528 #endif
1530 /** Helper function: called when a dirserver gets a complete HTTP GET
1531 * request. Look for a request for a directory or for a rendezvous
1532 * service descriptor. On finding one, write a response into
1533 * conn-\>outbuf. If the request is unrecognized, send a 400.
1534 * Always return 0. */
1535 static int
1536 directory_handle_command_get(dir_connection_t *conn, const char *headers,
1537 const char *body, size_t body_len)
1539 size_t dlen;
1540 const char *cp;
1541 char *url = NULL;
1542 or_options_t *options = get_options();
1543 /* We ignore the body of a GET request. */
1544 (void)body;
1545 (void)body_len;
1547 log_debug(LD_DIRSERV,"Received GET command.");
1549 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
1551 if (parse_http_url(headers, &url) < 0) {
1552 write_http_status_line(conn, 400, "Bad request");
1553 return 0;
1555 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
1557 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir.z")) { /* dir fetch */
1558 int deflated = !strcmp(url,"/tor/dir.z");
1559 cached_dir_t *d = dirserv_get_directory();
1561 if (!d) {
1562 log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
1563 "don't have a good one yet. Sending 503 Dir not available.");
1564 write_http_status_line(conn, 503, "Directory unavailable");
1565 /* try to get a new one now */
1566 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR))
1567 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1);
1568 tor_free(url);
1569 return 0;
1571 dlen = deflated ? d->dir_z_len : d->dir_len;
1573 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
1574 log_info(LD_DIRSERV,
1575 "Client asked for the mirrored directory, but we've been "
1576 "writing too many bytes lately. Sending 503 Dir busy.");
1577 write_http_status_line(conn, 503, "Directory busy, try again later");
1578 tor_free(url);
1579 return 0;
1582 note_request(url, dlen);
1583 tor_free(url);
1585 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
1586 deflated?"deflated ":"");
1587 write_http_response_header(conn, dlen,
1588 deflated?"application/octet-stream":"text/plain",
1589 deflated?"deflate":"identity",
1590 FULL_DIR_CACHE_LIFETIME);
1591 conn->cached_dir = d;
1592 conn->cached_dir_offset = 0;
1593 if (! deflated)
1594 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
1595 ++d->refcnt;
1597 /* Prime the connection with some data. */
1598 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
1599 connection_dirserv_flushed_some(conn);
1600 return 0;
1603 if (!strcmp(url,"/tor/running-routers") ||
1604 !strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
1605 int deflated = !strcmp(url,"/tor/running-routers.z");
1606 dlen = dirserv_get_runningrouters(&cp, deflated);
1607 if (!dlen) { /* we failed to create/cache cp */
1608 write_http_status_line(conn, 503, "Directory unavailable");
1609 /* try to get a new one now */
1610 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST))
1611 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
1612 tor_free(url);
1613 return 0;
1615 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
1616 log_info(LD_DIRSERV,
1617 "Client asked for running-routers, but we've been "
1618 "writing too many bytes lately. Sending 503 Dir busy.");
1619 write_http_status_line(conn, 503, "Directory busy, try again later");
1620 tor_free(url);
1621 return 0;
1623 note_request(url, dlen);
1624 tor_free(url);
1625 write_http_response_header(conn, dlen,
1626 deflated?"application/octet-stream":"text/plain",
1627 deflated?"deflate":"identity",
1628 RUNNINGROUTERS_CACHE_LIFETIME);
1629 connection_write_to_buf(cp, strlen(cp), TO_CONN(conn));
1630 return 0;
1633 if (!strcmpstart(url,"/tor/status/")) {
1634 /* v2 network status fetch. */
1635 size_t url_len = strlen(url);
1636 int deflated = !strcmp(url+url_len-2, ".z");
1637 smartlist_t *dir_fps = smartlist_create();
1638 const char *request_type = NULL;
1639 const char *key = url + strlen("/tor/status/");
1640 if (deflated)
1641 url[url_len-2] = '\0';
1642 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
1643 if (!strcmpstart(key, "fp/"))
1644 request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
1645 else if (!strcmpstart(key, "authority"))
1646 request_type = deflated?"/tor/status/authority.z":
1647 "/tor/status/authority";
1648 else if (!strcmpstart(key, "all"))
1649 request_type = deflated?"/tor/status/all.z":"/tor/status/all";
1650 else
1651 request_type = "/tor/status/?";
1652 tor_free(url);
1653 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
1654 write_http_status_line(conn, 503, "Network status object unavailable");
1655 smartlist_free(dir_fps);
1656 return 0;
1658 dlen = dirserv_estimate_data_size(dir_fps, 0, deflated);
1659 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
1660 log_info(LD_DIRSERV,
1661 "Client asked for network status lists, but we've been "
1662 "writing too many bytes lately. Sending 503 Dir busy.");
1663 write_http_status_line(conn, 503, "Directory busy, try again later");
1664 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
1665 smartlist_free(dir_fps);
1666 return 0;
1669 // note_request(request_type,dlen);
1670 (void) request_type;
1671 write_http_response_header(conn, -1,
1672 deflated?"application/octet_stream":"text/plain",
1673 deflated?"deflate":NULL,
1674 smartlist_len(dir_fps) == 1 ? NETWORKSTATUS_CACHE_LIFETIME:0);
1675 conn->fingerprint_stack = dir_fps;
1676 if (! deflated)
1677 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
1679 /* Prime the connection with some data. */
1680 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
1681 connection_dirserv_flushed_some(conn);
1683 return 0;
1686 if (!strcmpstart(url,"/tor/server/")) {
1687 size_t url_len = strlen(url);
1688 int deflated = !strcmp(url+url_len-2, ".z");
1689 int res;
1690 const char *msg;
1691 const char *request_type = NULL;
1692 int cache_lifetime = 0;
1693 if (deflated)
1694 url[url_len-2] = '\0';
1695 conn->fingerprint_stack = smartlist_create();
1696 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
1697 &msg);
1699 if (!strcmpstart(url, "/tor/server/fp/")) {
1700 request_type = deflated?"/tor/server/fp.z":"/tor/server/fp";
1701 if (smartlist_len(conn->fingerprint_stack) == 1)
1702 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
1703 } else if (!strcmpstart(url, "/tor/server/authority")) {
1704 request_type = deflated?"/tor/server/authority.z":
1705 "/tor/server/authority";
1706 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
1707 } else if (!strcmpstart(url, "/tor/server/all")) {
1708 request_type = deflated?"/tor/server/all.z":"/tor/server/all";
1709 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
1710 } else if (!strcmpstart(url, "/tor/server/d/")) {
1711 request_type = deflated?"/tor/server/d.z":"/tor/server/d";
1712 if (smartlist_len(conn->fingerprint_stack) == 1)
1713 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
1714 } else {
1715 request_type = "/tor/server/?";
1717 (void) request_type; /* usable for note_request. */
1718 if (!strcmpstart(url, "/tor/server/d/"))
1719 conn->dir_spool_src = DIR_SPOOL_SERVER_BY_DIGEST;
1720 else
1721 conn->dir_spool_src = DIR_SPOOL_SERVER_BY_FP;
1722 tor_free(url);
1723 if (res < 0)
1724 write_http_status_line(conn, 404, msg);
1725 else {
1726 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
1727 1, deflated);
1728 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
1729 log_info(LD_DIRSERV,
1730 "Client asked for server descriptors, but we've been "
1731 "writing too many bytes lately. Sending 503 Dir busy.");
1732 write_http_status_line(conn, 503, "Directory busy, try again later");
1733 return 0;
1735 write_http_response_header(conn, -1,
1736 deflated?"application/octet_stream":"text/plain",
1737 deflated?"deflate":NULL, cache_lifetime);
1738 if (deflated)
1739 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
1740 /* Prime the connection with some data. */
1741 connection_dirserv_flushed_some(conn);
1743 return 0;
1746 if (options->HSAuthoritativeDir &&
1747 (!strcmpstart(url,"/tor/rendezvous/") ||
1748 !strcmpstart(url,"/tor/rendezvous1/"))) {
1749 /* rendezvous descriptor fetch */
1750 const char *descp;
1751 size_t desc_len;
1752 int versioned = !strcmpstart(url,"/tor/rendezvous1/");
1753 const char *query = url+strlen("/tor/rendezvous/")+(versioned?1:0);
1755 switch (rend_cache_lookup_desc(query, versioned?-1:0, &descp, &desc_len)) {
1756 case 1: /* valid */
1757 write_http_response_header(conn, desc_len, "application/octet-stream",
1758 NULL, 0);
1759 note_request("/tor/rendezvous?/", desc_len);
1760 /* need to send descp separately, because it may include nuls */
1761 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
1762 break;
1763 case 0: /* well-formed but not present */
1764 write_http_status_line(conn, 404, "Not found");
1765 break;
1766 case -1: /* not well-formed */
1767 write_http_status_line(conn, 400, "Bad request");
1768 break;
1770 tor_free(url);
1771 return 0;
1774 if (!strcmpstart(url,"/tor/bytes.txt")) {
1775 char *bytes = directory_dump_request_log();
1776 size_t len = strlen(bytes);
1777 write_http_response_header(conn, len, "text/plain", NULL, 0);
1778 connection_write_to_buf(bytes, len, TO_CONN(conn));
1779 tor_free(bytes);
1780 tor_free(url);
1781 return 0;
1784 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
1785 rewritten to /tor/robots.txt */
1786 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
1787 size_t len = strlen(robots);
1788 write_http_response_header(conn, len, "text/plain", NULL,
1789 ROBOTS_CACHE_LIFETIME);
1790 connection_write_to_buf(robots, len, TO_CONN(conn));
1791 tor_free(url);
1792 return 0;
1795 if (!strcmp(url,"/tor/dir-all-weaselhack") &&
1796 (conn->_base.addr == 0x7f000001ul) &&
1797 authdir_mode(options)) {
1798 /* until weasel rewrites his scripts at noreply */
1799 char *new_directory=NULL;
1801 if (dirserv_dump_directory_to_string(&new_directory,
1802 get_identity_key(), 1)) {
1803 log_warn(LD_BUG, "Error creating full v1 directory.");
1804 tor_free(new_directory);
1805 write_http_status_line(conn, 503, "Directory unavailable");
1806 return 0;
1809 dlen = strlen(new_directory);
1811 write_http_response_header(conn, dlen, "text/plain", "identity", 0);
1813 connection_write_to_buf(new_directory, dlen, TO_CONN(conn));
1814 tor_free(new_directory);
1815 tor_free(url);
1816 return 0;
1819 /* we didn't recognize the url */
1820 write_http_status_line(conn, 404, "Not found");
1821 tor_free(url);
1822 return 0;
1825 /** Helper function: called when a dirserver gets a complete HTTP POST
1826 * request. Look for an uploaded server descriptor or rendezvous
1827 * service descriptor. On finding one, process it and write a
1828 * response into conn-\>outbuf. If the request is unrecognized, send a
1829 * 400. Always return 0. */
1830 static int
1831 directory_handle_command_post(dir_connection_t *conn, const char *headers,
1832 const char *body, size_t body_len)
1834 char *url = NULL;
1835 or_options_t *options = get_options();
1837 log_debug(LD_DIRSERV,"Received POST command.");
1839 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
1841 if (!authdir_mode(options)) {
1842 /* we just provide cached directories; we don't want to
1843 * receive anything. */
1844 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
1845 "accept posted server descriptors");
1846 return 0;
1849 if (parse_http_url(headers, &url) < 0) {
1850 write_http_status_line(conn, 400, "Bad request");
1851 return 0;
1853 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
1855 if (!strcmp(url,"/tor/")) { /* server descriptor post */
1856 const char *msg = NULL;
1857 int r = dirserv_add_descriptor(body, &msg);
1858 tor_assert(msg);
1859 if (r > 0)
1860 dirserv_get_directory(); /* rebuild and write to disk */
1861 switch (r) {
1862 case -2:
1863 case -1:
1864 case 1:
1865 log_notice(LD_DIRSERV,"Rejected router descriptor from %s.",
1866 conn->_base.address);
1867 /* malformed descriptor, or something wrong */
1868 write_http_status_line(conn, 400, msg);
1869 break;
1870 case 0: /* accepted but discarded */
1871 case 2: /* accepted */
1872 write_http_status_line(conn, 200, msg);
1873 break;
1875 goto done;
1878 if (options->HSAuthoritativeDir &&
1879 !strcmpstart(url,"/tor/rendezvous/publish")) {
1880 /* rendezvous descriptor post */
1881 if (rend_cache_store(body, body_len) < 0) {
1882 // char tmp[1024*2+1];
1883 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
1884 "Rejected rend descriptor (length %d) from %s.",
1885 (int)body_len, conn->_base.address);
1886 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
1887 } else {
1888 write_http_status_line(conn, 200, "Service descriptor stored");
1890 goto done;
1893 /* we didn't recognize the url */
1894 write_http_status_line(conn, 404, "Not found");
1896 done:
1897 tor_free(url);
1898 return 0;
1901 /** Called when a dirserver receives data on a directory connection;
1902 * looks for an HTTP request. If the request is complete, remove it
1903 * from the inbuf, try to process it; otherwise, leave it on the
1904 * buffer. Return a 0 on success, or -1 on error.
1906 static int
1907 directory_handle_command(dir_connection_t *conn)
1909 char *headers=NULL, *body=NULL;
1910 size_t body_len=0;
1911 int r;
1913 tor_assert(conn);
1914 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1916 switch (fetch_from_buf_http(conn->_base.inbuf,
1917 &headers, MAX_HEADERS_SIZE,
1918 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
1919 case -1: /* overflow */
1920 log_warn(LD_DIRSERV,
1921 "Invalid input from address '%s'. Closing.",
1922 conn->_base.address);
1923 return -1;
1924 case 0:
1925 log_debug(LD_DIRSERV,"command not all here yet.");
1926 return 0;
1927 /* case 1, fall through */
1930 http_set_address_origin(headers, TO_CONN(conn));
1931 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
1933 if (!strncasecmp(headers,"GET",3))
1934 r = directory_handle_command_get(conn, headers, body, body_len);
1935 else if (!strncasecmp(headers,"POST",4))
1936 r = directory_handle_command_post(conn, headers, body, body_len);
1937 else {
1938 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
1939 "Got headers %s with unknown command. Closing.",
1940 escaped(headers));
1941 r = -1;
1944 tor_free(headers); tor_free(body);
1945 return r;
1948 /** Write handler for directory connections; called when all data has
1949 * been flushed. Close the connection or wait for a response as
1950 * appropriate.
1953 connection_dir_finished_flushing(dir_connection_t *conn)
1955 tor_assert(conn);
1956 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1958 switch (conn->_base.state) {
1959 case DIR_CONN_STATE_CLIENT_SENDING:
1960 log_debug(LD_DIR,"client finished sending command.");
1961 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
1962 connection_stop_writing(TO_CONN(conn));
1963 return 0;
1964 case DIR_CONN_STATE_SERVER_WRITING:
1965 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
1966 connection_mark_for_close(TO_CONN(conn));
1967 return 0;
1968 default:
1969 log_warn(LD_BUG,"Bug: called in unexpected state %d.",
1970 conn->_base.state);
1971 tor_fragile_assert();
1972 return -1;
1974 return 0;
1977 /** Connected handler for directory connections: begin sending data to the
1978 * server */
1980 connection_dir_finished_connecting(dir_connection_t *conn)
1982 tor_assert(conn);
1983 tor_assert(conn->_base.type == CONN_TYPE_DIR);
1984 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
1986 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
1987 conn->_base.address,conn->_base.port);
1989 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
1990 return 0;
1993 /** Called when one or more networkstatus fetches have failed (with uppercase
1994 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
1995 * failed once, unless they failed with status code 503. */
1996 static void
1997 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
1999 if (status_code == 503)
2000 return;
2001 SMARTLIST_FOREACH(failed, const char *, fp,
2003 char digest[DIGEST_LEN];
2004 trusted_dir_server_t *dir;
2005 base16_decode(digest, DIGEST_LEN, fp, strlen(fp));
2006 dir = router_get_trusteddirserver_by_digest(digest);
2008 if (dir)
2009 ++dir->n_networkstatus_failures;
2013 /** Called when one or more routerdesc fetches have failed (with uppercase
2014 * fingerprints listed in <b>failed</b>). */
2015 static void
2016 dir_routerdesc_download_failed(smartlist_t *failed, int status_code)
2018 time_t now = time(NULL);
2019 int server = server_mode(get_options()) && get_options()->DirPort;
2020 smartlist_t *routerstatuses, *digests = smartlist_create();
2022 SMARTLIST_FOREACH(failed, const char *, cp,
2024 char *d = tor_malloc(DIGEST_LEN);
2025 base16_decode(d, DIGEST_LEN, cp, strlen(cp));
2026 smartlist_add(digests, d);
2028 routerstatuses = router_get_combined_status_by_descriptor_digests(digests);
2029 SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
2030 smartlist_free(digests);
2032 SMARTLIST_FOREACH(routerstatuses, local_routerstatus_t *, rs, {
2033 if (!rs || rs->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
2034 continue;
2035 if (status_code != 503 || server)
2036 ++rs->n_download_failures;
2037 if (server) {
2038 switch (rs->n_download_failures) {
2039 case 0: rs->next_attempt_at = 0; break;
2040 case 1: rs->next_attempt_at = 0; break;
2041 case 2: rs->next_attempt_at = 0; break;
2042 case 3: rs->next_attempt_at = now+60; break;
2043 case 4: rs->next_attempt_at = now+60; break;
2044 case 5: rs->next_attempt_at = now+60*2; break;
2045 case 6: rs->next_attempt_at = now+60*5; break;
2046 case 7: rs->next_attempt_at = now+60*15; break;
2047 default: rs->next_attempt_at = TIME_MAX; break;
2049 } else {
2050 switch (rs->n_download_failures) {
2051 case 0: rs->next_attempt_at = 0; break;
2052 case 1: rs->next_attempt_at = 0; break;
2053 case 2: rs->next_attempt_at = now+60; break;
2054 case 3: rs->next_attempt_at = now+60*5; break;
2055 case 4: rs->next_attempt_at = now+60*10; break;
2056 default: rs->next_attempt_at = TIME_MAX; break;
2059 if (rs->next_attempt_at == 0)
2060 log_debug(LD_DIR, "dl failed %d time(s); I'll try again immediately.",
2061 (int)rs->n_download_failures);
2062 else if (rs->next_attempt_at < TIME_MAX)
2063 log_debug(LD_DIR, "dl failed %d time(s); I'll try again in %d seconds.",
2064 (int)rs->n_download_failures,
2065 (int)(rs->next_attempt_at-now));
2066 else
2067 log_debug(LD_DIR, "dl failed %d time(s); Giving up for a while.",
2068 (int)rs->n_download_failures);
2071 smartlist_free(routerstatuses);
2073 /* No need to relaunch descriptor downloads here: we already do it
2074 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
2077 /** Given a directory <b>resource</b> request, containing zero
2078 * or more strings separated by plus signs, followed optionally by ".z", store
2079 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
2080 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
2081 * decode_hex is true, then delete all elements that aren't hex digests, and
2082 * decode the rest. If sort_uniq is true, then sort the list and remove
2083 * all duplicates.
2086 dir_split_resource_into_fingerprints(const char *resource,
2087 smartlist_t *fp_out, int *compressed_out,
2088 int decode_hex, int sort_uniq)
2090 smartlist_t *fp_tmp = smartlist_create();
2091 tor_assert(fp_out);
2092 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
2093 if (compressed_out)
2094 *compressed_out = 0;
2095 if (smartlist_len(fp_tmp)) {
2096 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
2097 size_t last_len = strlen(last);
2098 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
2099 last[last_len-2] = '\0';
2100 if (compressed_out)
2101 *compressed_out = 1;
2104 if (decode_hex) {
2105 int i;
2106 char *cp, *d = NULL;
2107 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
2108 cp = smartlist_get(fp_tmp, i);
2109 if (strlen(cp) != HEX_DIGEST_LEN) {
2110 log_info(LD_DIR,
2111 "Skipping digest %s with non-standard length.", escaped(cp));
2112 smartlist_del_keeporder(fp_tmp, i--);
2113 goto again;
2115 d = tor_malloc_zero(DIGEST_LEN);
2116 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
2117 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
2118 smartlist_del_keeporder(fp_tmp, i--);
2119 goto again;
2121 smartlist_set(fp_tmp, i, d);
2122 d = NULL;
2123 again:
2124 tor_free(cp);
2125 tor_free(d);
2128 if (sort_uniq) {
2129 smartlist_t *fp_tmp2 = smartlist_create();
2130 int i;
2131 if (decode_hex)
2132 smartlist_sort_digests(fp_tmp);
2133 else
2134 smartlist_sort_strings(fp_tmp);
2135 if (smartlist_len(fp_tmp))
2136 smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
2137 for (i = 1; i < smartlist_len(fp_tmp); ++i) {
2138 char *cp = smartlist_get(fp_tmp, i);
2139 char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
2141 if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
2142 || (!decode_hex && strcasecmp(cp, last)))
2143 smartlist_add(fp_tmp2, cp);
2144 else
2145 tor_free(cp);
2147 smartlist_free(fp_tmp);
2148 fp_tmp = fp_tmp2;
2150 smartlist_add_all(fp_out, fp_tmp);
2151 smartlist_free(fp_tmp);
2152 return 0;