1 /* Copyright 2001-2004 Roger Dingledine.
2 * Copyright 2004-2006 Roger Dingledine, Nick Mathewson. */
3 /* See LICENSE for licensing information */
5 const char directory_c_id
[] =
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.
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
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
34 directory_initiate_command(const char *address
, uint32_t addr
, uint16_t port
,
36 const char *digest
, uint8_t purpose
,
37 int private_connection
, const char *resource
,
38 const char *payload
, size_t payload_len
);
41 directory_send_command(connection_t
*conn
, const char *platform
,
42 int purpose
, const char *resource
,
43 const char *payload
, size_t payload_len
);
44 static int directory_handle_command(connection_t
*conn
);
45 static int body_is_plausible(const char *body
, size_t body_len
, int purpose
);
46 static int purpose_is_private(uint8_t purpose
);
47 static char *http_get_header(const char *headers
, const char *which
);
48 static char *http_get_origin(const char *headers
, connection_t
*conn
);
49 static void connection_dir_download_networkstatus_failed(connection_t
*conn
);
50 static void connection_dir_download_routerdesc_failed(connection_t
*conn
);
51 static void dir_networkstatus_download_failed(smartlist_t
*failed
);
52 static void dir_routerdesc_download_failed(smartlist_t
*failed
);
53 static void note_request(const char *key
, size_t bytes
);
55 /********* START VARIABLES **********/
57 /** How far in the future do we allow a directory server to tell us it is
58 * before deciding that one of us has the wrong time? */
59 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
61 /********* END VARIABLES ************/
63 /** Return true iff the directory purpose 'purpose' must use an
64 * anonymous connection to a directory. */
66 purpose_is_private(uint8_t purpose
)
68 if (get_options()->AllDirActionsPrivate
)
70 if (purpose
== DIR_PURPOSE_FETCH_DIR
||
71 purpose
== DIR_PURPOSE_UPLOAD_DIR
||
72 purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
||
73 purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
||
74 purpose
== DIR_PURPOSE_FETCH_SERVERDESC
)
79 /** Start a connection to every known directory server, using
80 * connection purpose 'purpose' and uploading the payload 'payload'
81 * (length 'payload_len'). The purpose should be one of
82 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
85 directory_post_to_dirservers(uint8_t purpose
, const char *payload
,
88 smartlist_t
*dirservers
;
92 dirservers
= router_get_trusted_dir_servers();
93 tor_assert(dirservers
);
94 /* Only old dirservers handle rendezvous descriptor publishing. */
95 post_to_v1_only
= (purpose
== DIR_PURPOSE_UPLOAD_RENDDESC
);
96 /* This tries dirservers which we believe to be down, but ultimately, that's
97 * harmless, and we may as well err on the side of getting things uploaded.
99 SMARTLIST_FOREACH(dirservers
, trusted_dir_server_t
*, ds
,
101 routerstatus_t
*rs
= &(ds
->fake_status
);
102 if (post_to_v1_only
&& !ds
->is_v1_authority
)
104 post_via_tor
= purpose_is_private(purpose
) ||
105 !fascist_firewall_allows_address_dir(ds
->addr
, ds
->dir_port
);
106 directory_initiate_command_routerstatus(rs
, purpose
, post_via_tor
,
107 NULL
, payload
, payload_len
);
111 /** Start a connection to a random running directory server, using
112 * connection purpose 'purpose' and requesting 'resource'.
113 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
114 * down, mark them up and try again.
117 directory_get_from_dirserver(uint8_t purpose
, const char *resource
,
118 int retry_if_no_servers
)
120 routerstatus_t
*rs
= NULL
;
121 or_options_t
*options
= get_options();
122 int prefer_authority
= server_mode(options
) && options
->DirPort
!= 0;
123 int directconn
= !purpose_is_private(purpose
);
125 int need_v1_support
= purpose
== DIR_PURPOSE_FETCH_DIR
||
126 purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
||
127 purpose
== DIR_PURPOSE_FETCH_RENDDESC
;
128 int need_v2_support
= purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
||
129 purpose
== DIR_PURPOSE_FETCH_SERVERDESC
;
131 if (!options
->FetchServerDescriptors
&&
132 (need_v1_support
|| need_v2_support
))
136 if (prefer_authority
) {
137 /* only ask authdirservers, and don't ask myself */
138 rs
= router_pick_trusteddirserver(need_v1_support
, 1, 1,
139 retry_if_no_servers
);
142 /* anybody with a non-zero dirport will do */
143 rs
= router_pick_directory_server(1, 1, need_v2_support
,
144 retry_if_no_servers
);
147 if (purpose
== DIR_PURPOSE_FETCH_DIR
)
149 else if (purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
)
150 which
= "status list";
151 else if (purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
)
152 which
= "network status";
153 else // if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
154 which
= "server descriptors";
156 "No router found for %s; falling back to dirserver list",
158 rs
= router_pick_trusteddirserver(need_v1_support
, 1, 1,
159 retry_if_no_servers
);
161 directconn
= 0; /* last resort: try routing it via Tor */
166 /* Never use fascistfirewall; we're going via Tor. */
167 if (purpose
== DIR_PURPOSE_FETCH_RENDDESC
) {
168 /* only ask authdirservers, any of them will do */
169 rs
= router_pick_trusteddirserver(1, 0, 0, retry_if_no_servers
);
171 /* anybody with a non-zero dirport will do. Disregard firewalls. */
172 rs
= router_pick_directory_server(1, 0, need_v2_support
,
173 retry_if_no_servers
);
174 /* If we have any hope of building an indirect conn, we know some router
175 * descriptors. If (rs==NULL), we can't build circuits anyway, so
176 * there's no point in falling back to the authorities in this case. */
181 directory_initiate_command_routerstatus(rs
, purpose
, !directconn
,
185 "No running dirservers known. Will try again later. "
186 "(purpose %d)", purpose
);
187 if (!purpose_is_private(purpose
)) {
188 /* remember we tried them all and failed. */
189 directory_all_unreachable(time(NULL
));
194 /** Launch a new connection to the directory server <b>router</b> to upload or
195 * download a service or rendezvous descriptor. <b>purpose</b> determines what
196 * kind of directory connection we're launching, and must be one of
197 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
199 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
200 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
202 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
206 directory_initiate_command_router(routerinfo_t
*router
,
208 int private_connection
,
209 const char *resource
,
213 directory_initiate_command(router
->address
, router
->addr
, router
->dir_port
,
215 router
->cache_info
.identity_digest
,
216 purpose
, private_connection
, resource
,
217 payload
, payload_len
);
220 /** Launch a new connection to the directory server <b>status</b> to upload or
221 * download a service or rendezvous descriptor. <b>purpose</b> determines what
222 * kind of directory connection we're launching, and must be one of
223 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
225 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
226 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
228 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
232 directory_initiate_command_routerstatus(routerstatus_t
*status
,
234 int private_connection
,
235 const char *resource
,
239 const char *platform
= NULL
;
240 routerinfo_t
*router
;
241 char address_buf
[INET_NTOA_BUF_LEN
];
244 if ((router
= router_get_by_digest(status
->identity_digest
))) {
245 platform
= router
->platform
;
246 address
= router
->address
;
248 in
.s_addr
= htonl(status
->addr
);
249 tor_inet_ntoa(&in
, address_buf
, sizeof(address_buf
));
250 address
= address_buf
;
252 directory_initiate_command(address
, status
->addr
, status
->dir_port
,
253 platform
, status
->identity_digest
,
254 purpose
, private_connection
, resource
,
255 payload
, payload_len
);
258 /** Called when we are unable to complete the client's request to a
259 * directory server: Mark the router as down and try again if possible.
262 connection_dir_request_failed(connection_t
*conn
)
264 if (router_digest_is_me(conn
->identity_digest
))
265 return; /* this was a test fetch. don't retry. */
266 router_set_status(conn
->identity_digest
, 0); /* don't try him again */
267 if (conn
->purpose
== DIR_PURPOSE_FETCH_DIR
||
268 conn
->purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
) {
269 log_info(LD_DIR
, "Giving up on directory server at '%s:%d'; retrying",
270 conn
->address
, conn
->port
);
271 directory_get_from_dirserver(conn
->purpose
, NULL
,
272 0 /* don't retry_if_no_servers */);
273 } else if (conn
->purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
) {
274 log_info(LD_DIR
, "Giving up on directory server at '%s'; retrying",
276 connection_dir_download_networkstatus_failed(conn
);
277 } else if (conn
->purpose
== DIR_PURPOSE_FETCH_SERVERDESC
) {
278 log_info(LD_DIR
, "Giving up on directory server at '%s'; retrying",
280 connection_dir_download_routerdesc_failed(conn
);
284 /** Called when an attempt to download one or more network status
285 * documents on connection <b>conn</b> failed. Decide whether to
286 * retry the fetch now, later, or never.
289 connection_dir_download_networkstatus_failed(connection_t
*conn
)
291 if (!conn
->requested_resource
) {
292 /* We never reached directory_send_command, which means that we never
293 * opened a network connection. Either we're out of sockets, or the
294 * network is down. Either way, retrying would be pointless. */
297 if (!strcmpstart(conn
->requested_resource
, "all")) {
298 /* We're a non-authoritative directory cache; try again. */
299 smartlist_t
*trusted_dirs
= router_get_trusted_dir_servers();
300 SMARTLIST_FOREACH(trusted_dirs
, trusted_dir_server_t
*, ds
,
301 ++ds
->n_networkstatus_failures
);
302 directory_get_from_dirserver(conn
->purpose
, "all.z",
303 0 /* don't retry_if_no_servers */);
304 } else if (!strcmpstart(conn
->requested_resource
, "fp/")) {
305 /* We were trying to download by fingerprint; mark them all as having
306 * failed, and possibly retry them later.*/
307 smartlist_t
*failed
= smartlist_create();
308 dir_split_resource_into_fingerprints(conn
->requested_resource
+3,
310 if (smartlist_len(failed
)) {
311 dir_networkstatus_download_failed(failed
);
312 SMARTLIST_FOREACH(failed
, char *, cp
, tor_free(cp
));
314 smartlist_free(failed
);
318 /** Called when an attempt to download one or more router descriptors
319 * on connection <b>conn</b> failed.
322 connection_dir_download_routerdesc_failed(connection_t
*conn
)
324 /* Try again. No need to increment the failure count for routerdescs, since
325 * it's not their fault.*/
326 /* update_router_descriptor_downloads(time(NULL)); */
329 /** Helper for directory_initiate_command_(router|trusted_dir): send the
330 * command to a server whose address is <b>address</b>, whose IP is
331 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version is
332 * <b>platform</b>, and whose identity key digest is <b>digest</b>. The
333 * <b>platform</b> argument is optional; the others are required. */
335 directory_initiate_command(const char *address
, uint32_t addr
,
336 uint16_t dir_port
, const char *platform
,
337 const char *digest
, uint8_t purpose
,
338 int private_connection
, const char *resource
,
339 const char *payload
, size_t payload_len
)
345 tor_assert(dir_port
);
349 case DIR_PURPOSE_FETCH_DIR
:
350 log_debug(LD_DIR
,"initiating directory fetch");
352 case DIR_PURPOSE_FETCH_RENDDESC
:
353 log_debug(LD_DIR
,"initiating hidden-service descriptor fetch");
355 case DIR_PURPOSE_UPLOAD_DIR
:
356 log_debug(LD_OR
,"initiating server descriptor upload");
358 case DIR_PURPOSE_UPLOAD_RENDDESC
:
359 log_debug(LD_REND
,"initiating hidden-service descriptor upload");
361 case DIR_PURPOSE_FETCH_RUNNING_LIST
:
362 log_debug(LD_DIR
,"initiating running-routers fetch");
364 case DIR_PURPOSE_FETCH_NETWORKSTATUS
:
365 log_debug(LD_DIR
,"initiating network-status fetch");
367 case DIR_PURPOSE_FETCH_SERVERDESC
:
368 log_debug(LD_DIR
,"initiating server descriptor fetch");
371 log_err(LD_BUG
, "Unrecognized directory connection purpose.");
375 conn
= connection_new(CONN_TYPE_DIR
);
377 /* set up conn so it's got all the data we need to remember */
379 conn
->port
= dir_port
;
380 conn
->address
= tor_strdup(address
);
381 memcpy(conn
->identity_digest
, digest
, DIGEST_LEN
);
383 conn
->purpose
= purpose
;
385 /* give it an initial state */
386 conn
->state
= DIR_CONN_STATE_CONNECTING
;
388 if (!private_connection
) {
389 /* then we want to connect directly */
391 if (get_options()->HttpProxy
) {
392 addr
= get_options()->HttpProxyAddr
;
393 dir_port
= get_options()->HttpProxyPort
;
396 switch (connection_connect(conn
, conn
->address
, addr
, dir_port
)) {
398 connection_dir_request_failed(conn
); /* retry if we want */
399 connection_free(conn
);
402 conn
->state
= DIR_CONN_STATE_CLIENT_SENDING
; /* start flushing conn */
405 /* queue the command on the outbuf */
406 directory_send_command(conn
, platform
, purpose
, resource
,
407 payload
, payload_len
);
408 connection_watch_events(conn
, EV_READ
| EV_WRITE
);
409 /* writable indicates finish, readable indicates broken link,
410 error indicates broken link in windowsland. */
412 } else { /* we want to connect via tor */
413 /* make an AP connection
414 * populate it and add it at the right state
415 * socketpair and hook up both sides
417 conn
->s
= connection_ap_make_bridge(conn
->address
, conn
->port
);
419 log_warn(LD_NET
,"Making AP bridge to dirserver failed.");
420 connection_mark_for_close(conn
);
424 if (connection_add(conn
) < 0) {
425 log_warn(LD_NET
,"Unable to add AP bridge to dirserver.");
426 connection_mark_for_close(conn
);
429 conn
->state
= DIR_CONN_STATE_CLIENT_SENDING
;
430 /* queue the command on the outbuf */
431 directory_send_command(conn
, platform
, purpose
, resource
,
432 payload
, payload_len
);
433 connection_watch_events(conn
, EV_READ
| EV_WRITE
);
437 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
438 * are as in directory_initiate_command.
441 directory_send_command(connection_t
*conn
, const char *platform
,
442 int purpose
, const char *resource
,
443 const char *payload
, size_t payload_len
)
445 char proxystring
[256];
446 char proxyauthstring
[256];
447 char hoststring
[128];
450 const char *httpcommand
= NULL
;
454 tor_assert(conn
->type
== CONN_TYPE_DIR
);
456 tor_free(conn
->requested_resource
);
458 conn
->requested_resource
= tor_strdup(resource
);
460 /* come up with a string for which Host: we want */
461 if (conn
->port
== 80) {
462 strlcpy(hoststring
, conn
->address
, sizeof(hoststring
));
464 tor_snprintf(hoststring
, sizeof(hoststring
),"%s:%d",
465 conn
->address
, conn
->port
);
468 /* come up with some proxy lines, if we're using one. */
469 if (get_options()->HttpProxy
) {
470 char *base64_authenticator
=NULL
;
471 const char *authenticator
= get_options()->HttpProxyAuthenticator
;
473 tor_snprintf(proxystring
, sizeof(proxystring
),"http://%s", hoststring
);
475 base64_authenticator
= alloc_http_authenticator(authenticator
);
476 if (!base64_authenticator
)
477 log_warn(LD_BUG
, "Encoding http authenticator failed");
479 if (base64_authenticator
) {
480 tor_snprintf(proxyauthstring
, sizeof(proxyauthstring
),
481 "\r\nProxy-Authorization: Basic %s",
482 base64_authenticator
);
483 tor_free(base64_authenticator
);
485 proxyauthstring
[0] = 0;
489 proxyauthstring
[0] = 0;
493 case DIR_PURPOSE_FETCH_DIR
:
494 tor_assert(!resource
);
495 tor_assert(!payload
);
497 "Asking for compressed directory from server running %s",
498 platform
?escaped(platform
):"<unknown version>");
500 url
= tor_strdup("/tor/dir.z");
502 case DIR_PURPOSE_FETCH_RUNNING_LIST
:
503 tor_assert(!resource
);
504 tor_assert(!payload
);
506 url
= tor_strdup("/tor/running-routers");
508 case DIR_PURPOSE_FETCH_NETWORKSTATUS
:
510 len
= strlen(resource
)+32;
511 url
= tor_malloc(len
);
512 tor_snprintf(url
, len
, "/tor/status/%s", resource
);
514 case DIR_PURPOSE_FETCH_SERVERDESC
:
516 len
= strlen(resource
)+32;
517 url
= tor_malloc(len
);
518 tor_snprintf(url
, len
, "/tor/server/%s", resource
);
520 case DIR_PURPOSE_UPLOAD_DIR
:
521 tor_assert(!resource
);
523 httpcommand
= "POST";
524 url
= tor_strdup("/tor/");
526 case DIR_PURPOSE_FETCH_RENDDESC
:
527 tor_assert(resource
);
528 tor_assert(!payload
);
530 /* this must be true or we wouldn't be doing the lookup */
531 tor_assert(strlen(resource
) <= REND_SERVICE_ID_LEN
);
532 /* This breaks the function abstraction. */
533 strlcpy(conn
->rend_query
, resource
, sizeof(conn
->rend_query
));
536 /* Request the most recent versioned descriptor. */
538 //tor_snprintf(url, sizeof(url), "/tor/rendezvous1/%s", resource);
539 len
= strlen(resource
)+32;
540 url
= tor_malloc(len
);
541 tor_snprintf(url
, len
, "/tor/rendezvous/%s", resource
);
543 case DIR_PURPOSE_UPLOAD_RENDDESC
:
544 tor_assert(!resource
);
546 httpcommand
= "POST";
547 url
= tor_strdup("/tor/rendezvous/publish");
554 if (strlen(proxystring
) + strlen(url
) >= 4096) {
556 "Bug: squid does not like URLs longer than 4095 bytes, this "
557 "one is %d bytes long: %s%s",
558 (int)(strlen(proxystring
) + strlen(url
)), proxystring
, url
);
561 tor_snprintf(request
, sizeof(request
), "%s %s", httpcommand
, proxystring
);
562 connection_write_to_buf(request
, strlen(request
), conn
);
563 connection_write_to_buf(url
, strlen(url
), conn
);
566 if (!strcmp(httpcommand
, "GET") && !payload
) {
567 tor_snprintf(request
, sizeof(request
),
568 " HTTP/1.0\r\nHost: %s%s\r\n\r\n",
572 tor_snprintf(request
, sizeof(request
),
573 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
574 payload
? (unsigned long)payload_len
: 0,
578 connection_write_to_buf(request
, strlen(request
), conn
);
581 /* then send the payload afterwards too */
582 connection_write_to_buf(payload
, payload_len
, conn
);
586 /** Parse an HTTP request string <b>headers</b> of the form
588 * "\%s [http[s]://]\%s HTTP/1..."
590 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
591 * null-terminate it. If the url doesn't start with "/tor/", rewrite it
592 * so it does. Return 0.
593 * Otherwise, return -1.
596 parse_http_url(char *headers
, char **url
)
598 char *s
, *start
, *tmp
;
600 s
= (char *)eat_whitespace_no_nl(headers
);
602 s
= (char *)find_whitespace(s
); /* get past GET/POST */
604 s
= (char *)eat_whitespace_no_nl(s
);
606 start
= s
; /* this is it, assuming it's valid */
607 s
= (char *)find_whitespace(start
);
610 /* tolerate the http[s] proxy style of putting the hostname in the url */
611 if (s
-start
>= 4 && !strcmpstart(start
,"http")) {
615 if (s
-tmp
>= 3 && !strcmpstart(tmp
,"://")) {
616 tmp
= strchr(tmp
+3, '/');
617 if (tmp
&& tmp
< s
) {
618 log_debug(LD_DIR
,"Skipping over 'http[s]://hostname' string");
624 if (s
-start
< 5 || strcmpstart(start
,"/tor/")) { /* need to rewrite it */
625 *url
= tor_malloc(s
- start
+ 5);
626 strlcpy(*url
,"/tor", s
-start
+5);
627 strlcat((*url
)+4, start
, s
-start
+1);
629 *url
= tor_strndup(start
, s
-start
);
634 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
635 * <b>which</b>. The key should be given with a terminating colon and space;
636 * this function copies everything after, up to but not including the
637 * following \\r\\n. */
639 http_get_header(const char *headers
, const char *which
)
641 const char *cp
= headers
;
643 if (!strcmpstart(cp
, which
)) {
646 if ((eos
= strchr(cp
,'\r')))
647 return tor_strndup(cp
, eos
-cp
);
649 return tor_strdup(cp
);
651 cp
= strchr(cp
, '\n');
658 /** Allocate and return a string describing the source of an HTTP request with
659 * headers <b>headers</b> received on <b>conn</b>. The format is either
660 * "'1.2.3.4'", or "'1.2.3.4' (forwarded for '5.6.7.8')".
663 http_get_origin(const char *headers
, connection_t
*conn
)
667 fwd
= http_get_header(headers
, "Forwarded-For: ");
669 fwd
= http_get_header(headers
, "X-Forwarded-For: ");
671 size_t len
= strlen(fwd
)+strlen(conn
->address
)+32;
672 char *result
= tor_malloc(len
);
673 tor_snprintf(result
, len
, "'%s' (forwarded for %s)", conn
->address
,
678 size_t len
= strlen(conn
->address
)+3;
679 char *result
= tor_malloc(len
);
680 tor_snprintf(result
, len
, "'%s'", conn
->address
);
685 /** Parse an HTTP response string <b>headers</b> of the form
687 * "HTTP/1.\%d \%d\%s\r\n...".
690 * If it's well-formed, assign the status code to *<b>code</b> and
691 * return 0. Otherwise, return -1.
693 * On success: If <b>date</b> is provided, set *date to the Date
694 * header in the http headers, or 0 if no such header is found. If
695 * <b>compression</b> is provided, set *<b>compression</b> to the
696 * compression method given in the Content-Encoding header, or 0 if no
697 * such header is found, or -1 if the value of the header is not
698 * recognized. If <b>reason</b> is provided, strdup the reason string
702 parse_http_response(const char *headers
, int *code
, time_t *date
,
703 int *compression
, char **reason
)
706 char datestr
[RFC1123_TIME_LEN
+1];
707 smartlist_t
*parsed_headers
;
711 while (TOR_ISSPACE(*headers
)) headers
++; /* tolerate leading whitespace */
713 if (sscanf(headers
, "HTTP/1.%d %d", &n1
, &n2
) < 2 ||
714 (n1
!= 0 && n1
!= 1) ||
715 (n2
< 100 || n2
>= 600)) {
716 log_warn(LD_HTTP
,"Failed to parse header %s",escaped(headers
));
721 parsed_headers
= smartlist_create();
722 smartlist_split_string(parsed_headers
, headers
, "\n",
723 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
725 smartlist_t
*status_line_elements
= smartlist_create();
726 tor_assert(smartlist_len(parsed_headers
));
727 smartlist_split_string(status_line_elements
,
728 smartlist_get(parsed_headers
, 0),
729 " ", SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 3);
730 tor_assert(smartlist_len(status_line_elements
) <= 3);
731 if (smartlist_len(status_line_elements
) == 3) {
732 *reason
= smartlist_get(status_line_elements
, 2);
733 smartlist_set(status_line_elements
, 2, NULL
); /* Prevent free */
735 SMARTLIST_FOREACH(status_line_elements
, char *, cp
, tor_free(cp
));
736 smartlist_free(status_line_elements
);
740 SMARTLIST_FOREACH(parsed_headers
, const char *, s
,
741 if (!strcmpstart(s
, "Date: ")) {
742 strlcpy(datestr
, s
+6, sizeof(datestr
));
743 /* This will do nothing on failure, so we don't need to check
744 the result. We shouldn't warn, since there are many other valid
745 date formats besides the one we use. */
746 parse_rfc1123_time(datestr
, date
);
751 const char *enc
= NULL
;
752 SMARTLIST_FOREACH(parsed_headers
, const char *, s
,
753 if (!strcmpstart(s
, "Content-Encoding: ")) {
756 if (!enc
|| !strcmp(enc
, "identity")) {
758 } else if (!strcmp(enc
, "deflate") || !strcmp(enc
, "x-deflate")) {
759 *compression
= ZLIB_METHOD
;
760 } else if (!strcmp(enc
, "gzip") || !strcmp(enc
, "x-gzip")) {
761 *compression
= GZIP_METHOD
;
763 log_info(LD_HTTP
, "Unrecognized content encoding: %s. Trying to deal.",
768 SMARTLIST_FOREACH(parsed_headers
, char *, s
, tor_free(s
));
769 smartlist_free(parsed_headers
);
774 /** Return true iff <b>body</b> doesn't start with a plausible router or
775 * running-list or directory opening. This is a sign of possible compression.
778 body_is_plausible(const char *body
, size_t len
, int purpose
)
782 return 1; /* empty bodies don't need decompression */
785 if (purpose
!= DIR_PURPOSE_FETCH_RENDDESC
) {
786 if (!strcmpstart(body
,"router") ||
787 !strcmpstart(body
,"signed-directory") ||
788 !strcmpstart(body
,"network-status") ||
789 !strcmpstart(body
,"running-routers"))
792 if (!TOR_ISPRINT(body
[i
]) && !TOR_ISSPACE(body
[i
]))
801 /** We are a client, and we've finished reading the server's
802 * response. Parse and it and act appropriately.
804 * If we're still happy with using this directory server in the future, return
805 * 0. Otherwise return -1; and the caller should consider trying the request
808 * The caller will take care of marking the connection for close.
811 connection_dir_client_reached_eof(connection_t
*conn
)
816 size_t body_len
=0, orig_len
=0;
818 time_t now
, date_header
=0;
823 int allow_partial
= conn
->purpose
== DIR_PURPOSE_FETCH_SERVERDESC
;
824 int was_compressed
=0;
826 switch (fetch_from_buf_http(conn
->inbuf
,
827 &headers
, MAX_HEADERS_SIZE
,
828 &body
, &body_len
, MAX_DIR_SIZE
,
830 case -1: /* overflow */
831 log_warn(LD_PROTOCOL
,
832 "'fetch' response too large (server '%s:%d'). Closing.",
833 conn
->address
, conn
->port
);
837 "'fetch' response not all here, but we're at eof. Closing.");
839 /* case 1, fall through */
843 if (parse_http_response(headers
, &status_code
, &date_header
,
844 &compression
, &reason
) < 0) {
845 log_warn(LD_HTTP
,"Unparseable headers (server '%s:%d'). Closing.",
846 conn
->address
, conn
->port
);
847 tor_free(body
); tor_free(headers
);
850 if (!reason
) reason
= tor_strdup("[no reason given]");
853 "Received response from directory server '%s:%d': %d %s",
854 conn
->address
, conn
->port
, status_code
, escaped(reason
));
856 if (date_header
> 0) {
858 delta
= now
-date_header
;
859 if (abs(delta
)>ALLOW_DIRECTORY_TIME_SKEW
) {
860 log_fn(router_digest_is_trusted_dir(conn
->identity_digest
) ?
863 "Received directory with skewed time (server '%s:%d'): "
864 "we are %d minutes %s, or the directory is %d minutes %s.",
865 conn
->address
, conn
->port
,
866 abs(delta
)/60, delta
>0 ? "ahead" : "behind",
867 abs(delta
)/60, delta
>0 ? "behind" : "ahead");
868 skewed
= 1; /* don't check the recommended-versions line */
870 log_debug(LD_HTTP
, "Time on received directory is within tolerance; "
871 "we are %d seconds skewed. (That's okay.)", delta
);
875 if (status_code
== 503) {
876 log_info(LD_DIR
,"Received http status code %d (%s) from server "
877 "'%s:%d'. I'll try again soon.",
878 status_code
, escaped(reason
), conn
->address
, conn
->port
);
879 tor_free(body
); tor_free(headers
); tor_free(reason
);
883 plausible
= body_is_plausible(body
, body_len
, conn
->purpose
);
884 if (compression
|| !plausible
) {
885 char *new_body
= NULL
;
887 int guessed
= detect_compression_method(body
, body_len
);
888 if (compression
<= 0 || guessed
!= compression
) {
889 /* Tell the user if we don't believe what we're told about compression.*/
890 const char *description1
, *description2
;
891 if (compression
== ZLIB_METHOD
)
892 description1
= "as deflated";
893 else if (compression
== GZIP_METHOD
)
894 description1
= "as gzipped";
895 else if (compression
== 0)
896 description1
= "as uncompressed";
898 description1
= "with an unknown Content-Encoding";
899 if (guessed
== ZLIB_METHOD
)
900 description2
= "deflated";
901 else if (guessed
== GZIP_METHOD
)
902 description2
= "gzipped";
904 description2
= "confusing binary junk";
906 description2
= "uncompressed";
908 log_info(LD_HTTP
, "HTTP body from server '%s:%d' was labeled %s, "
909 "but it seems to be %s.%s",
910 conn
->address
, conn
->port
, description1
, description2
,
911 (compression
>0 && guessed
>0)?" Trying both.":"");
913 /* Try declared compression first if we can. */
915 tor_gzip_uncompress(&new_body
, &new_len
, body
, body_len
, compression
,
916 allow_partial
, LOG_PROTOCOL_WARN
);
917 /* Okay, if that didn't work, and we think that it was compressed
918 * differently, try that. */
919 if (!new_body
&& guessed
> 0 && compression
!= guessed
)
920 tor_gzip_uncompress(&new_body
, &new_len
, body
, body_len
, guessed
,
921 allow_partial
, LOG_PROTOCOL_WARN
);
922 /* If we're pretty sure that we have a compressed directory, and
923 * we didn't manage to uncompress it, then warn and bail. */
924 if (!plausible
&& !new_body
) {
925 log_fn(LOG_PROTOCOL_WARN
, LD_HTTP
,
926 "Unable to decompress HTTP body (server '%s:%d').",
927 conn
->address
, conn
->port
);
928 tor_free(body
); tor_free(headers
); tor_free(reason
);
939 if (conn
->purpose
== DIR_PURPOSE_FETCH_DIR
) {
940 /* fetch/process the directory to cache it. */
941 log_info(LD_DIR
,"Received directory (size %d) from server '%s:%d'",
942 (int)body_len
, conn
->address
, conn
->port
);
943 if (status_code
!= 200) {
944 log_warn(LD_DIR
,"Received http status code %d (%s) from server "
945 "'%s:%d'. I'll try again soon.",
946 status_code
, escaped(reason
), conn
->address
, conn
->port
);
947 tor_free(body
); tor_free(headers
); tor_free(reason
);
950 if (router_parse_directory(body
) < 0) {
951 log_notice(LD_DIR
,"I failed to parse the directory I fetched from "
952 "'%s:%d'. Ignoring.", conn
->address
, conn
->port
);
954 note_request(was_compressed
?"dl/dir.z":"dl/dir", orig_len
);
957 if (conn
->purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
) {
958 /* just update our list of running routers, if this list is new info */
959 log_info(LD_DIR
,"Received running-routers list (size %d)", (int)body_len
);
960 if (status_code
!= 200) {
961 log_warn(LD_DIR
,"Received http status code %d (%s) from server "
962 "'%s:%d'. I'll try again soon.",
963 status_code
, escaped(reason
), conn
->address
, conn
->port
);
964 tor_free(body
); tor_free(headers
); tor_free(reason
);
967 if (router_parse_runningrouters(body
)<0) {
969 "Bad running-routers from server '%s:%d'. I'll try again soon.",
970 conn
->address
, conn
->port
);
971 tor_free(body
); tor_free(headers
); tor_free(reason
);
974 note_request(was_compressed
?"dl/running-routers.z":
975 "dl/running-routers", orig_len
);
978 if (conn
->purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
) {
979 smartlist_t
*which
= NULL
;
981 log_info(LD_DIR
,"Received networkstatus objects (size %d) from server "
982 "'%s:%d'",(int) body_len
, conn
->address
, conn
->port
);
983 if (status_code
!= 200) {
985 "Received http status code %d (%s) from server "
986 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
987 status_code
, escaped(reason
), conn
->address
, conn
->port
,
988 conn
->requested_resource
);
989 tor_free(body
); tor_free(headers
); tor_free(reason
);
990 connection_dir_download_networkstatus_failed(conn
);
993 note_request(was_compressed
?"dl/status.z":"dl/status", orig_len
);
994 if (conn
->requested_resource
&&
995 !strcmpstart(conn
->requested_resource
,"fp/")) {
996 which
= smartlist_create();
997 dir_split_resource_into_fingerprints(conn
->requested_resource
+3,
999 } else if (conn
->requested_resource
&&
1000 !strcmpstart(conn
->requested_resource
, "all")) {
1001 which
= smartlist_create();
1002 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1003 trusted_dir_server_t
*, ds
,
1005 char *cp
= tor_malloc(HEX_DIGEST_LEN
+1);
1006 base16_encode(cp
, HEX_DIGEST_LEN
+1, ds
->digest
, DIGEST_LEN
);
1007 smartlist_add(which
, cp
);
1012 char *next
= strstr(cp
, "\nnetwork-status-version");
1015 /* learn from it, and then remove it from 'which' */
1016 if (router_set_networkstatus(cp
, time(NULL
), NS_FROM_DIR
, which
)<0)
1025 routers_update_all_from_networkstatus(); /*launches router downloads*/
1026 directory_info_has_arrived(time(NULL
), 0);
1028 if (smartlist_len(which
)) {
1029 dir_networkstatus_download_failed(which
);
1031 SMARTLIST_FOREACH(which
, char *, cp
, tor_free(cp
));
1032 smartlist_free(which
);
1036 if (conn
->purpose
== DIR_PURPOSE_FETCH_SERVERDESC
) {
1037 smartlist_t
*which
= NULL
;
1038 int n_asked_for
= 0;
1039 log_info(LD_DIR
,"Received server info (size %d) from server '%s:%d'",
1040 (int)body_len
, conn
->address
, conn
->port
);
1041 note_request(was_compressed
?"dl/server.z":"dl/server", orig_len
);
1042 if (conn
->requested_resource
&&
1043 !strcmpstart(conn
->requested_resource
,"d/")) {
1044 which
= smartlist_create();
1045 dir_split_resource_into_fingerprints(conn
->requested_resource
+2,
1047 n_asked_for
= smartlist_len(which
);
1049 if (status_code
!= 200) {
1050 int dir_okay
= status_code
== 404 ||
1051 (status_code
== 400 && !strcmp(reason
, "Servers unavailable."));
1052 /* 404 means that it didn't have them; no big deal.
1053 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1054 log_fn(dir_okay
? LOG_INFO
: LOG_WARN
, LD_DIR
,
1055 "Received http status code %d (%s) from server '%s:%d' "
1056 "while fetching \"/tor/server/%s\". I'll try again soon.",
1057 status_code
, escaped(reason
), conn
->address
, conn
->port
,
1058 conn
->requested_resource
);
1060 connection_dir_download_routerdesc_failed(conn
);
1062 dir_routerdesc_download_failed(which
);
1063 SMARTLIST_FOREACH(which
, char *, cp
, tor_free(cp
));
1064 smartlist_free(which
);
1066 tor_free(body
); tor_free(headers
); tor_free(reason
);
1067 return dir_okay
? 0 : -1;
1069 /* Learn the routers, assuming we requested by fingerprint or "all".
1070 * Right now, we only use "authority" to fetch ourself, so we don't want
1071 * to risk replacing ourself with a router running at the addr:port we
1074 if (which
|| (conn
->requested_resource
&&
1075 !strcmpstart(conn
->requested_resource
, "all"))) {
1076 /* as we learn from them, we remove them from 'which' */
1077 router_load_routers_from_string(body
, 0, which
);
1078 directory_info_has_arrived(time(NULL
), 0);
1080 if (which
) { /* mark remaining ones as failed */
1081 log_info(LD_DIR
, "Received %d/%d routers requested from %s:%d",
1082 n_asked_for
-smartlist_len(which
), n_asked_for
,
1083 conn
->address
, (int)conn
->port
);
1084 if (smartlist_len(which
)) {
1085 dir_routerdesc_download_failed(which
);
1087 SMARTLIST_FOREACH(which
, char *, cp
, tor_free(cp
));
1088 smartlist_free(which
);
1090 if (conn
->requested_resource
&&
1091 !strcmpstart(conn
->requested_resource
,"authority")) {
1092 /* this might have been a dirport reachability test. see if it is. */
1093 routerinfo_t
*me
= router_get_my_routerinfo();
1095 router_digest_is_me(conn
->identity_digest
) &&
1096 me
->addr
== conn
->addr
&&
1097 me
->dir_port
== conn
->port
)
1098 router_dirport_found_reachable();
1102 if (conn
->purpose
== DIR_PURPOSE_UPLOAD_DIR
) {
1103 switch (status_code
) {
1105 log_info(LD_GENERAL
,"eof (status 200) after uploading server "
1106 "descriptor: finished.");
1109 log_warn(LD_GENERAL
,"http status 400 (%s) response from "
1110 "dirserver '%s:%d'. Please correct.",
1111 escaped(reason
), conn
->address
, conn
->port
);
1114 log_warn(LD_GENERAL
,
1115 "http status 403 (%s) response from dirserver "
1116 "'%s:%d'. Is your clock skewed? Have you mailed us your key "
1117 "fingerprint? Are you using the right key? Are you using a "
1118 "private IP address? See http://tor.eff.org/doc/"
1119 "tor-doc-server.html",escaped(reason
), conn
->address
, conn
->port
);
1122 log_warn(LD_GENERAL
,
1123 "http status %d (%s) reason unexpected (server '%s:%d').",
1124 status_code
, escaped(reason
), conn
->address
, conn
->port
);
1127 /* return 0 in all cases, since we don't want to mark any
1128 * dirservers down just because they don't like us. */
1131 if (conn
->purpose
== DIR_PURPOSE_FETCH_RENDDESC
) {
1132 log_info(LD_REND
,"Received rendezvous descriptor (size %d, status %d "
1134 (int)body_len
, status_code
, escaped(reason
));
1135 switch (status_code
) {
1137 if (rend_cache_store(body
, body_len
) < 0) {
1138 log_warn(LD_REND
,"Failed to store rendezvous descriptor.");
1139 /* alice's ap_stream will notice when connection_mark_for_close
1142 /* success. notify pending connections about this. */
1143 conn
->purpose
= DIR_PURPOSE_HAS_FETCHED_RENDDESC
;
1144 rend_client_desc_here(conn
->rend_query
);
1148 /* not there. pending connections will be notified when
1149 * connection_mark_for_close cleans it up. */
1153 "http status 400 (%s). Dirserver didn't like our "
1154 "rendezvous query?", escaped(reason
));
1157 log_warn(LD_REND
,"http status %d (%s) response unexpected (server "
1159 status_code
, escaped(reason
), conn
->address
, conn
->port
);
1164 if (conn
->purpose
== DIR_PURPOSE_UPLOAD_RENDDESC
) {
1165 switch (status_code
) {
1168 "Uploading rendezvous descriptor: finished with status "
1169 "200 (%s)", escaped(reason
));
1172 log_warn(LD_REND
,"http status 400 (%s) response from dirserver "
1173 "'%s:%d'. Malformed rendezvous descriptor?",
1174 escaped(reason
), conn
->address
, conn
->port
);
1177 log_warn(LD_REND
,"http status %d (%s) response unexpected (server "
1179 status_code
, escaped(reason
), conn
->address
, conn
->port
);
1183 tor_free(body
); tor_free(headers
); tor_free(reason
);
1187 /** Called when a directory connection reaches EOF */
1189 connection_dir_reached_eof(connection_t
*conn
)
1192 if (conn
->state
!= DIR_CONN_STATE_CLIENT_READING
) {
1193 log_info(LD_HTTP
,"conn reached eof, not reading. Closing.");
1194 connection_close_immediate(conn
); /* error: give up on flushing */
1195 connection_mark_for_close(conn
);
1199 retval
= connection_dir_client_reached_eof(conn
);
1200 if (retval
== 0) /* success */
1201 conn
->state
= DIR_CONN_STATE_CLIENT_FINISHED
;
1202 connection_mark_for_close(conn
);
1206 /** Read handler for directory connections. (That's connections <em>to</em>
1207 * directory servers and connections <em>at</em> directory servers.)
1210 connection_dir_process_inbuf(connection_t
*conn
)
1213 tor_assert(conn
->type
== CONN_TYPE_DIR
);
1215 /* Directory clients write, then read data until they receive EOF;
1216 * directory servers read data until they get an HTTP command, then
1217 * write their response (when it's finished flushing, they mark for
1221 /* If we're on the dirserver side, look for a command. */
1222 if (conn
->state
== DIR_CONN_STATE_SERVER_COMMAND_WAIT
) {
1223 if (directory_handle_command(conn
) < 0) {
1224 connection_mark_for_close(conn
);
1230 /* XXX for READ states, might want to make sure inbuf isn't too big */
1232 if (!conn
->inbuf_reached_eof
)
1233 log_debug(LD_HTTP
,"Got data, not eof. Leaving on inbuf.");
1237 /** Create an http response for the client <b>conn</b> out of
1238 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1241 write_http_status_line(connection_t
*conn
, int status
,
1242 const char *reason_phrase
)
1245 if (tor_snprintf(buf
, sizeof(buf
), "HTTP/1.0 %d %s\r\n\r\n",
1246 status
, reason_phrase
) < 0) {
1247 log_warn(LD_BUG
,"Bug: status line too long.");
1250 connection_write_to_buf(buf
, strlen(buf
), conn
);
1253 /** Helper function: return 1 if there are any dir conns of purpose
1254 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1258 already_fetching_directory(int purpose
)
1262 connection_t
**carray
;
1264 get_connection_array(&carray
,&n
);
1267 if (conn
->type
== CONN_TYPE_DIR
&&
1268 conn
->purpose
== purpose
&&
1269 !conn
->marked_for_close
&&
1270 !router_digest_is_me(conn
->identity_digest
))
1276 #undef INSTRUMENT_DOWNLOADS
1278 #ifdef INSTRUMENT_DOWNLOADS
1280 static strmap_t
*request_bytes_map
= NULL
;
1284 note_request(const char *key
, size_t bytes
)
1287 if (!request_bytes_map
)
1288 request_bytes_map
= strmap_new();
1290 n
= strmap_get(request_bytes_map
, key
);
1292 n
= tor_malloc_zero(sizeof(uint64_t));
1293 strmap_set(request_bytes_map
, key
, n
);
1300 directory_dump_request_log(void)
1305 strmap_iter_t
*iter
;
1307 if (!request_bytes_map
)
1308 request_bytes_map
= strmap_new();
1310 lines
= smartlist_create();
1312 for (iter
= strmap_iter_init(request_bytes_map
);
1313 !strmap_iter_done(iter
);
1314 iter
= strmap_iter_next(request_bytes_map
, iter
)) {
1318 strmap_iter_get(iter
, &key
, &val
);
1320 tor_snprintf(tmp
, sizeof(tmp
), "%s "U64_FORMAT
"\n",
1321 key
, U64_PRINTF_ARG(*n
));
1322 smartlist_add(lines
, tor_strdup(tmp
));
1324 smartlist_sort_strings(lines
);
1325 result
= smartlist_join_strings(lines
, "", 0, NULL
);
1326 SMARTLIST_FOREACH(lines
, char *, cp
, tor_free(cp
));
1327 smartlist_free(lines
);
1332 note_request(const char *key
, size_t bytes
)
1338 directory_dump_request_log(void)
1340 return tor_strdup("Not supported.");
1344 /** Helper function: called when a dirserver gets a complete HTTP GET
1345 * request. Look for a request for a directory or for a rendezvous
1346 * service descriptor. On finding one, write a response into
1347 * conn-\>outbuf. If the request is unrecognized, send a 400.
1348 * Always return 0. */
1350 directory_handle_command_get(connection_t
*conn
, char *headers
,
1351 char *body
, size_t body_len
)
1357 char date
[RFC1123_TIME_LEN
+1];
1359 log_debug(LD_DIRSERV
,"Received GET command.");
1361 conn
->state
= DIR_CONN_STATE_SERVER_WRITING
;
1363 if (parse_http_url(headers
, &url
) < 0) {
1364 write_http_status_line(conn
, 400, "Bad request");
1367 log_debug(LD_DIRSERV
,"rewritten url as '%s'.", url
);
1369 if (!strcmp(url
,"/tor/") || !strcmp(url
,"/tor/dir.z")) { /* dir fetch */
1370 int deflated
= !strcmp(url
,"/tor/dir.z");
1371 dlen
= dirserv_get_directory(&cp
, deflated
);
1374 log_notice(LD_DIRSERV
,"Client asked for the mirrored directory, but we "
1375 "don't have a good one yet. Sending 503 Dir not available.");
1376 write_http_status_line(conn
, 503, "Directory unavailable");
1377 /* try to get a new one now */
1378 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR
))
1379 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR
, NULL
, 1);
1384 if (global_write_bucket_empty()) {
1385 log_info(LD_DIRSERV
,
1386 "Client asked for the mirrored directory, but we've been "
1387 "writing too many bytes lately. Sending 503 Dir busy.");
1388 write_http_status_line(conn
, 503, "Directory busy, try again later");
1393 note_request(url
, dlen
);
1396 log_debug(LD_DIRSERV
,"Dumping %sdirectory to client.",
1397 deflated
?"deflated ":"");
1398 format_rfc1123_time(date
, time(NULL
));
1399 tor_snprintf(tmp
, sizeof(tmp
),
1400 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1401 "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
1404 deflated
?"application/octet-stream":"text/plain",
1405 deflated
?"deflate":"identity");
1406 connection_write_to_buf(tmp
, strlen(tmp
), conn
);
1407 connection_write_to_buf(cp
, dlen
, conn
);
1411 if (!strcmp(url
,"/tor/running-routers") ||
1412 !strcmp(url
,"/tor/running-routers.z")) { /* running-routers fetch */
1413 int deflated
= !strcmp(url
,"/tor/running-routers.z");
1414 dlen
= dirserv_get_runningrouters(&cp
, deflated
);
1415 note_request(url
, dlen
);
1417 if (!dlen
) { /* we failed to create/cache cp */
1418 write_http_status_line(conn
, 503, "Directory unavailable");
1419 /* try to get a new one now */
1420 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST
))
1421 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST
, NULL
, 1);
1425 format_rfc1123_time(date
, time(NULL
));
1426 tor_snprintf(tmp
, sizeof(tmp
),
1427 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1428 "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
1431 deflated
?"application/octet-stream":"text/plain",
1432 deflated
?"deflate":"identity");
1433 connection_write_to_buf(tmp
, strlen(tmp
), conn
);
1434 connection_write_to_buf(cp
, strlen(cp
), conn
);
1438 if (!strcmpstart(url
,"/tor/status/")) {
1439 /* v2 network status fetch. */
1440 size_t url_len
= strlen(url
);
1441 int deflated
= !strcmp(url
+url_len
-2, ".z");
1442 smartlist_t
*dir_objs
= smartlist_create();
1443 const char *request_type
= NULL
;
1444 const char *key
= url
+ strlen("/tor/status/");
1446 url
[url_len
-2] = '\0';
1447 dirserv_get_networkstatus_v2(dir_objs
, key
);
1448 if (!strcmpstart(key
, "fp/"))
1449 request_type
= deflated
?"/tor/status/fp.z":"/tor/status/fp";
1450 else if (!strcmpstart(key
, "authority"))
1451 request_type
= deflated
?"/tor/status/authority.z":
1452 "/tor/status/authority";
1453 else if (!strcmpstart(key
, "all"))
1454 request_type
= deflated
?"/tor/status/all.z":"/tor/status/all";
1456 request_type
= "/tor/status/?";
1458 if (!smartlist_len(dir_objs
)) { /* we failed to create/cache cp */
1459 write_http_status_line(conn
, 503, "Network status object unavailable");
1460 smartlist_free(dir_objs
);
1464 SMARTLIST_FOREACH(dir_objs
, cached_dir_t
*, d
,
1465 dlen
+= deflated
?d
->dir_z_len
:d
->dir_len
);
1466 note_request(request_type
,dlen
);
1467 format_rfc1123_time(date
, time(NULL
));
1468 tor_snprintf(tmp
, sizeof(tmp
),
1469 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1470 "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
1473 deflated
?"application/octet-stream":"text/plain",
1474 deflated
?"deflate":"identity");
1475 connection_write_to_buf(tmp
, strlen(tmp
), conn
);
1476 SMARTLIST_FOREACH(dir_objs
, cached_dir_t
*, d
,
1479 connection_write_to_buf(d
->dir_z
, d
->dir_z_len
, conn
);
1481 connection_write_to_buf(d
->dir
, d
->dir_len
, conn
);
1483 smartlist_free(dir_objs
);
1487 if (!strcmpstart(url
,"/tor/server/")) {
1488 size_t url_len
= strlen(url
);
1489 int deflated
= !strcmp(url
+url_len
-2, ".z");
1492 smartlist_t
*descs
= smartlist_create();
1493 const char *request_type
= NULL
;
1495 url
[url_len
-2] = '\0';
1496 res
= dirserv_get_routerdescs(descs
, url
, &msg
);
1498 if (!strcmpstart(url
, "/tor/server/fp/"))
1499 request_type
= deflated
?"/tor/server/fp.z":"/tor/server/fp";
1500 else if (!strcmpstart(url
, "/tor/server/authority"))
1501 request_type
= deflated
?"/tor/server/authority.z":
1502 "/tor/server/authority";
1503 else if (!strcmpstart(url
, "/tor/server/all"))
1504 request_type
= deflated
?"/tor/server/all.z":"/tor/server/all";
1505 else if (!strcmpstart(url
, "/tor/server/d/"))
1506 request_type
= deflated
?"/tor/server/d.z":"/tor/server/d";
1508 request_type
= "/tor/server/?";
1511 write_http_status_line(conn
, 404, msg
);
1514 format_rfc1123_time(date
, time(NULL
));
1515 SMARTLIST_FOREACH(descs
, signed_descriptor_t
*, ri
,
1516 len
+= ri
->signed_descriptor_len
);
1518 size_t compressed_len
;
1520 char *inp
= tor_malloc(len
+smartlist_len(descs
)+1);
1522 SMARTLIST_FOREACH(descs
, signed_descriptor_t
*, ri
,
1524 const char *body
= signed_descriptor_get_body(ri
);
1525 memcpy(cp
, body
, ri
->signed_descriptor_len
);
1526 cp
+= ri
->signed_descriptor_len
;
1530 /* XXXX This could be way more efficiently handled; let's see if it
1531 * shows up under oprofile. */
1532 if (tor_gzip_compress(&compressed
, &compressed_len
,
1533 inp
, cp
-inp
, ZLIB_METHOD
)<0) {
1535 smartlist_free(descs
);
1539 tor_snprintf(tmp
, sizeof(tmp
),
1540 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1541 "Content-Type: application/octet-stream\r\n"
1542 "Content-Encoding: deflate\r\n\r\n",
1544 (int)compressed_len
);
1545 note_request(request_type
, compressed_len
);
1546 connection_write_to_buf(tmp
, strlen(tmp
), conn
);
1547 connection_write_to_buf(compressed
, compressed_len
, conn
);
1548 tor_free(compressed
);
1550 tor_snprintf(tmp
, sizeof(tmp
),
1551 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1552 "Content-Type: text/plain\r\n\r\n",
1555 note_request(request_type
, len
);
1556 connection_write_to_buf(tmp
, strlen(tmp
), conn
);
1557 SMARTLIST_FOREACH(descs
, signed_descriptor_t
*, ri
,
1559 const char *body
= signed_descriptor_get_body(ri
);
1560 connection_write_to_buf(body
, ri
->signed_descriptor_len
, conn
);
1564 smartlist_free(descs
);
1568 if (!strcmpstart(url
,"/tor/rendezvous/") ||
1569 !strcmpstart(url
,"/tor/rendezvous1/")) {
1570 /* rendezvous descriptor fetch */
1573 int versioned
= !strcmpstart(url
,"/tor/rendezvous1/");
1574 const char *query
= url
+strlen("/tor/rendezvous/")+(versioned
?1:0);
1576 if (!authdir_mode(get_options())) {
1577 /* We don't hand out rend descs. In fact, it could be a security
1578 * risk, since rend_cache_lookup_desc() below would provide it
1579 * if we're gone to the site recently, and 404 if we haven't.
1582 write_http_status_line(conn
, 400, "Nonauthoritative directory does not "
1583 "store rendezvous descriptors");
1587 switch (rend_cache_lookup_desc(query
, versioned
?-1:0, &descp
, &desc_len
)) {
1589 format_rfc1123_time(date
, time(NULL
));
1590 tor_snprintf(tmp
, sizeof(tmp
),
1591 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1592 "Content-Type: application/octet-stream\r\n\r\n",
1595 note_request("/tor/rendezvous?/", desc_len
);
1596 connection_write_to_buf(tmp
, strlen(tmp
), conn
);
1597 /* need to send descp separately, because it may include nuls */
1598 connection_write_to_buf(descp
, desc_len
, conn
);
1600 case 0: /* well-formed but not present */
1601 write_http_status_line(conn
, 404, "Not found");
1603 case -1: /* not well-formed */
1604 write_http_status_line(conn
, 400, "Bad request");
1611 if (!strcmpstart(url
,"/tor/bytes.txt")) {
1612 char *bytes
= directory_dump_request_log();
1613 size_t len
= strlen(bytes
);
1614 format_rfc1123_time(date
, time(NULL
));
1615 tor_snprintf(tmp
, sizeof(tmp
),
1616 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1617 "Content-Type: text/plain\r\n\r\n",
1620 connection_write_to_buf(tmp
, strlen(tmp
), conn
);
1621 connection_write_to_buf(bytes
, len
, conn
);
1627 if (!strcmp(url
,"/tor/robots.txt")) { /* /robots.txt will have been
1628 rewritten to /tor/robots.txt */
1629 char robots
[] = "User-agent: *\r\nDisallow: /\r\n";
1630 size_t len
= strlen(robots
);
1631 format_rfc1123_time(date
, time(NULL
));
1632 tor_snprintf(tmp
, sizeof(tmp
),
1633 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1634 "Content-Type: text/plain\r\n\r\n",
1637 connection_write_to_buf(tmp
, strlen(tmp
), conn
);
1638 connection_write_to_buf(robots
, len
, conn
);
1643 /* we didn't recognize the url */
1644 write_http_status_line(conn
, 404, "Not found");
1649 /** Helper function: called when a dirserver gets a complete HTTP POST
1650 * request. Look for an uploaded server descriptor or rendezvous
1651 * service descriptor. On finding one, process it and write a
1652 * response into conn-\>outbuf. If the request is unrecognized, send a
1653 * 400. Always return 0. */
1655 directory_handle_command_post(connection_t
*conn
, char *headers
,
1656 char *body
, size_t body_len
)
1659 char *origin
= NULL
;
1662 log_debug(LD_DIRSERV
,"Received POST command.");
1664 conn
->state
= DIR_CONN_STATE_SERVER_WRITING
;
1666 if (!authdir_mode(get_options())) {
1667 /* we just provide cached directories; we don't want to
1668 * receive anything. */
1669 write_http_status_line(conn
, 400, "Nonauthoritative directory does not "
1670 "accept posted server descriptors");
1674 if (parse_http_url(headers
, &url
) < 0) {
1675 write_http_status_line(conn
, 400, "Bad request");
1678 log_debug(LD_DIRSERV
,"rewritten url as '%s'.", url
);
1679 origin
= http_get_origin(headers
, conn
);
1681 if (!strcmp(url
,"/tor/")) { /* server descriptor post */
1683 int r
= dirserv_add_descriptor(body
, &msg
);
1686 dirserv_get_directory(&cp
, 0); /* rebuild and write to disk */
1691 log_notice(LD_DIRSERV
,"Rejected router descriptor from %s.", origin
);
1692 /* malformed descriptor, or something wrong */
1693 write_http_status_line(conn
, 400, msg
);
1695 case 0: /* accepted but discarded */
1696 case 2: /* accepted */
1697 write_http_status_line(conn
, 200, msg
);
1703 if (!strcmpstart(url
,"/tor/rendezvous/publish")) {
1704 /* rendezvous descriptor post */
1705 if (rend_cache_store(body
, body_len
) < 0) {
1706 // char tmp[1024*2+1];
1707 log_fn(LOG_PROTOCOL_WARN
, LD_DIRSERV
,
1708 "Rejected rend descriptor (length %d) from %s.",
1709 (int)body_len
, origin
);
1711 if (body_len
<= 1024) {
1712 base16_encode(tmp
, sizeof(tmp
), body
, body_len
);
1713 log_notice(LD_DIRSERV
,"Body was: %s", escaped(tmp
));
1716 write_http_status_line(conn
, 400, "Invalid service descriptor rejected");
1718 write_http_status_line(conn
, 200, "Service descriptor stored");
1723 /* we didn't recognize the url */
1724 write_http_status_line(conn
, 404, "Not found");
1732 /** Called when a dirserver receives data on a directory connection;
1733 * looks for an HTTP request. If the request is complete, remove it
1734 * from the inbuf, try to process it; otherwise, leave it on the
1735 * buffer. Return a 0 on success, or -1 on error.
1738 directory_handle_command(connection_t
*conn
)
1740 char *headers
=NULL
, *body
=NULL
;
1745 tor_assert(conn
->type
== CONN_TYPE_DIR
);
1747 switch (fetch_from_buf_http(conn
->inbuf
,
1748 &headers
, MAX_HEADERS_SIZE
,
1749 &body
, &body_len
, MAX_BODY_SIZE
, 0)) {
1750 case -1: /* overflow */
1751 log_warn(LD_DIRSERV
,
1752 "Invalid input from address '%s'. Closing.", conn
->address
);
1755 log_debug(LD_DIRSERV
,"command not all here yet.");
1757 /* case 1, fall through */
1760 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
1762 if (!strncasecmp(headers
,"GET",3))
1763 r
= directory_handle_command_get(conn
, headers
, body
, body_len
);
1764 else if (!strncasecmp(headers
,"POST",4))
1765 r
= directory_handle_command_post(conn
, headers
, body
, body_len
);
1767 log_fn(LOG_PROTOCOL_WARN
, LD_PROTOCOL
,
1768 "Got headers %s with unknown command. Closing.",
1773 tor_free(headers
); tor_free(body
);
1777 /** Write handler for directory connections; called when all data has
1778 * been flushed. Close the connection or wait for a response as
1782 connection_dir_finished_flushing(connection_t
*conn
)
1785 tor_assert(conn
->type
== CONN_TYPE_DIR
);
1787 switch (conn
->state
) {
1788 case DIR_CONN_STATE_CLIENT_SENDING
:
1789 log_debug(LD_DIR
,"client finished sending command.");
1790 conn
->state
= DIR_CONN_STATE_CLIENT_READING
;
1791 connection_stop_writing(conn
);
1793 case DIR_CONN_STATE_SERVER_WRITING
:
1794 log_debug(LD_DIRSERV
,"Finished writing server response. Closing.");
1795 connection_mark_for_close(conn
);
1798 log_warn(LD_BUG
,"Bug: called in unexpected state %d.", conn
->state
);
1799 tor_fragile_assert();
1805 /** Connected handler for directory connections: begin sending data to the
1808 connection_dir_finished_connecting(connection_t
*conn
)
1811 tor_assert(conn
->type
== CONN_TYPE_DIR
);
1812 tor_assert(conn
->state
== DIR_CONN_STATE_CONNECTING
);
1814 log_debug(LD_HTTP
,"Dir connection to router %s:%u established.",
1815 conn
->address
,conn
->port
);
1817 conn
->state
= DIR_CONN_STATE_CLIENT_SENDING
; /* start flushing conn */
1821 /** Called when one or more networkstatus fetches have failed (with uppercase
1822 * fingerprints listed in <b>failed</>). Mark those fingerprints as having
1825 dir_networkstatus_download_failed(smartlist_t
*failed
)
1827 SMARTLIST_FOREACH(failed
, const char *, fp
,
1829 char digest
[DIGEST_LEN
];
1830 trusted_dir_server_t
*dir
;
1831 base16_decode(digest
, DIGEST_LEN
, fp
, strlen(fp
));
1832 dir
= router_get_trusteddirserver_by_digest(digest
);
1835 ++dir
->n_networkstatus_failures
;
1839 /** Called when one or more routerdesc fetches have failed (with uppercase
1840 * fingerprints listed in <b>failed</b>). */
1842 dir_routerdesc_download_failed(smartlist_t
*failed
)
1844 char digest
[DIGEST_LEN
];
1845 local_routerstatus_t
*rs
;
1846 time_t now
= time(NULL
);
1847 int server
= server_mode(get_options()) && get_options()->DirPort
;
1848 SMARTLIST_FOREACH(failed
, const char *, cp
,
1850 base16_decode(digest
, DIGEST_LEN
, cp
, strlen(cp
));
1851 rs
= router_get_combined_status_by_digest(digest
);
1852 if (!rs
|| rs
->n_download_failures
>= MAX_ROUTERDESC_DOWNLOAD_FAILURES
)
1854 ++rs
->n_download_failures
;
1856 switch (rs
->n_download_failures
) {
1857 case 1: rs
->next_attempt_at
= 0; break;
1858 case 2: rs
->next_attempt_at
= 0; break;
1859 case 3: rs
->next_attempt_at
= now
+60; break;
1860 case 4: rs
->next_attempt_at
= now
+60; break;
1861 case 5: rs
->next_attempt_at
= now
+60*2; break;
1862 case 6: rs
->next_attempt_at
= now
+60*5; break;
1863 case 7: rs
->next_attempt_at
= now
+60*15; break;
1864 default: rs
->next_attempt_at
= TIME_MAX
; break;
1867 switch (rs
->n_download_failures
) {
1868 case 1: rs
->next_attempt_at
= 0; break;
1869 case 2: rs
->next_attempt_at
= now
+60; break;
1870 case 3: rs
->next_attempt_at
= now
+60*5; break;
1871 case 4: rs
->next_attempt_at
= now
+60*10; break;
1872 default: rs
->next_attempt_at
= TIME_MAX
; break;
1875 if (rs
->next_attempt_at
== 0)
1876 log_debug(LD_DIR
, "%s failed %d time(s); I'll try again immediately.",
1877 cp
, (int)rs
->n_download_failures
);
1878 else if (rs
->next_attempt_at
< TIME_MAX
)
1879 log_debug(LD_DIR
, "%s failed %d time(s); I'll try again in %d seconds.",
1880 cp
, (int)rs
->n_download_failures
,
1881 (int)(rs
->next_attempt_at
-now
));
1883 log_debug(LD_DIR
, "%s failed %d time(s); Giving up for a while.",
1884 cp
, (int)rs
->n_download_failures
);
1887 /* update_router_descriptor_downloads(time(NULL)); */
1890 /* Given a directory <b>resource</b> request, containing zero
1891 * or more strings separated by plus signs, followed optionally by ".z", store
1892 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
1893 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
1894 * decode_hex is true, then delete all elements that aren't hex digests, and
1898 dir_split_resource_into_fingerprints(const char *resource
,
1899 smartlist_t
*fp_out
, int *compressed_out
,
1904 old_len
= smartlist_len(fp_out
);
1905 smartlist_split_string(fp_out
, resource
, "+", 0, 0);
1907 *compressed_out
= 0;
1908 if (smartlist_len(fp_out
) > old_len
) {
1909 char *last
= smartlist_get(fp_out
,smartlist_len(fp_out
)-1);
1910 size_t last_len
= strlen(last
);
1911 if (last_len
> 2 && !strcmp(last
+last_len
-2, ".z")) {
1912 last
[last_len
-2] = '\0';
1914 *compressed_out
= 1;
1919 char *cp
, *d
= NULL
;
1920 for (i
= old_len
; i
< smartlist_len(fp_out
); ++i
) {
1921 cp
= smartlist_get(fp_out
, i
);
1922 if (strlen(cp
) != HEX_DIGEST_LEN
) {
1924 "Skipping digest %s with non-standard length.", escaped(cp
));
1925 smartlist_del(fp_out
, i
--);
1928 d
= tor_malloc_zero(DIGEST_LEN
);
1929 if (base16_decode(d
, DIGEST_LEN
, cp
, HEX_DIGEST_LEN
)<0) {
1930 log_info(LD_DIR
, "Skipping non-decodable digest %s", escaped(cp
));
1931 smartlist_del(fp_out
, i
--);
1934 smartlist_set(fp_out
, i
, d
);