Fix memory leak when retrieving networkstatus or routerdesc by malformed fingerprint
[tor.git] / src / or / directory.c
blobaf6b9afc49674bb320752a22da2cc4415a662147
1 /* Copyright 2001-2004 Roger Dingledine.
2 * Copyright 2004-2005 Roger Dingledine, Nick Mathewson. */
3 /* See LICENSE for licensing information */
4 /* $Id$ */
5 const char directory_c_id[] = "$Id$";
7 #include "or.h"
9 /**
10 * \file directory.c
11 * \brief Code to send and fetch directories and router
12 * descriptors via HTTP. Directories use dirserv.c to generate the
13 * results; clients use routers.c to parse them.
14 **/
16 /* In-points to directory.c:
18 * - directory_post_to_dirservers(), called from
19 * router_upload_dir_desc_to_dirservers() in router.c
20 * upload_service_descriptor() in rendservice.c
21 * - directory_get_from_dirserver(), called from
22 * rend_client_refetch_renddesc() in rendclient.c
23 * run_scheduled_events() in main.c
24 * do_hup() in main.c
25 * - connection_dir_process_inbuf(), called from
26 * connection_process_inbuf() in connection.c
27 * - connection_dir_finished_flushing(), called from
28 * connection_finished_flushing() in connection.c
29 * - connection_dir_finished_connecting(), called from
30 * connection_finished_connecting() in connection.c
32 static void
33 directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
34 uint8_t purpose, int private_connection,
35 const char *resource,
36 const char *payload, size_t payload_len);
37 static void
38 directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
39 const char *platform,
40 const char *digest, uint8_t purpose,
41 int private_connection, const char *resource,
42 const char *payload, size_t payload_len);
44 static void
45 directory_send_command(connection_t *conn, const char *platform,
46 int purpose, const char *resource,
47 const char *payload, size_t payload_len);
48 static int directory_handle_command(connection_t *conn);
49 static int body_is_plausible(const char *body, size_t body_len, int purpose);
50 static int purpose_is_private(uint8_t purpose);
51 static char *http_get_header(const char *headers, const char *which);
52 static char *http_get_origin(const char *headers, connection_t *conn);
53 static void connection_dir_download_networkstatus_failed(connection_t *conn);
54 static void connection_dir_download_routerdesc_failed(connection_t *conn);
55 static void dir_networkstatus_download_failed(smartlist_t *failed);
56 static void dir_routerdesc_download_failed(smartlist_t *failed);
58 /********* START VARIABLES **********/
60 static addr_policy_t *dir_policy = NULL;
62 #define ALLOW_DIRECTORY_TIME_SKEW 30*60 /* 30 minutes */
64 /********* END VARIABLES ************/
66 /** Parse get_options()->DirPolicy, and put the processed version in
67 * &dir_policy. Ignore port specifiers.
69 void
70 parse_dir_policy(void)
72 addr_policy_t *n;
73 if (dir_policy) {
74 addr_policy_free(dir_policy);
75 dir_policy = NULL;
77 config_parse_addr_policy(get_options()->DirPolicy, &dir_policy, -1);
78 /* ports aren't used. */
79 for (n=dir_policy; n; n = n->next) {
80 n->prt_min = 1;
81 n->prt_max = 65535;
85 /** Free storage used to hold parsed directory policy */
86 void
87 free_dir_policy(void)
89 addr_policy_free(dir_policy);
90 dir_policy = NULL;
93 /** Return 1 if <b>addr</b> is permitted to connect to our dir port,
94 * based on <b>dir_policy</b>. Else return 0.
96 int
97 dir_policy_permits_address(uint32_t addr)
99 int a;
101 if (!dir_policy) /* 'no dir policy' means 'accept' */
102 return 1;
103 a = router_compare_addr_to_addr_policy(addr, 1, dir_policy);
104 if (a==ADDR_POLICY_REJECTED)
105 return 0;
106 else if (a==ADDR_POLICY_ACCEPTED)
107 return 1;
108 log_fn(LOG_WARN, "Bug: got unexpected 'maybe' answer from dir policy");
109 return 0;
112 /** Return true iff the directory purpose 'purpose' must use an
113 * anonymous connection to a directory. */
114 static int
115 purpose_is_private(uint8_t purpose)
117 if (purpose == DIR_PURPOSE_FETCH_DIR ||
118 purpose == DIR_PURPOSE_UPLOAD_DIR ||
119 purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
120 purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
121 purpose == DIR_PURPOSE_FETCH_SERVERDESC)
122 return 0;
123 return 1;
126 /** Start a connection to every known directory server, using
127 * connection purpose 'purpose' and uploading the payload 'payload'
128 * (length 'payload_len'). The purpose should be one of
129 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
131 void
132 directory_post_to_dirservers(uint8_t purpose, const char *payload,
133 size_t payload_len)
135 smartlist_t *dirservers;
137 router_get_trusted_dir_servers(&dirservers);
138 tor_assert(dirservers);
139 /* This tries dirservers which we believe to be down, but ultimately, that's
140 * harmless, and we may as well err on the side of getting things uploaded.
142 SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
144 /* Pay attention to fascistfirewall when we're uploading a
145 * router descriptor, but not when uploading a service
146 * descriptor -- those use Tor. */
147 if (purpose == DIR_PURPOSE_UPLOAD_DIR && !get_options()->HttpProxy) {
148 if (!fascist_firewall_allows_address(ds->addr,ds->dir_port))
149 continue;
151 directory_initiate_command_trusted_dir(ds, purpose,
152 purpose_is_private(purpose),
153 NULL, payload, payload_len);
157 /** Start a connection to a random running directory server, using
158 * connection purpose 'purpose' requesting 'resource'. The purpose
159 * should be one of 'DIR_PURPOSE_FETCH_DIR',
160 * 'DIR_PURPOSE_FETCH_RENDDESC', 'DIR_PURPOSE_FETCH_RUNNING_LIST.'
161 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
162 * down, mark them up and try again.
164 void
165 directory_get_from_dirserver(uint8_t purpose, const char *resource,
166 int retry_if_no_servers)
168 routerinfo_t *r = NULL;
169 trusted_dir_server_t *ds = NULL;
170 int fascistfirewall = firewall_is_fascist();
171 or_options_t *options = get_options();
172 int fetch_fresh_first = server_mode(options) && options->DirPort != 0;
173 int directconn = !purpose_is_private(purpose);
175 int need_v1_support = purpose == DIR_PURPOSE_FETCH_DIR ||
176 purpose == DIR_PURPOSE_FETCH_RUNNING_LIST;
177 int need_v2_support = purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
178 purpose == DIR_PURPOSE_FETCH_SERVERDESC;
180 if (directconn) {
181 if (fetch_fresh_first && purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS &&
182 !strcmpstart(resource,"fp/") && strlen(resource) == HEX_DIGEST_LEN+3) {
183 /* Try to ask the actual dirserver its opinion. */
184 char digest[DIGEST_LEN];
185 base16_decode(digest, DIGEST_LEN, resource+3, HEX_DIGEST_LEN);
186 ds = router_get_trusteddirserver_by_digest(digest);
188 if (!ds && fetch_fresh_first) {
189 /* only ask authdirservers, and don't ask myself */
190 ds = router_pick_trusteddirserver(need_v1_support, 1, fascistfirewall,
191 retry_if_no_servers);
193 if (!ds) {
194 /* anybody with a non-zero dirport will do */
195 r = router_pick_directory_server(1, fascistfirewall, need_v2_support,
196 retry_if_no_servers);
197 if (!r) {
198 const char *which;
199 if (purpose == DIR_PURPOSE_FETCH_DIR)
200 which = "directory";
201 else if (purpose == DIR_PURPOSE_FETCH_RUNNING_LIST)
202 which = "status list";
203 else if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
204 which = "network status";
205 else // if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
206 which = "server descriptors";
207 log_fn(LOG_INFO,
208 "No router found for %s; falling back to dirserver list",which);
209 ds = router_pick_trusteddirserver(1, 1, fascistfirewall,
210 retry_if_no_servers);
213 } else { // (purpose == DIR_PURPOSE_FETCH_RENDDESC)
214 /* only ask authdirservers, any of them will do */
215 /* Never use fascistfirewall; we're going via Tor. */
216 ds = router_pick_trusteddirserver(0, 0, 0, retry_if_no_servers);
219 if (r)
220 directory_initiate_command_router(r, purpose, !directconn,
221 resource, NULL, 0);
222 else if (ds)
223 directory_initiate_command_trusted_dir(ds, purpose, !directconn,
224 resource, NULL, 0);
225 else {
226 log_fn(LOG_NOTICE,"No running dirservers known. Will try again later. (purpose %d)",
227 purpose);
228 if (directconn) {
229 /* remember we tried them all and failed. */
230 directory_all_unreachable(time(NULL));
235 /** Launch a new connection to the directory server <b>router</b> to upload or
236 * download a service or rendezvous descriptor. <b>purpose</b> determines what
237 * kind of directory connection we're launching, and must be one of
238 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
240 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
241 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
243 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
244 * want to fetch.
246 void
247 directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
248 int private_connection, const char *resource,
249 const char *payload, size_t payload_len)
251 directory_initiate_command(router->address, router->addr, router->dir_port,
252 router->platform, router->identity_digest,
253 purpose, private_connection, resource,
254 payload, payload_len);
257 /** As directory_initiate_command_router, but send the command to a trusted
258 * directory server <b>dirserv</b>. **/
259 static void
260 directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
261 uint8_t purpose, int private_connection,
262 const char *resource,
263 const char *payload, size_t payload_len)
265 directory_initiate_command(dirserv->address, dirserv->addr,
266 dirserv->dir_port, NULL, dirserv->digest, purpose,
267 private_connection, resource,
268 payload, payload_len);
271 /** Called when we are unable to complete the client's request to a
272 * directory server: Mark the router as down and try again if possible.
274 void
275 connection_dir_request_failed(connection_t *conn)
277 if (router_digest_is_me(conn->identity_digest))
278 return; /* this was a test fetch. don't retry. */
279 router_mark_as_down(conn->identity_digest); /* don't try him again */
280 if (conn->purpose == DIR_PURPOSE_FETCH_DIR ||
281 conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
282 log_fn(LOG_INFO, "Giving up on directory server at '%s:%d'; retrying",
283 conn->address, conn->port);
284 directory_get_from_dirserver(conn->purpose, NULL,
285 0 /* don't retry_if_no_servers */);
286 } else if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
287 log_fn(LOG_INFO, "Giving up on directory server at '%s'; retrying",
288 conn->address);
289 connection_dir_download_networkstatus_failed(conn);
290 } else if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
291 log_fn(LOG_INFO, "Giving up on directory server at '%s'; retrying",
292 conn->address);
293 connection_dir_download_routerdesc_failed(conn);
297 /** Called when an attempt to download one or more network status
298 * documents on connection <b>conn</b> failed. Decide whether to
299 * retry the fetch now, later, or never.
301 static void
302 connection_dir_download_networkstatus_failed(connection_t *conn)
304 if (!conn->requested_resource) {
305 /* We never reached directory_send_command, which means that we never
306 * opened a network connection. Either we're out of sockets, or the
307 * network is down. Either way, retrying would be pointless. */
308 return;
310 if (!strcmpstart(conn->requested_resource, "all")) {
311 /* We're a non-authoritative directory cache; try again. */
312 directory_get_from_dirserver(conn->purpose, "all.z",
313 0 /* don't retry_if_no_servers */);
314 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
315 /* We were trying to download by fingerprint; mark them all has having
316 * failed, and possibly retry them later.*/
317 smartlist_t *failed = smartlist_create();
318 dir_split_resource_into_fingerprints(conn->requested_resource+3,
319 failed, NULL, 0);
320 if (smartlist_len(failed)) {
321 dir_networkstatus_download_failed(failed);
322 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
324 smartlist_free(failed);
328 /** Called when an attempt to download one or more router descriptors
329 * on connection <b>conn</b> failed.
331 static void
332 connection_dir_download_routerdesc_failed(connection_t *conn)
334 /* Try again. No need to increment the failure count for routerdescs, since
335 * it's not their fault.*/
336 /* update_router_descriptor_downloads(time(NULL)); */
339 /** Helper for directory_initiate_command_(router|trusted_dir): send the
340 * command to a server whose address is <b>address</b>, whose IP is
341 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version is
342 * <b>platform</b>, and whose identity key digest is <b>digest</b>. The
343 * <b>platform</b> argument is optional; the others are required. */
344 static void
345 directory_initiate_command(const char *address, uint32_t addr,
346 uint16_t dir_port, const char *platform,
347 const char *digest, uint8_t purpose,
348 int private_connection, const char *resource,
349 const char *payload, size_t payload_len)
351 connection_t *conn;
353 tor_assert(address);
354 tor_assert(addr);
355 tor_assert(dir_port);
356 tor_assert(digest);
358 switch (purpose) {
359 case DIR_PURPOSE_FETCH_DIR:
360 log_fn(LOG_DEBUG,"initiating directory fetch");
361 break;
362 case DIR_PURPOSE_FETCH_RENDDESC:
363 log_fn(LOG_DEBUG,"initiating hidden-service descriptor fetch");
364 break;
365 case DIR_PURPOSE_UPLOAD_DIR:
366 log_fn(LOG_DEBUG,"initiating server descriptor upload");
367 break;
368 case DIR_PURPOSE_UPLOAD_RENDDESC:
369 log_fn(LOG_DEBUG,"initiating hidden-service descriptor upload");
370 break;
371 case DIR_PURPOSE_FETCH_RUNNING_LIST:
372 log_fn(LOG_DEBUG,"initiating running-routers fetch");
373 break;
374 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
375 log_fn(LOG_DEBUG,"initiating network-status fetch");
376 break;
377 case DIR_PURPOSE_FETCH_SERVERDESC:
378 log_fn(LOG_DEBUG,"initiating server descriptor fetch");
379 break;
380 default:
381 log_fn(LOG_ERR, "Unrecognized directory connection purpose.");
382 tor_assert(0);
385 conn = connection_new(CONN_TYPE_DIR);
387 /* set up conn so it's got all the data we need to remember */
388 conn->addr = addr;
389 conn->port = dir_port;
390 conn->address = tor_strdup(address);
391 memcpy(conn->identity_digest, digest, DIGEST_LEN);
393 conn->purpose = purpose;
395 /* give it an initial state */
396 conn->state = DIR_CONN_STATE_CONNECTING;
398 if (!private_connection) {
399 /* then we want to connect directly */
401 if (get_options()->HttpProxy) {
402 addr = get_options()->HttpProxyAddr;
403 dir_port = get_options()->HttpProxyPort;
406 switch (connection_connect(conn, conn->address, addr, dir_port)) {
407 case -1:
408 connection_dir_request_failed(conn); /* retry if we want */
409 connection_free(conn);
410 return;
411 case 1:
412 conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
413 /* fall through */
414 case 0:
415 /* queue the command on the outbuf */
416 directory_send_command(conn, platform, purpose, resource,
417 payload, payload_len);
418 connection_watch_events(conn, EV_READ | EV_WRITE);
419 /* writable indicates finish, readable indicates broken link,
420 error indicates broken link in windowsland. */
422 } else { /* we want to connect via tor */
423 /* make an AP connection
424 * populate it and add it at the right state
425 * socketpair and hook up both sides
427 conn->s = connection_ap_make_bridge(conn->address, conn->port);
428 if (conn->s < 0) {
429 log_fn(LOG_WARN,"Making AP bridge to dirserver failed.");
430 connection_mark_for_close(conn);
431 return;
434 conn->state = DIR_CONN_STATE_CLIENT_SENDING;
435 connection_add(conn);
436 /* queue the command on the outbuf */
437 directory_send_command(conn, platform, purpose, resource,
438 payload, payload_len);
439 connection_watch_events(conn, EV_READ | EV_WRITE);
443 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
444 * are as in directory_initiate_command.
446 static void
447 directory_send_command(connection_t *conn, const char *platform,
448 int purpose, const char *resource,
449 const char *payload, size_t payload_len)
451 char proxystring[256];
452 char proxyauthstring[256];
453 char hoststring[128];
454 char *url;
455 char request[8192];
456 const char *httpcommand = NULL;
457 size_t len;
459 tor_assert(conn);
460 tor_assert(conn->type == CONN_TYPE_DIR);
462 tor_free(conn->requested_resource);
463 if (resource)
464 conn->requested_resource = tor_strdup(resource);
466 /* come up with a string for which Host: we want */
467 if (conn->port == 80) {
468 strlcpy(hoststring, conn->address, sizeof(hoststring));
469 } else {
470 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",conn->address, conn->port);
473 /* come up with some proxy lines, if we're using one. */
474 if (get_options()->HttpProxy) {
475 char *base64_authenticator=NULL;
476 const char *authenticator = get_options()->HttpProxyAuthenticator;
478 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
479 if (authenticator) {
480 base64_authenticator = alloc_http_authenticator(authenticator);
481 if (!base64_authenticator)
482 log_fn(LOG_WARN, "Encoding http authenticator failed");
484 if (base64_authenticator) {
485 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
486 "\r\nProxy-Authorization: Basic %s",
487 base64_authenticator);
488 tor_free(base64_authenticator);
489 } else {
490 proxyauthstring[0] = 0;
492 } else {
493 proxystring[0] = 0;
494 proxyauthstring[0] = 0;
497 switch (purpose) {
498 case DIR_PURPOSE_FETCH_DIR:
499 tor_assert(!resource);
500 tor_assert(!payload);
501 log_fn(LOG_DEBUG, "Asking for compressed directory from server running %s",
502 platform?platform:"<unknown version>");
503 httpcommand = "GET";
504 url = tor_strdup("/tor/dir.z");
505 break;
506 case DIR_PURPOSE_FETCH_RUNNING_LIST:
507 tor_assert(!resource);
508 tor_assert(!payload);
509 httpcommand = "GET";
510 url = tor_strdup("/tor/running-routers");
511 break;
512 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
513 httpcommand = "GET";
514 len = strlen(resource)+32;
515 url = tor_malloc(len);
516 tor_snprintf(url, len, "/tor/status/%s", resource);
517 break;
518 case DIR_PURPOSE_FETCH_SERVERDESC:
519 httpcommand = "GET";
520 len = strlen(resource)+32;
521 url = tor_malloc(len);
522 tor_snprintf(url, len, "/tor/server/%s", resource);
523 break;
524 case DIR_PURPOSE_UPLOAD_DIR:
525 tor_assert(!resource);
526 tor_assert(payload);
527 httpcommand = "POST";
528 url = tor_strdup("/tor/");
529 break;
530 case DIR_PURPOSE_FETCH_RENDDESC:
531 tor_assert(resource);
532 tor_assert(!payload);
534 /* this must be true or we wouldn't be doing the lookup */
535 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN);
536 /* This breaks the function abstraction. */
537 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
539 httpcommand = "GET";
540 /* Request the most recent versioned descriptor. */
541 // XXXX011
542 //tor_snprintf(url, sizeof(url), "/tor/rendezvous1/%s", resource);
543 len = strlen(resource)+32;
544 url = tor_malloc(len);
545 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
546 break;
547 case DIR_PURPOSE_UPLOAD_RENDDESC:
548 tor_assert(!resource);
549 tor_assert(payload);
550 httpcommand = "POST";
551 url = tor_strdup("/tor/rendezvous/publish");
552 break;
553 default:
554 tor_assert(0);
555 return;
557 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
558 connection_write_to_buf(request, strlen(request), conn);
559 connection_write_to_buf(url, strlen(url), conn);
560 tor_free(url);
562 tor_snprintf(request, sizeof(request), " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
563 payload ? (unsigned long)payload_len : 0,
564 hoststring,
565 proxyauthstring);
566 connection_write_to_buf(request, strlen(request), conn);
568 if (payload) {
569 /* then send the payload afterwards too */
570 connection_write_to_buf(payload, payload_len, conn);
574 /** Parse an HTTP request string <b>headers</b> of the form
575 * \verbatim
576 * "\%s [http[s]://]\%s HTTP/1..."
577 * \endverbatim
578 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
579 * null-terminate it. If the url doesn't start with "/tor/", rewrite it
580 * so it does. Return 0.
581 * Otherwise, return -1.
583 static int
584 parse_http_url(char *headers, char **url)
586 char *s, *start, *tmp;
588 s = (char *)eat_whitespace_no_nl(headers);
589 if (!*s) return -1;
590 s = (char *)find_whitespace(s); /* get past GET/POST */
591 if (!*s) return -1;
592 s = (char *)eat_whitespace_no_nl(s);
593 if (!*s) return -1;
594 start = s; /* this is it, assuming it's valid */
595 s = (char *)find_whitespace(start);
596 if (!*s) return -1;
598 /* tolerate the http[s] proxy style of putting the hostname in the url */
599 if (s-start >= 4 && !strcmpstart(start,"http")) {
600 tmp = start + 4;
601 if (*tmp == 's')
602 tmp++;
603 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
604 tmp = strchr(tmp+3, '/');
605 if (tmp && tmp < s) {
606 log_fn(LOG_DEBUG,"Skipping over 'http[s]://hostname' string");
607 start = tmp;
612 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
613 *url = tor_malloc(s - start + 5);
614 strlcpy(*url,"/tor", s-start+5);
615 strlcat((*url)+4, start, s-start+1);
616 } else {
617 *url = tor_strndup(start, s-start);
619 return 0;
622 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
623 * <b>which</b>. The key should be given with a terminating colon and space;
624 * this function copies everything after, up to but not including the
625 * following \\r\\n. */
626 static char *
627 http_get_header(const char *headers, const char *which)
629 const char *cp = headers;
630 while (cp) {
631 if (!strcmpstart(cp, which)) {
632 char *eos;
633 cp += strlen(which);
634 if ((eos = strchr(cp,'\r')))
635 return tor_strndup(cp, eos-cp);
636 else
637 return tor_strdup(cp);
639 cp = strchr(cp, '\n');
640 if (cp)
641 ++cp;
643 return NULL;
646 /** Allocate and return a string describing the source of an HTTP request with
647 * headers <b>headers</b> received on <b>conn</b>. The format is either
648 * "'1.2.3.4'", or "'1.2.3.4' (forwarded for '5.6.7.8')".
650 static char *
651 http_get_origin(const char *headers, connection_t *conn)
653 char *fwd;
655 fwd = http_get_header(headers, "Forwarded-For: ");
656 if (!fwd)
657 fwd = http_get_header(headers, "X-Forwarded-For: ");
658 if (fwd) {
659 size_t len = strlen(fwd)+strlen(conn->address)+32;
660 char *result = tor_malloc(len);
661 tor_snprintf(result, len, "'%s' (forwarded for '%s')", conn->address, fwd);
662 tor_free(fwd);
663 return result;
664 } else {
665 size_t len = strlen(conn->address)+3;
666 char *result = tor_malloc(len);
667 tor_snprintf(result, len, "'%s'", conn->address);
668 return result;
672 /** Parse an HTTP response string <b>headers</b> of the form
673 * \verbatim
674 * "HTTP/1.\%d \%d\%s\r\n...".
675 * \endverbatim
677 * If it's well-formed, assign the status code to *<b>code</b> and
678 * return 0. Otherwise, return -1.
680 * On success: If <b>date</b> is provided, set *date to the Date
681 * header in the http headers, or 0 if no such header is found. If
682 * <b>compression</b> is provided, set *<b>compression</b> to the
683 * compression method given in the Content-Encoding header, or 0 if no
684 * such header is found, or -1 if the value of the header is not
685 * recognized. If <b>reason</b> is provided, strdup the reason string
686 * into it.
689 parse_http_response(const char *headers, int *code, time_t *date,
690 int *compression, char **reason)
692 int n1, n2;
693 char datestr[RFC1123_TIME_LEN+1];
694 smartlist_t *parsed_headers;
695 tor_assert(headers);
696 tor_assert(code);
698 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
700 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
701 (n1 != 0 && n1 != 1) ||
702 (n2 < 100 || n2 >= 600)) {
703 log_fn(LOG_WARN,"Failed to parse header '%s'",headers);
704 return -1;
706 *code = n2;
708 parsed_headers = smartlist_create();
709 smartlist_split_string(parsed_headers, headers, "\n",
710 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
711 if (reason) {
712 smartlist_t *status_line_elements = smartlist_create();
713 tor_assert(smartlist_len(parsed_headers));
714 smartlist_split_string(status_line_elements,
715 smartlist_get(parsed_headers, 0),
716 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
717 tor_assert(smartlist_len(status_line_elements) <= 3);
718 if (smartlist_len(status_line_elements) == 3) {
719 *reason = smartlist_get(status_line_elements, 2);
720 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
722 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
723 smartlist_free(status_line_elements);
725 if (date) {
726 *date = 0;
727 SMARTLIST_FOREACH(parsed_headers, const char *, s,
728 if (!strcmpstart(s, "Date: ")) {
729 strlcpy(datestr, s+6, sizeof(datestr));
730 /* This will do nothing on failure, so we don't need to check
731 the result. We shouldn't warn, since there are many other valid
732 date formats besides the one we use. */
733 parse_rfc1123_time(datestr, date);
734 break;
737 if (compression) {
738 const char *enc = NULL;
739 SMARTLIST_FOREACH(parsed_headers, const char *, s,
740 if (!strcmpstart(s, "Content-Encoding: ")) {
741 enc = s+18; break;
743 if (!enc || !strcmp(enc, "identity")) {
744 *compression = 0;
745 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
746 *compression = ZLIB_METHOD;
747 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
748 *compression = GZIP_METHOD;
749 } else {
750 log_fn(LOG_INFO, "Unrecognized content encoding: '%s'. Trying to deal.", enc);
751 *compression = -1;
754 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
755 smartlist_free(parsed_headers);
757 return 0;
760 /** Return true iff <b>body</b> doesn't start with a plausible router or
761 * running-list or directory opening. This is a sign of possible compression.
763 static int
764 body_is_plausible(const char *body, size_t len, int purpose)
766 int i;
767 if (len == 0)
768 return 1; /* empty bodies don't need decompression */
769 if (len < 32)
770 return 0;
771 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
772 if (!strcmpstart(body,"router") ||
773 !strcmpstart(body,"signed-directory") ||
774 !strcmpstart(body,"network-status") ||
775 !strcmpstart(body,"running-routers"))
776 return 1;
777 for (i=0;i<32;++i) {
778 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
779 return 0;
781 return 1;
782 } else {
783 return 1;
787 /** We are a client, and we've finished reading the server's
788 * response. Parse and it and act appropriately.
790 * If we're happy with the result (we get it and it's useful),
791 * return 0. Otherwise return -1, and the caller should consider
792 * trying the request again.
794 * The caller will take care of marking the connection for close.
796 static int
797 connection_dir_client_reached_eof(connection_t *conn)
799 char *body;
800 char *headers;
801 char *reason = NULL;
802 size_t body_len=0;
803 int status_code;
804 time_t now, date_header=0;
805 int delta;
806 int compression;
807 int plausible;
808 int skewed=0;
809 int allow_partial = conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC;
811 switch (fetch_from_buf_http(conn->inbuf,
812 &headers, MAX_HEADERS_SIZE,
813 &body, &body_len, MAX_DIR_SIZE,
814 allow_partial)) {
815 case -1: /* overflow */
816 log_fn(LOG_WARN,"'fetch' response too large (server '%s:%d'). Closing.", conn->address, conn->port);
817 return -1;
818 case 0:
819 log_fn(LOG_INFO,"'fetch' response not all here, but we're at eof. Closing.");
820 return -1;
821 /* case 1, fall through */
824 if (parse_http_response(headers, &status_code, &date_header,
825 &compression, &reason) < 0) {
826 log_fn(LOG_WARN,"Unparseable headers (server '%s:%d'). Closing.", conn->address, conn->port);
827 tor_free(body); tor_free(headers);
828 return -1;
830 if (!reason) reason = tor_strdup("[no reason given]");
832 log_fn(LOG_DEBUG,
833 "Received response from directory server '%s:%d': %d \"%s\"",
834 conn->address, conn->port, status_code, reason);
836 if (date_header > 0) {
837 now = time(NULL);
838 delta = now-date_header;
839 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
840 log_fn(router_digest_is_trusted_dir(conn->identity_digest) ? LOG_WARN : LOG_INFO,
841 "Received directory with skewed time (server '%s:%d'): we are %d minutes %s, or the directory is %d minutes %s.",
842 conn->address, conn->port,
843 abs(delta)/60, delta>0 ? "ahead" : "behind",
844 abs(delta)/60, delta>0 ? "behind" : "ahead");
845 skewed = 1; /* don't check the recommended-versions line */
846 } else {
847 log_fn(LOG_DEBUG, "Time on received directory is within tolerance; we are %d seconds skewed. (That's okay.)", delta);
851 plausible = body_is_plausible(body, body_len, conn->purpose);
852 if (compression || !plausible) {
853 char *new_body = NULL;
854 size_t new_len = 0;
855 int guessed = detect_compression_method(body, body_len);
856 if (compression <= 0 || guessed != compression) {
857 /* Tell the user if we don't believe what we're told about compression.*/
858 const char *description1, *description2;
859 if (compression == ZLIB_METHOD)
860 description1 = "as deflated";
861 else if (compression == GZIP_METHOD)
862 description1 = "as gzipped";
863 else if (compression == 0)
864 description1 = "as uncompressed";
865 else
866 description1 = "with an unknown Content-Encoding";
867 if (guessed == ZLIB_METHOD)
868 description2 = "deflated";
869 else if (guessed == GZIP_METHOD)
870 description2 = "gzipped";
871 else if (!plausible)
872 description2 = "confusing binary junk";
873 else
874 description2 = "uncompressed";
876 log_fn(LOG_INFO, "HTTP body from server '%s:%d' was labeled %s, "
877 "but it seems to be %s.%s",
878 conn->address, conn->port, description1, description2,
879 (compression>0 && guessed>0)?" Trying both.":"");
881 /* Try declared compression first if we can. */
882 if (compression > 0)
883 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
884 allow_partial);
885 /* Okay, if that didn't work, and we think that it was compressed
886 * differently, try that. */
887 if (!new_body && guessed > 0 && compression != guessed)
888 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
889 allow_partial);
890 /* If we're pretty sure that we have a compressed directory, and
891 * we didn't manage to uncompress it, then warn and bail. */
892 if (!plausible && !new_body) {
893 log_fn(LOG_WARN, "Unable to decompress HTTP body (server '%s:%d').",
894 conn->address, conn->port);
895 tor_free(body); tor_free(headers); tor_free(reason);
896 return -1;
898 if (new_body) {
899 tor_free(body);
900 body = new_body;
901 body_len = new_len;
905 if (conn->purpose == DIR_PURPOSE_FETCH_DIR) {
906 /* fetch/process the directory to learn about new routers. */
907 log_fn(LOG_INFO,"Received directory (size %d) from server '%s:%d'",
908 (int)body_len, conn->address, conn->port);
909 if (status_code == 503 || body_len == 0) {
910 log_fn(LOG_INFO,"Empty directory; status %d (\"%s\") Ignoring.",
911 status_code, reason);
912 tor_free(body); tor_free(headers); tor_free(reason);
913 return -1;
915 if (status_code != 200) {
916 log_fn(LOG_WARN,"Received http status code %d (\"%s\") from server '%s:%d'. I'll try again soon.",
917 status_code, reason, conn->address, conn->port);
918 tor_free(body); tor_free(headers); tor_free(reason);
919 return -1;
921 if (router_parse_directory(body) < 0) {
922 log_fn(LOG_NOTICE,"I failed to parse the directory I fetched from '%s:%d'. Ignoring.", conn->address, conn->port);
926 if (conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
927 /* just update our list of running routers, if this list is new info */
928 log_fn(LOG_INFO,"Received running-routers list (size %d)", (int)body_len);
929 if (status_code != 200) {
930 log_fn(LOG_WARN,"Received http status code %d (\"%s\") from server '%s:%d'. I'll try again soon.",
931 status_code, reason, conn->address, conn->port);
932 tor_free(body); tor_free(headers); tor_free(reason);
933 return -1;
935 if (router_parse_runningrouters(body)<0) {
936 log_fn(LOG_WARN,"Bad running-routers from server '%s:%d'. I'll try again soon.",
937 conn->address, conn->port);
938 tor_free(body); tor_free(headers); tor_free(reason);
939 return -1;
943 if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
944 smartlist_t *which = NULL;
945 char *cp;
946 log_fn(LOG_INFO,"Received networkstatus objects (size %d) from server '%s:%d'",(int) body_len, conn->address, conn->port);
947 if (status_code != 200) {
948 log_fn(LOG_WARN,"Received http status code %d (\"%s\") from server '%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
949 status_code, reason, conn->address, conn->port,
950 conn->requested_resource);
951 tor_free(body); tor_free(headers); tor_free(reason);
952 connection_dir_download_networkstatus_failed(conn);
953 return -1;
955 if (conn->requested_resource &&
956 !strcmpstart(conn->requested_resource,"fp/")) {
957 which = smartlist_create();
958 dir_split_resource_into_fingerprints(conn->requested_resource+3,
959 which, NULL, 0);
961 cp = body;
962 while (*cp) {
963 char *next = strstr(cp, "\nnetwork-status-version");
964 if (next)
965 next[1] = '\0';
966 /* learn from it, and then remove it from 'which' */
967 if (router_set_networkstatus(cp, time(NULL), NS_FROM_DIR, which)<0)
968 break;
969 if (next) {
970 next[1] = 'n';
971 cp = next+1;
973 else
974 break;
976 routers_update_all_from_networkstatus(); /*launches router downloads*/
977 directory_info_has_arrived(time(NULL), 0);
978 if (which) {
979 if (smartlist_len(which)) {
980 dir_networkstatus_download_failed(which);
982 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
983 smartlist_free(which);
987 if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
988 smartlist_t *which = NULL;
989 int n_asked_for = 0;
990 log_fn(LOG_INFO,"Received server info (size %d) from server '%s:%d'",
991 (int)body_len, conn->address, conn->port);
992 if (conn->requested_resource &&
993 !strcmpstart(conn->requested_resource,"fp/")) {
994 which = smartlist_create();
995 dir_split_resource_into_fingerprints(conn->requested_resource+3,
996 which, NULL, 0);
997 n_asked_for = smartlist_len(which);
999 if (status_code != 200) {
1000 int no_warn = status_code == 404 ||
1001 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1002 /* 404 means that it didn't have them; no big deal.
1003 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1004 log_fn(no_warn ? LOG_INFO : LOG_WARN,
1005 "Received http status code %d (\"%s\") from server '%s:%d' while fetching \"/tor/server/%s\". I'll try again soon.",
1006 status_code, reason, conn->address, conn->port,
1007 conn->requested_resource);
1008 if (!which) {
1009 connection_dir_download_routerdesc_failed(conn);
1010 } else {
1011 dir_routerdesc_download_failed(which);
1012 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1013 smartlist_free(which);
1015 tor_free(body); tor_free(headers); tor_free(reason);
1016 return -1;
1018 /* Learn the routers, assuming we requested by fingerprint or "all".
1019 * Right now, we only use "authority" to fetch ourself, so we don't want
1020 * to risk replacing ourself with a router running at the addr:port we
1021 * think we have.
1023 if (which || (conn->requested_resource &&
1024 !strcmpstart(conn->requested_resource, "all"))) {
1025 /* as we learn from them, we remove them from 'which' */
1026 router_load_routers_from_string(body, 0, which);
1027 directory_info_has_arrived(time(NULL), 0);
1029 if (which) { /* mark remaining ones as failed */
1030 log_fn(LOG_INFO, "Received %d/%d routers requested from %s:%d",
1031 n_asked_for-smartlist_len(which), n_asked_for,
1032 conn->address, (int)conn->port);
1033 if (smartlist_len(which)) {
1034 dir_routerdesc_download_failed(which);
1036 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1037 smartlist_free(which);
1039 if (conn->requested_resource &&
1040 !strcmpstart(conn->requested_resource,"authority")) {
1041 /* this might have been a dirport reachability test. see if it is. */
1042 routerinfo_t *me = router_get_my_routerinfo();
1043 if (me &&
1044 !memcmp(me->identity_digest, conn->identity_digest, DIGEST_LEN) &&
1045 me->addr == conn->addr &&
1046 me->dir_port == conn->port)
1047 router_dirport_found_reachable();
1051 if (conn->purpose == DIR_PURPOSE_UPLOAD_DIR) {
1052 switch (status_code) {
1053 case 200:
1054 log_fn(LOG_INFO,"eof (status 200) after uploading server descriptor: finished.");
1055 break;
1056 case 400:
1057 log_fn(LOG_WARN,"http status 400 (\"%s\") response from dirserver '%s:%d'. Please correct.", reason, conn->address, conn->port);
1058 break;
1059 case 403:
1060 log_fn(LOG_WARN,"http status 403 (\"%s\") response from dirserver '%s:%d'. Is your clock skewed? Have you mailed us your key fingerprint? Are you using the right key? Are you using a private IP address? See http://tor.eff.org/doc/tor-doc-server.html", reason, conn->address, conn->port);
1061 break;
1062 default:
1063 log_fn(LOG_WARN,"http status %d (\"%s\") reason unexpected (server '%s:%d').", status_code, reason, conn->address, conn->port);
1064 break;
1066 /* return 0 in all cases, since we don't want to mark any
1067 * dirservers down just because they don't like us. */
1070 if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1071 log_fn(LOG_INFO,"Received rendezvous descriptor (size %d, status %d (\"%s\"))",
1072 (int)body_len, status_code, reason);
1073 switch (status_code) {
1074 case 200:
1075 if (rend_cache_store(body, body_len) < 0) {
1076 log_fn(LOG_WARN,"Failed to store rendezvous descriptor.");
1077 /* alice's ap_stream will notice when connection_mark_for_close
1078 * cleans it up */
1079 } else {
1080 /* success. notify pending connections about this. */
1081 conn->purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1082 rend_client_desc_here(conn->rend_query);
1084 break;
1085 case 404:
1086 /* not there. pending connections will be notified when
1087 * connection_mark_for_close cleans it up. */
1088 break;
1089 case 400:
1090 log_fn(LOG_WARN,"http status 400 (\"%s\"). Dirserver didn't like our rendezvous query?", reason);
1091 break;
1092 default:
1093 log_fn(LOG_WARN,"http status %d (\"%s\") response unexpected (server '%s:%d').", status_code, reason, conn->address, conn->port);
1094 break;
1098 if (conn->purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
1099 switch (status_code) {
1100 case 200:
1101 log_fn(LOG_INFO,"Uploading rendezvous descriptor: finished with status 200 (\"%s\")", reason);
1102 break;
1103 case 400:
1104 log_fn(LOG_WARN,"http status 400 (\"%s\") response from dirserver '%s:%d'. Malformed rendezvous descriptor?", reason, conn->address, conn->port);
1105 break;
1106 default:
1107 log_fn(LOG_WARN,"http status %d (\"%s\") response unexpected (server '%s:%d').", status_code, reason, conn->address, conn->port);
1108 break;
1111 tor_free(body); tor_free(headers); tor_free(reason);
1112 return 0;
1115 /** Called when a directory connection reaches EOF */
1117 connection_dir_reached_eof(connection_t *conn)
1119 int retval;
1120 if (conn->state != DIR_CONN_STATE_CLIENT_READING) {
1121 log_fn(LOG_INFO,"conn reached eof, not reading. Closing.");
1122 /* This check is temporary; it's to let us know whether we should consider
1123 * parsing partial serverdesc responses. */
1124 if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
1125 buf_datalen(conn->inbuf)>=(24*1024)) {
1126 log_fn(LOG_NOTICE, "Directory connection closed early after downloading %d bytes of descriptors. If this happens often, please file a bug report.",
1127 (int)buf_datalen(conn->inbuf));
1129 connection_close_immediate(conn); /* it was an error; give up on flushing */
1130 connection_mark_for_close(conn);
1131 return -1;
1134 retval = connection_dir_client_reached_eof(conn);
1135 if (retval == 0) /* success */
1136 conn->state = DIR_CONN_STATE_CLIENT_FINISHED;
1137 connection_mark_for_close(conn);
1138 return retval;
1141 /** Read handler for directory connections. (That's connections <em>to</em>
1142 * directory servers and connections <em>at</em> directory servers.)
1145 connection_dir_process_inbuf(connection_t *conn)
1147 tor_assert(conn);
1148 tor_assert(conn->type == CONN_TYPE_DIR);
1150 /* Directory clients write, then read data until they receive EOF;
1151 * directory servers read data until they get an HTTP command, then
1152 * write their response (when it's finished flushing, they mark for
1153 * close).
1156 /* If we're on the dirserver side, look for a command. */
1157 if (conn->state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1158 if (directory_handle_command(conn) < 0) {
1159 connection_mark_for_close(conn);
1160 return -1;
1162 return 0;
1165 /* XXX for READ states, might want to make sure inbuf isn't too big */
1167 log_fn(LOG_DEBUG,"Got data, not eof. Leaving on inbuf.");
1168 return 0;
1171 /** Create an http response for the client <b>conn</b> out of
1172 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1174 static void
1175 write_http_status_line(connection_t *conn, int status,
1176 const char *reason_phrase)
1178 char buf[256];
1179 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1180 status, reason_phrase) < 0) {
1181 log_fn(LOG_WARN,"Bug: status line too long.");
1182 return;
1184 connection_write_to_buf(buf, strlen(buf), conn);
1187 /** Helper function: return 1 if there are any dir conns of purpose
1188 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1189 * Else return 0.
1191 static int
1192 already_fetching_directory(int purpose)
1194 int i, n;
1195 connection_t *conn;
1196 connection_t **carray;
1198 get_connection_array(&carray,&n);
1199 for (i=0;i<n;i++) {
1200 conn = carray[i];
1201 if (conn->type == CONN_TYPE_DIR &&
1202 conn->purpose == purpose &&
1203 !conn->marked_for_close &&
1204 !router_digest_is_me(conn->identity_digest))
1205 return 1;
1207 return 0;
1210 /** Helper function: called when a dirserver gets a complete HTTP GET
1211 * request. Look for a request for a directory or for a rendezvous
1212 * service descriptor. On finding one, write a response into
1213 * conn-\>outbuf. If the request is unrecognized, send a 400.
1214 * Always return 0. */
1215 static int
1216 directory_handle_command_get(connection_t *conn, char *headers,
1217 char *body, size_t body_len)
1219 size_t dlen;
1220 const char *cp;
1221 char *url = NULL;
1222 char tmp[8192];
1223 char date[RFC1123_TIME_LEN+1];
1225 log_fn(LOG_DEBUG,"Received GET command.");
1227 conn->state = DIR_CONN_STATE_SERVER_WRITING;
1229 if (parse_http_url(headers, &url) < 0) {
1230 write_http_status_line(conn, 400, "Bad request");
1231 return 0;
1233 log_fn(LOG_DEBUG,"rewritten url as '%s'.", url);
1235 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir.z")) { /* directory fetch */
1236 int deflated = !strcmp(url,"/tor/dir.z");
1237 dlen = dirserv_get_directory(&cp, deflated);
1239 tor_free(url);
1241 if (dlen == 0) {
1242 log_fn(LOG_NOTICE,"Client asked for the mirrored directory, but we don't have a good one yet. Sending 503 Dir not available.");
1243 write_http_status_line(conn, 503, "Directory unavailable");
1244 /* try to get a new one now */
1245 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR))
1246 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1);
1247 return 0;
1250 log_fn(LOG_DEBUG,"Dumping %sdirectory to client.",
1251 deflated?"deflated ":"");
1252 format_rfc1123_time(date, time(NULL));
1253 tor_snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
1254 date,
1255 (int)dlen,
1256 deflated?"application/octet-stream":"text/plain",
1257 deflated?"deflate":"identity");
1258 connection_write_to_buf(tmp, strlen(tmp), conn);
1259 connection_write_to_buf(cp, dlen, conn);
1260 return 0;
1263 if (!strcmp(url,"/tor/running-routers") ||
1264 !strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
1265 int deflated = !strcmp(url,"/tor/running-routers.z");
1266 tor_free(url);
1267 dlen = dirserv_get_runningrouters(&cp, deflated);
1268 if (!dlen) { /* we failed to create/cache cp */
1269 write_http_status_line(conn, 503, "Directory unavailable");
1270 /* try to get a new one now */
1271 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST))
1272 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
1273 return 0;
1276 format_rfc1123_time(date, time(NULL));
1277 tor_snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
1278 date,
1279 (int)dlen,
1280 deflated?"application/octet-stream":"text/plain",
1281 deflated?"deflate":"identity");
1282 connection_write_to_buf(tmp, strlen(tmp), conn);
1283 connection_write_to_buf(cp, strlen(cp), conn);
1284 return 0;
1287 if (!strcmpstart(url,"/tor/status/")) {
1288 /* v2 network status fetch. */
1289 size_t url_len = strlen(url);
1290 int deflated = !strcmp(url+url_len-2, ".z");
1291 smartlist_t *dir_objs = smartlist_create();
1292 const char *key = url + strlen("/tor/status/");
1293 if (deflated)
1294 url[url_len-2] = '\0';
1295 if (dirserv_get_networkstatus_v2(dir_objs, key)) {
1296 smartlist_free(dir_objs);
1297 return 0;
1299 tor_free(url);
1300 if (!smartlist_len(dir_objs)) { /* we failed to create/cache cp */
1301 write_http_status_line(conn, 503, "Network status object unavailable");
1302 smartlist_free(dir_objs);
1303 return 0;
1305 dlen = 0;
1306 SMARTLIST_FOREACH(dir_objs, cached_dir_t *, d,
1307 dlen += deflated?d->dir_z_len:d->dir_len);
1308 format_rfc1123_time(date, time(NULL));
1309 tor_snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
1310 date,
1311 (int)dlen,
1312 deflated?"application/octet-stream":"text/plain",
1313 deflated?"deflate":"identity");
1314 connection_write_to_buf(tmp, strlen(tmp), conn);
1315 SMARTLIST_FOREACH(dir_objs, cached_dir_t *, d,
1317 if (deflated)
1318 connection_write_to_buf(d->dir_z, d->dir_z_len, conn);
1319 else
1320 connection_write_to_buf(d->dir, d->dir_len, conn);
1322 smartlist_free(dir_objs);
1323 return 0;
1326 if (!strcmpstart(url,"/tor/server/")) {
1327 size_t url_len = strlen(url);
1328 int deflated = !strcmp(url+url_len-2, ".z");
1329 int res;
1330 const char *msg;
1331 smartlist_t *descs = smartlist_create();
1332 if (deflated)
1333 url[url_len-2] = '\0';
1334 res = dirserv_get_routerdescs(descs, url, &msg);
1335 tor_free(url);
1336 if (res < 0)
1337 write_http_status_line(conn, 404, msg);
1338 else {
1339 size_t len = 0;
1340 format_rfc1123_time(date, time(NULL));
1341 SMARTLIST_FOREACH(descs, routerinfo_t *, ri,
1342 len += ri->signed_descriptor_len);
1343 if (deflated) {
1344 size_t compressed_len;
1345 char *compressed;
1346 char *inp = tor_malloc(len+smartlist_len(descs)+1);
1347 char *cp = inp;
1348 SMARTLIST_FOREACH(descs, routerinfo_t *, ri,
1350 memcpy(cp, ri->signed_descriptor,
1351 ri->signed_descriptor_len);
1352 cp += ri->signed_descriptor_len;
1353 *cp++ = '\n';
1355 *cp = '\0';
1356 /* XXXX This could be way more efficiently handled; let's see if it
1357 * shows up under oprofile. */
1358 if (tor_gzip_compress(&compressed, &compressed_len,
1359 inp, cp-inp, ZLIB_METHOD)<0) {
1360 tor_free(inp);
1361 smartlist_free(descs);
1362 return -1;
1364 tor_free(inp);
1365 tor_snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: application/octet-stream\r\nContent-Encoding: deflate\r\n\r\n",
1366 date,
1367 (int)compressed_len);
1368 connection_write_to_buf(tmp, strlen(tmp), conn);
1369 connection_write_to_buf(compressed, compressed_len, conn);
1370 tor_free(compressed);
1371 } else {
1372 tor_snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: text/plain\r\n\r\n",
1373 date,
1374 (int)len);
1375 connection_write_to_buf(tmp, strlen(tmp), conn);
1376 SMARTLIST_FOREACH(descs, routerinfo_t *, ri,
1377 connection_write_to_buf(ri->signed_descriptor,
1378 ri->signed_descriptor_len,
1379 conn));
1382 smartlist_free(descs);
1383 return 0;
1386 if (!strcmpstart(url,"/tor/rendezvous/") ||
1387 !strcmpstart(url,"/tor/rendezvous1/")) {
1388 /* rendezvous descriptor fetch */
1389 const char *descp;
1390 size_t desc_len;
1391 int versioned = !strcmpstart(url,"/tor/rendezvous1/");
1392 const char *query = url+strlen("/tor/rendezvous/")+(versioned?1:0);
1394 if (!authdir_mode(get_options())) {
1395 /* We don't hand out rend descs. In fact, it could be a security
1396 * risk, since rend_cache_lookup_desc() below would provide it
1397 * if we're gone to the site recently, and 404 if we haven't.
1399 * Reject. */
1400 write_http_status_line(conn, 400, "Nonauthoritative directory does not not store rendezvous descriptors");
1401 tor_free(url);
1402 return 0;
1404 switch (rend_cache_lookup_desc(query, versioned?-1:0, &descp, &desc_len)) {
1405 case 1: /* valid */
1406 format_rfc1123_time(date, time(NULL));
1407 tor_snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: application/octet-stream\r\n\r\n",
1408 date,
1409 (int)desc_len); /* can't include descp here, because it's got nuls */
1410 connection_write_to_buf(tmp, strlen(tmp), conn);
1411 connection_write_to_buf(descp, desc_len, conn);
1412 break;
1413 case 0: /* well-formed but not present */
1414 write_http_status_line(conn, 404, "Not found");
1415 break;
1416 case -1: /* not well-formed */
1417 write_http_status_line(conn, 400, "Bad request");
1418 break;
1420 tor_free(url);
1421 return 0;
1424 /* we didn't recognize the url */
1425 write_http_status_line(conn, 404, "Not found");
1426 tor_free(url);
1427 return 0;
1430 /** Helper function: called when a dirserver gets a complete HTTP POST
1431 * request. Look for an uploaded server descriptor or rendezvous
1432 * service descriptor. On finding one, process it and write a
1433 * response into conn-\>outbuf. If the request is unrecognized, send a
1434 * 400. Always return 0. */
1435 static int
1436 directory_handle_command_post(connection_t *conn, char *headers,
1437 char *body, size_t body_len)
1439 const char *cp;
1440 char *origin = NULL;
1441 char *url = NULL;
1443 log_fn(LOG_DEBUG,"Received POST command.");
1445 conn->state = DIR_CONN_STATE_SERVER_WRITING;
1447 if (!authdir_mode(get_options())) {
1448 /* we just provide cached directories; we don't want to
1449 * receive anything. */
1450 write_http_status_line(conn, 400, "Nonauthoritative directory does not accept posted server descriptors");
1451 return 0;
1454 if (parse_http_url(headers, &url) < 0) {
1455 write_http_status_line(conn, 400, "Bad request");
1456 return 0;
1458 log_fn(LOG_DEBUG,"rewritten url as '%s'.", url);
1459 origin = http_get_origin(headers, conn);
1461 if (!strcmp(url,"/tor/")) { /* server descriptor post */
1462 const char *msg;
1463 int r = dirserv_add_descriptor(body, &msg);
1464 tor_assert(msg);
1465 if (r > 0)
1466 dirserv_get_directory(&cp, 0); /* rebuild and write to disk */
1467 switch (r) {
1468 case -2:
1469 case -1:
1470 case 1:
1471 log_fn(LOG_NOTICE,"Rejected descriptor from %s.", origin);
1472 /* malformed descriptor, or something wrong */
1473 write_http_status_line(conn, 400, msg);
1474 break;
1475 case 0: /* accepted but discarded */
1476 case 2: /* accepted */
1477 write_http_status_line(conn, 200, msg);
1478 break;
1480 goto done;
1483 if (!strcmpstart(url,"/tor/rendezvous/publish")) {
1484 /* rendezvous descriptor post */
1485 if (rend_cache_store(body, body_len) < 0)
1486 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
1487 else
1488 write_http_status_line(conn, 200, "Service descriptor stored");
1489 goto done;
1492 /* we didn't recognize the url */
1493 write_http_status_line(conn, 404, "Not found");
1495 done:
1496 tor_free(url);
1497 tor_free(origin);
1498 return 0;
1502 /** Called when a dirserver receives data on a directory connection;
1503 * looks for an HTTP request. If the request is complete, remove it
1504 * from the inbuf, try to process it; otherwise, leave it on the
1505 * buffer. Return a 0 on success, or -1 on error.
1507 static int
1508 directory_handle_command(connection_t *conn)
1510 char *headers=NULL, *body=NULL;
1511 size_t body_len=0;
1512 int r;
1514 tor_assert(conn);
1515 tor_assert(conn->type == CONN_TYPE_DIR);
1517 switch (fetch_from_buf_http(conn->inbuf,
1518 &headers, MAX_HEADERS_SIZE,
1519 &body, &body_len, MAX_BODY_SIZE, 0)) {
1520 case -1: /* overflow */
1521 log_fn(LOG_WARN,"Invalid input from address '%s'. Closing.", conn->address);
1522 return -1;
1523 case 0:
1524 log_fn(LOG_DEBUG,"command not all here yet.");
1525 return 0;
1526 /* case 1, fall through */
1529 log_fn(LOG_DEBUG,"headers '%s', body '%s'.", headers, body);
1531 if (!strncasecmp(headers,"GET",3))
1532 r = directory_handle_command_get(conn, headers, body, body_len);
1533 else if (!strncasecmp(headers,"POST",4))
1534 r = directory_handle_command_post(conn, headers, body, body_len);
1535 else {
1536 log_fn(LOG_WARN,"Got headers '%s' with unknown command. Closing.", headers);
1537 r = -1;
1540 tor_free(headers); tor_free(body);
1541 return r;
1544 /** Write handler for directory connections; called when all data has
1545 * been flushed. Close the connection or wait for a response as
1546 * appropriate.
1549 connection_dir_finished_flushing(connection_t *conn)
1551 tor_assert(conn);
1552 tor_assert(conn->type == CONN_TYPE_DIR);
1554 switch (conn->state) {
1555 case DIR_CONN_STATE_CLIENT_SENDING:
1556 log_fn(LOG_DEBUG,"client finished sending command.");
1557 conn->state = DIR_CONN_STATE_CLIENT_READING;
1558 connection_stop_writing(conn);
1559 return 0;
1560 case DIR_CONN_STATE_SERVER_WRITING:
1561 log_fn(LOG_DEBUG,"Finished writing server response. Closing.");
1562 connection_mark_for_close(conn);
1563 return 0;
1564 default:
1565 log_fn(LOG_WARN,"Bug: called in unexpected state %d.", conn->state);
1566 tor_fragile_assert();
1567 return -1;
1569 return 0;
1572 /** Connected handler for directory connections: begin sending data to the
1573 * server */
1575 connection_dir_finished_connecting(connection_t *conn)
1577 tor_assert(conn);
1578 tor_assert(conn->type == CONN_TYPE_DIR);
1579 tor_assert(conn->state == DIR_CONN_STATE_CONNECTING);
1581 log_fn(LOG_DEBUG,"Dir connection to router %s:%u established.",
1582 conn->address,conn->port);
1584 conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
1585 return 0;
1588 /** Called when one or more networkstatus fetches have failed (with uppercase
1589 * fingerprints listed in <b>failed</>). Mark those fingerprints has having
1590 * failed once. */
1591 static void
1592 dir_networkstatus_download_failed(smartlist_t *failed)
1594 SMARTLIST_FOREACH(failed, const char *, fp,
1596 char digest[DIGEST_LEN];
1597 trusted_dir_server_t *dir;
1598 base16_decode(digest, DIGEST_LEN, fp, strlen(fp));
1599 dir = router_get_trusteddirserver_by_digest(digest);
1601 ++dir->n_networkstatus_failures;
1605 /** Called when one or more networkstatus fetches have failed (with uppercase
1606 * fingerprints listed in <b>failed</>). */
1607 static void
1608 dir_routerdesc_download_failed(smartlist_t *failed)
1610 char digest[DIGEST_LEN];
1611 local_routerstatus_t *rs;
1612 time_t now = time(NULL);
1613 int server = server_mode(get_options()) && get_options()->DirPort;
1614 SMARTLIST_FOREACH(failed, const char *, cp,
1616 base16_decode(digest, DIGEST_LEN, cp, strlen(cp));
1617 rs = router_get_combined_status_by_digest(digest);
1618 if (!rs || rs->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
1619 continue;
1620 ++rs->n_download_failures;
1621 if (server) {
1622 switch (rs->n_download_failures) {
1623 case 1: rs->next_attempt_at = 0; break;
1624 case 2: rs->next_attempt_at = 0; break;
1625 case 3: rs->next_attempt_at = now+60; break;
1626 case 4: rs->next_attempt_at = now+60; break;
1627 case 5: rs->next_attempt_at = now+60*2; break;
1628 case 6: rs->next_attempt_at = now+60*5; break;
1629 case 7: rs->next_attempt_at = now+60*15; break;
1630 default: rs->next_attempt_at = TIME_MAX; break;
1632 } else {
1633 switch (rs->n_download_failures) {
1634 case 1: rs->next_attempt_at = 0; break;
1635 case 2: rs->next_attempt_at = now+60; break;
1636 case 3: rs->next_attempt_at = now+60*5; break;
1637 case 4: rs->next_attempt_at = now+60*10; break;
1638 default: rs->next_attempt_at = TIME_MAX; break;
1641 if (rs->next_attempt_at == 0)
1642 log_fn(LOG_DEBUG, "%s failed %d time(s); I'll try again immediately.",
1643 cp, (int)rs->n_download_failures);
1644 else if (rs->next_attempt_at < TIME_MAX)
1645 log_fn(LOG_DEBUG, "%s failed %d time(s); I'll try again in %d seconds.",
1646 cp, (int)rs->n_download_failures, (int)(rs->next_attempt_at-now));
1647 else
1648 log_fn(LOG_DEBUG, "%s failed %d time(s); Giving up for a while.",
1649 cp, (int)rs->n_download_failures);
1652 /* update_router_descriptor_downloads(time(NULL)); */
1655 /* Given a directory <b>resource</b> request generated by us, containing zero
1656 * or more strings separated by plus signs, followed optionally by ".z", store
1657 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
1658 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
1659 * decode_hex is true, then delete all elements that aren't hex digests, and
1660 * decode the rest.
1663 dir_split_resource_into_fingerprints(const char *resource,
1664 smartlist_t *fp_out, int *compressed_out,
1665 int decode_hex)
1667 smartlist_split_string(fp_out, resource, "+", 0, 0);
1668 if (compressed_out)
1669 *compressed_out = 0;
1670 if (smartlist_len(fp_out)) {
1671 char *last = smartlist_get(fp_out,smartlist_len(fp_out)-1);
1672 size_t last_len = strlen(last);
1673 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
1674 last[last_len-2] = '\0';
1675 if (compressed_out)
1676 *compressed_out = 1;
1679 if (decode_hex) {
1680 int i;
1681 char *cp, *d = NULL;
1682 for (i = 0; i < smartlist_len(fp_out); ++i) {
1683 cp = smartlist_get(fp_out, i);
1684 if (strlen(cp) != HEX_DIGEST_LEN) {
1685 smartlist_del(fp_out, i--);
1686 goto again;
1688 d = tor_malloc_zero(DIGEST_LEN);
1689 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
1690 smartlist_del(fp_out, i--);
1691 goto again;
1693 smartlist_set(fp_out, i, d);
1694 d = NULL;
1695 again:
1696 tor_free(cp);
1697 tor_free(d);
1700 return 0;