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