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(dir_connection_t
*conn
, const char *platform
,
42 int purpose
, int direct
, const char *resource
,
43 const char *payload
, size_t payload_len
);
44 static int directory_handle_command(dir_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 void http_set_address_origin(const char *headers
, connection_t
*conn
);
49 static void connection_dir_download_networkstatus_failed(
50 dir_connection_t
*conn
, int status_code
);
51 static void connection_dir_download_routerdesc_failed(dir_connection_t
*conn
);
52 static void dir_networkstatus_download_failed(smartlist_t
*failed
,
54 static void dir_routerdesc_download_failed(smartlist_t
*failed
,
56 static void note_request(const char *key
, size_t bytes
);
58 /********* START VARIABLES **********/
60 /** How far in the future do we allow a directory server to tell us it is
61 * before deciding that one of us has the wrong time? */
62 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
64 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
66 /* HTTP cache control: how long do we tell proxies they can cache things? */
67 #define FULL_DIR_CACHE_LIFETIME (60*60)
68 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
69 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
70 #define ROUTERDESC_CACHE_LIFETIME (30*60)
71 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
72 #define ROBOTS_CACHE_LIFETIME (24*60*60)
74 /********* END VARIABLES ************/
76 /** Return true iff the directory purpose 'purpose' must use an
77 * anonymous connection to a directory. */
79 purpose_is_private(uint8_t purpose
)
81 if (get_options()->AllDirActionsPrivate
)
83 if (purpose
== DIR_PURPOSE_FETCH_DIR
||
84 purpose
== DIR_PURPOSE_UPLOAD_DIR
||
85 purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
||
86 purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
||
87 purpose
== DIR_PURPOSE_FETCH_SERVERDESC
)
92 /** Start a connection to every known directory server, using
93 * connection purpose 'purpose' and uploading the payload 'payload'
94 * (length 'payload_len'). The purpose should be one of
95 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
98 directory_post_to_dirservers(uint8_t purpose
, const char *payload
,
101 smartlist_t
*dirservers
;
103 int post_to_hidserv_only
;
105 dirservers
= router_get_trusted_dir_servers();
106 tor_assert(dirservers
);
107 /* Only old dirservers handle rendezvous descriptor publishing. */
108 post_to_hidserv_only
= (purpose
== DIR_PURPOSE_UPLOAD_RENDDESC
);
109 /* This tries dirservers which we believe to be down, but ultimately, that's
110 * harmless, and we may as well err on the side of getting things uploaded.
112 SMARTLIST_FOREACH(dirservers
, trusted_dir_server_t
*, ds
,
114 routerstatus_t
*rs
= &(ds
->fake_status
.status
);
115 if (post_to_hidserv_only
&& !ds
->is_hidserv_authority
)
117 if (!post_to_hidserv_only
&&
118 !(ds
->is_v1_authority
|| ds
->is_v2_authority
))
120 if (purpose
== DIR_PURPOSE_UPLOAD_DIR
)
121 ds
->has_accepted_serverdesc
= 0;
122 post_via_tor
= purpose_is_private(purpose
) ||
123 !fascist_firewall_allows_address_dir(ds
->addr
, ds
->dir_port
);
124 directory_initiate_command_routerstatus(rs
, purpose
, post_via_tor
,
125 NULL
, payload
, payload_len
);
129 /** Start a connection to a random running directory server, using
130 * connection purpose 'purpose' and requesting 'resource'.
131 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
132 * down, mark them up and try again.
135 directory_get_from_dirserver(uint8_t purpose
, const char *resource
,
136 int retry_if_no_servers
)
138 routerstatus_t
*rs
= NULL
;
139 or_options_t
*options
= get_options();
140 int prefer_authority
= server_mode(options
) && options
->DirPort
!= 0;
141 int directconn
= !purpose_is_private(purpose
);
142 authority_type_t type
;
144 /* FFFF we could break this switch into its own function, and call
145 * it elsewhere in directory.c. -RD */
147 case DIR_PURPOSE_FETCH_NETWORKSTATUS
:
148 case DIR_PURPOSE_FETCH_SERVERDESC
:
151 case DIR_PURPOSE_FETCH_DIR
:
152 case DIR_PURPOSE_FETCH_RUNNING_LIST
:
155 case DIR_PURPOSE_FETCH_RENDDESC
:
156 type
= HIDSERV_AUTHORITY
;
159 log_warn(LD_BUG
, "Unexpected purpose %d", (int)purpose
);
163 if (!options
->FetchServerDescriptors
&& type
!= HIDSERV_AUTHORITY
)
167 if (prefer_authority
) {
168 /* only ask authdirservers, and don't ask myself */
169 rs
= router_pick_trusteddirserver(type
, 1, 1,
170 retry_if_no_servers
);
173 /* anybody with a non-zero dirport will do */
174 rs
= router_pick_directory_server(1, 1, type
==V2_AUTHORITY
,
175 retry_if_no_servers
);
178 if (purpose
== DIR_PURPOSE_FETCH_DIR
)
180 else if (purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
)
181 which
= "status list";
182 else if (purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
)
183 which
= "network status";
184 else // if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
185 which
= "server descriptors";
187 "No router found for %s; falling back to dirserver list",
189 rs
= router_pick_trusteddirserver(type
, 1, 1,
190 retry_if_no_servers
);
192 directconn
= 0; /* last resort: try routing it via Tor */
197 /* Never use fascistfirewall; we're going via Tor. */
198 if (purpose
== DIR_PURPOSE_FETCH_RENDDESC
) {
199 /* only ask hidserv authorities, any of them will do */
200 rs
= router_pick_trusteddirserver(HIDSERV_AUTHORITY
, 0, 0,
201 retry_if_no_servers
);
203 /* anybody with a non-zero dirport will do. Disregard firewalls. */
204 rs
= router_pick_directory_server(1, 0, type
== V2_AUTHORITY
,
205 retry_if_no_servers
);
206 /* If we have any hope of building an indirect conn, we know some router
207 * descriptors. If (rs==NULL), we can't build circuits anyway, so
208 * there's no point in falling back to the authorities in this case. */
213 directory_initiate_command_routerstatus(rs
, purpose
, !directconn
,
217 "While fetching directory info, "
218 "no running dirservers known. Will try again later. "
219 "(purpose %d)", purpose
);
220 if (!purpose_is_private(purpose
)) {
221 /* remember we tried them all and failed. */
222 directory_all_unreachable(time(NULL
));
227 /** Launch a new connection to the directory server <b>router</b> to upload or
228 * download a service or rendezvous descriptor. <b>purpose</b> determines what
229 * kind of directory connection we're launching, and must be one of
230 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
232 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
233 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
235 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
239 directory_initiate_command_router(routerinfo_t
*router
,
241 int private_connection
,
242 const char *resource
,
246 directory_initiate_command(router
->address
, router
->addr
, router
->dir_port
,
248 router
->cache_info
.identity_digest
,
249 purpose
, private_connection
, resource
,
250 payload
, payload_len
);
253 /** Launch a new connection to the directory server <b>status</b> to upload or
254 * download a server or rendezvous descriptor. <b>purpose</b> determines what
255 * kind of directory connection we're launching, and must be one of
256 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
258 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
259 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
261 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
265 directory_initiate_command_routerstatus(routerstatus_t
*status
,
267 int private_connection
,
268 const char *resource
,
272 const char *platform
= NULL
;
273 routerinfo_t
*router
;
274 char address_buf
[INET_NTOA_BUF_LEN
+1];
277 if ((router
= router_get_by_digest(status
->identity_digest
))) {
278 platform
= router
->platform
;
279 address
= router
->address
;
281 in
.s_addr
= htonl(status
->addr
);
282 tor_inet_ntoa(&in
, address_buf
, sizeof(address_buf
));
283 address
= address_buf
;
285 directory_initiate_command(address
, status
->addr
, status
->dir_port
,
286 platform
, status
->identity_digest
,
287 purpose
, private_connection
, resource
,
288 payload
, payload_len
);
291 /** Return true iff <b>conn</b> is the client side of a directory connection
292 * we launched to ourself in order to determine the reachability of our
295 directory_conn_is_self_reachability_test(dir_connection_t
*conn
)
297 if (conn
->requested_resource
&&
298 !strcmpstart(conn
->requested_resource
,"authority")) {
299 routerinfo_t
*me
= router_get_my_routerinfo();
301 router_digest_is_me(conn
->identity_digest
) &&
302 me
->addr
== conn
->_base
.addr
&&
303 me
->dir_port
== conn
->_base
.port
)
309 /** Called when we are unable to complete the client's request to a directory
310 * server due to a network error: Mark the router as down and try again if
314 connection_dir_request_failed(dir_connection_t
*conn
)
316 if (router_digest_is_me(conn
->identity_digest
))
317 return; /* this was a test fetch. don't retry. */
318 router_set_status(conn
->identity_digest
, 0); /* don't try him again */
319 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_DIR
||
320 conn
->_base
.purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
) {
321 log_info(LD_DIR
, "Giving up on directory server at '%s:%d'; retrying",
322 conn
->_base
.address
, conn
->_base
.port
);
323 directory_get_from_dirserver(conn
->_base
.purpose
, NULL
,
324 0 /* don't retry_if_no_servers */);
326 if (directory_conn_is_self_reachability_test(conn
)) {
327 routerinfo_t
*me
= router_get_my_routerinfo();
329 control_event_server_status(LOG_WARN
,
330 "REACHABILITY_FAILED DIRADDRESS=%s:%d",
331 me
->address
, me
->dir_port
);
333 } else if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
) {
334 log_info(LD_DIR
, "Giving up on directory server at '%s'; retrying",
335 conn
->_base
.address
);
336 connection_dir_download_networkstatus_failed(conn
, -1);
337 } else if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_SERVERDESC
) {
338 log_info(LD_DIR
, "Giving up on directory server at '%s'; retrying",
339 conn
->_base
.address
);
340 connection_dir_download_routerdesc_failed(conn
);
344 /** Called when an attempt to download one or more network status
345 * documents on connection <b>conn</b> failed. Decide whether to
346 * retry the fetch now, later, or never.
349 connection_dir_download_networkstatus_failed(dir_connection_t
*conn
,
352 if (!conn
->requested_resource
) {
353 /* We never reached directory_send_command, which means that we never
354 * opened a network connection. Either we're out of sockets, or the
355 * network is down. Either way, retrying would be pointless. */
358 if (!strcmpstart(conn
->requested_resource
, "all")) {
359 /* We're a non-authoritative directory cache; try again. Ignore status
360 * code, since we don't want to keep trying forever in a tight loop
361 * if all the authorities are shutting us out. */
362 smartlist_t
*trusted_dirs
= router_get_trusted_dir_servers();
363 SMARTLIST_FOREACH(trusted_dirs
, trusted_dir_server_t
*, ds
,
364 ++ds
->n_networkstatus_failures
);
365 directory_get_from_dirserver(conn
->_base
.purpose
, "all.z",
366 0 /* don't retry_if_no_servers */);
367 } else if (!strcmpstart(conn
->requested_resource
, "fp/")) {
368 /* We were trying to download by fingerprint; mark them all as having
369 * failed, and possibly retry them later.*/
370 smartlist_t
*failed
= smartlist_create();
371 dir_split_resource_into_fingerprints(conn
->requested_resource
+3,
373 if (smartlist_len(failed
)) {
374 dir_networkstatus_download_failed(failed
, status_code
);
375 SMARTLIST_FOREACH(failed
, char *, cp
, tor_free(cp
));
377 smartlist_free(failed
);
381 /** Called when an attempt to download one or more router descriptors
382 * on connection <b>conn</b> failed.
385 connection_dir_download_routerdesc_failed(dir_connection_t
*conn
)
387 /* Try again. No need to increment the failure count for routerdescs, since
388 * it's not their fault.*/
389 /* update_router_descriptor_downloads(time(NULL)); */
391 /* XXXX012 Why did the above get commented out? -NM */
394 /** Return 1 if platform can handle a BEGIN_DIR cell, and if
395 * we're willing to send one. Else return 0. */
396 /* XXX we should refactor directory.c to hand status->or_port around,
397 * so we can check it here rather than platform. */
399 connection_dir_supports_tunnels(or_options_t
*options
, const char *platform
)
401 return options
->TunnelDirConns
&& platform
&&
402 tor_version_as_new_as(platform
, "0.1.2.2-alpha");
405 /** Helper for directory_initiate_command_(router|trusted_dir): send the
406 * command to a server whose address is <b>address</b>, whose IP is
407 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version is
408 * <b>platform</b>, and whose identity key digest is <b>digest</b>. The
409 * <b>platform</b> argument is optional; the others are required. */
411 directory_initiate_command(const char *address
, uint32_t addr
,
412 uint16_t dir_port
, const char *platform
,
413 const char *digest
, uint8_t purpose
,
414 int private_connection
, const char *resource
,
415 const char *payload
, size_t payload_len
)
417 dir_connection_t
*conn
;
418 or_options_t
*options
= get_options();
419 int want_to_tunnel
= connection_dir_supports_tunnels(options
, platform
);
423 tor_assert(dir_port
);
426 log_debug(LD_DIR
, "private %d, want_to_tunnel %d.",
427 private_connection
, want_to_tunnel
);
430 case DIR_PURPOSE_FETCH_DIR
:
431 log_debug(LD_DIR
,"initiating directory fetch");
433 case DIR_PURPOSE_FETCH_RENDDESC
:
434 log_debug(LD_DIR
,"initiating hidden-service descriptor fetch");
436 case DIR_PURPOSE_UPLOAD_DIR
:
437 log_debug(LD_OR
,"initiating server descriptor upload");
439 case DIR_PURPOSE_UPLOAD_RENDDESC
:
440 log_debug(LD_REND
,"initiating hidden-service descriptor upload");
442 case DIR_PURPOSE_FETCH_RUNNING_LIST
:
443 log_debug(LD_DIR
,"initiating running-routers fetch");
445 case DIR_PURPOSE_FETCH_NETWORKSTATUS
:
446 log_debug(LD_DIR
,"initiating network-status fetch");
448 case DIR_PURPOSE_FETCH_SERVERDESC
:
449 log_debug(LD_DIR
,"initiating server descriptor fetch");
452 log_err(LD_BUG
, "Unrecognized directory connection purpose.");
456 conn
= TO_DIR_CONN(connection_new(CONN_TYPE_DIR
));
458 /* set up conn so it's got all the data we need to remember */
459 conn
->_base
.addr
= addr
;
460 conn
->_base
.port
= dir_port
;
461 conn
->_base
.address
= tor_strdup(address
);
462 memcpy(conn
->identity_digest
, digest
, DIGEST_LEN
);
464 conn
->_base
.purpose
= purpose
;
466 /* give it an initial state */
467 conn
->_base
.state
= DIR_CONN_STATE_CONNECTING
;
469 if (!private_connection
&& !want_to_tunnel
) {
470 /* then we want to connect directly */
472 conn
->dirconn_direct
= 1;
473 if (options
->HttpProxy
) {
474 addr
= options
->HttpProxyAddr
;
475 dir_port
= options
->HttpProxyPort
;
478 switch (connection_connect(TO_CONN(conn
), conn
->_base
.address
, addr
,
481 connection_dir_request_failed(conn
); /* retry if we want */
482 connection_free(TO_CONN(conn
));
485 /* start flushing conn */
486 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_SENDING
;
489 /* queue the command on the outbuf */
490 directory_send_command(conn
, platform
, purpose
, 1, resource
,
491 payload
, payload_len
);
492 connection_watch_events(TO_CONN(conn
), EV_READ
| EV_WRITE
);
493 /* writable indicates finish, readable indicates broken link,
494 error indicates broken link in windowsland. */
496 } else { /* we want to connect via tor */
497 /* make an AP connection
498 * populate it and add it at the right state
499 * socketpair and hook up both sides
501 conn
->dirconn_direct
= 0;
503 connection_ap_make_bridge(conn
->_base
.address
, conn
->_base
.port
,
506 SOCKS_COMMAND_CONNECT
:
507 SOCKS_COMMAND_CONNECT_DIR
);
508 if (conn
->_base
.s
< 0) {
509 log_warn(LD_NET
,"Making AP bridge to dirserver failed.");
510 connection_mark_for_close(TO_CONN(conn
));
514 if (connection_add(TO_CONN(conn
)) < 0) {
515 log_warn(LD_NET
,"Unable to add AP bridge to dirserver.");
516 connection_mark_for_close(TO_CONN(conn
));
519 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_SENDING
;
520 /* queue the command on the outbuf */
521 directory_send_command(conn
, platform
, purpose
, 0, resource
,
522 payload
, payload_len
);
523 connection_watch_events(TO_CONN(conn
), EV_READ
| EV_WRITE
);
527 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
528 * are as in directory_initiate_command.
531 directory_send_command(dir_connection_t
*conn
, const char *platform
,
532 int purpose
, int direct
, const char *resource
,
533 const char *payload
, size_t payload_len
)
535 char proxystring
[256];
536 char proxyauthstring
[256];
537 char hoststring
[128];
540 const char *httpcommand
= NULL
;
544 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
546 tor_free(conn
->requested_resource
);
548 conn
->requested_resource
= tor_strdup(resource
);
550 /* come up with a string for which Host: we want */
551 if (conn
->_base
.port
== 80) {
552 strlcpy(hoststring
, conn
->_base
.address
, sizeof(hoststring
));
554 tor_snprintf(hoststring
, sizeof(hoststring
),"%s:%d",
555 conn
->_base
.address
, conn
->_base
.port
);
558 /* come up with some proxy lines, if we're using one. */
559 if (direct
&& get_options()->HttpProxy
) {
560 char *base64_authenticator
=NULL
;
561 const char *authenticator
= get_options()->HttpProxyAuthenticator
;
563 tor_snprintf(proxystring
, sizeof(proxystring
),"http://%s", hoststring
);
565 base64_authenticator
= alloc_http_authenticator(authenticator
);
566 if (!base64_authenticator
)
567 log_warn(LD_BUG
, "Encoding http authenticator failed");
569 if (base64_authenticator
) {
570 tor_snprintf(proxyauthstring
, sizeof(proxyauthstring
),
571 "\r\nProxy-Authorization: Basic %s",
572 base64_authenticator
);
573 tor_free(base64_authenticator
);
575 proxyauthstring
[0] = 0;
579 proxyauthstring
[0] = 0;
583 case DIR_PURPOSE_FETCH_DIR
:
584 tor_assert(!resource
);
585 tor_assert(!payload
);
587 "Asking for compressed directory from server running %s",
588 platform
?escaped(platform
):"<unknown version>");
590 url
= tor_strdup("/tor/dir.z");
592 case DIR_PURPOSE_FETCH_RUNNING_LIST
:
593 tor_assert(!resource
);
594 tor_assert(!payload
);
596 url
= tor_strdup("/tor/running-routers");
598 case DIR_PURPOSE_FETCH_NETWORKSTATUS
:
600 len
= strlen(resource
)+32;
601 url
= tor_malloc(len
);
602 tor_snprintf(url
, len
, "/tor/status/%s", resource
);
604 case DIR_PURPOSE_FETCH_SERVERDESC
:
606 len
= strlen(resource
)+32;
607 url
= tor_malloc(len
);
608 tor_snprintf(url
, len
, "/tor/server/%s", resource
);
610 case DIR_PURPOSE_UPLOAD_DIR
:
611 tor_assert(!resource
);
613 httpcommand
= "POST";
614 url
= tor_strdup("/tor/");
616 case DIR_PURPOSE_FETCH_RENDDESC
:
617 tor_assert(resource
);
618 tor_assert(!payload
);
620 /* this must be true or we wouldn't be doing the lookup */
621 tor_assert(strlen(resource
) <= REND_SERVICE_ID_LEN
);
622 /* This breaks the function abstraction. */
623 strlcpy(conn
->rend_query
, resource
, sizeof(conn
->rend_query
));
626 /* Request the most recent versioned descriptor. */
627 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
628 // but that never got testing, and it wasn't a good design.)
629 len
= strlen(resource
)+32;
630 url
= tor_malloc(len
);
631 tor_snprintf(url
, len
, "/tor/rendezvous/%s", resource
);
633 case DIR_PURPOSE_UPLOAD_RENDDESC
:
634 tor_assert(!resource
);
636 httpcommand
= "POST";
637 url
= tor_strdup("/tor/rendezvous/publish");
644 if (strlen(proxystring
) + strlen(url
) >= 4096) {
646 "Bug: squid does not like URLs longer than 4095 bytes, this "
647 "one is %d bytes long: %s%s",
648 (int)(strlen(proxystring
) + strlen(url
)), proxystring
, url
);
651 tor_snprintf(request
, sizeof(request
), "%s %s", httpcommand
, proxystring
);
652 connection_write_to_buf(request
, strlen(request
), TO_CONN(conn
));
653 connection_write_to_buf(url
, strlen(url
), TO_CONN(conn
));
656 if (!strcmp(httpcommand
, "GET") && !payload
) {
657 tor_snprintf(request
, sizeof(request
),
658 " HTTP/1.0\r\nHost: %s%s\r\n\r\n",
662 tor_snprintf(request
, sizeof(request
),
663 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
664 payload
? (unsigned long)payload_len
: 0,
668 connection_write_to_buf(request
, strlen(request
), TO_CONN(conn
));
671 /* then send the payload afterwards too */
672 connection_write_to_buf(payload
, payload_len
, TO_CONN(conn
));
676 /** Parse an HTTP request string <b>headers</b> of the form
678 * "\%s [http[s]://]\%s HTTP/1..."
680 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
681 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
682 * so it does. Return 0.
683 * Otherwise, return -1.
686 parse_http_url(char *headers
, char **url
)
688 char *s
, *start
, *tmp
;
690 s
= (char *)eat_whitespace_no_nl(headers
);
692 s
= (char *)find_whitespace(s
); /* get past GET/POST */
694 s
= (char *)eat_whitespace_no_nl(s
);
696 start
= s
; /* this is it, assuming it's valid */
697 s
= (char *)find_whitespace(start
);
700 /* tolerate the http[s] proxy style of putting the hostname in the url */
701 if (s
-start
>= 4 && !strcmpstart(start
,"http")) {
705 if (s
-tmp
>= 3 && !strcmpstart(tmp
,"://")) {
706 tmp
= strchr(tmp
+3, '/');
707 if (tmp
&& tmp
< s
) {
708 log_debug(LD_DIR
,"Skipping over 'http[s]://hostname' string");
714 if (s
-start
< 5 || strcmpstart(start
,"/tor/")) { /* need to rewrite it */
715 *url
= tor_malloc(s
- start
+ 5);
716 strlcpy(*url
,"/tor", s
-start
+5);
717 strlcat((*url
)+4, start
, s
-start
+1);
719 *url
= tor_strndup(start
, s
-start
);
724 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
725 * <b>which</b>. The key should be given with a terminating colon and space;
726 * this function copies everything after, up to but not including the
727 * following \\r\\n. */
729 http_get_header(const char *headers
, const char *which
)
731 const char *cp
= headers
;
733 if (!strcmpstart(cp
, which
)) {
736 if ((eos
= strchr(cp
,'\r')))
737 return tor_strndup(cp
, eos
-cp
);
739 return tor_strdup(cp
);
741 cp
= strchr(cp
, '\n');
748 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
749 * <b>conn</b>-\>address to describe our best guess of the address that
750 * originated this HTTP request. */
752 http_set_address_origin(const char *headers
, connection_t
*conn
)
756 fwd
= http_get_header(headers
, "Forwarded-For: ");
758 fwd
= http_get_header(headers
, "X-Forwarded-For: ");
760 tor_free(conn
->address
);
761 conn
->address
= tor_strdup(escaped(fwd
));
766 /** Parse an HTTP response string <b>headers</b> of the form
768 * "HTTP/1.\%d \%d\%s\r\n...".
771 * If it's well-formed, assign the status code to *<b>code</b> and
772 * return 0. Otherwise, return -1.
774 * On success: If <b>date</b> is provided, set *date to the Date
775 * header in the http headers, or 0 if no such header is found. If
776 * <b>compression</b> is provided, set *<b>compression</b> to the
777 * compression method given in the Content-Encoding header, or 0 if no
778 * such header is found, or -1 if the value of the header is not
779 * recognized. If <b>reason</b> is provided, strdup the reason string
783 parse_http_response(const char *headers
, int *code
, time_t *date
,
784 compress_method_t
*compression
, char **reason
)
787 char datestr
[RFC1123_TIME_LEN
+1];
788 smartlist_t
*parsed_headers
;
792 while (TOR_ISSPACE(*headers
)) headers
++; /* tolerate leading whitespace */
794 if (sscanf(headers
, "HTTP/1.%d %d", &n1
, &n2
) < 2 ||
795 (n1
!= 0 && n1
!= 1) ||
796 (n2
< 100 || n2
>= 600)) {
797 log_warn(LD_HTTP
,"Failed to parse header %s",escaped(headers
));
802 parsed_headers
= smartlist_create();
803 smartlist_split_string(parsed_headers
, headers
, "\n",
804 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
806 smartlist_t
*status_line_elements
= smartlist_create();
807 tor_assert(smartlist_len(parsed_headers
));
808 smartlist_split_string(status_line_elements
,
809 smartlist_get(parsed_headers
, 0),
810 " ", SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 3);
811 tor_assert(smartlist_len(status_line_elements
) <= 3);
812 if (smartlist_len(status_line_elements
) == 3) {
813 *reason
= smartlist_get(status_line_elements
, 2);
814 smartlist_set(status_line_elements
, 2, NULL
); /* Prevent free */
816 SMARTLIST_FOREACH(status_line_elements
, char *, cp
, tor_free(cp
));
817 smartlist_free(status_line_elements
);
821 SMARTLIST_FOREACH(parsed_headers
, const char *, s
,
822 if (!strcmpstart(s
, "Date: ")) {
823 strlcpy(datestr
, s
+6, sizeof(datestr
));
824 /* This will do nothing on failure, so we don't need to check
825 the result. We shouldn't warn, since there are many other valid
826 date formats besides the one we use. */
827 parse_rfc1123_time(datestr
, date
);
832 const char *enc
= NULL
;
833 SMARTLIST_FOREACH(parsed_headers
, const char *, s
,
834 if (!strcmpstart(s
, "Content-Encoding: ")) {
837 if (!enc
|| !strcmp(enc
, "identity")) {
838 *compression
= NO_METHOD
;
839 } else if (!strcmp(enc
, "deflate") || !strcmp(enc
, "x-deflate")) {
840 *compression
= ZLIB_METHOD
;
841 } else if (!strcmp(enc
, "gzip") || !strcmp(enc
, "x-gzip")) {
842 *compression
= GZIP_METHOD
;
844 log_info(LD_HTTP
, "Unrecognized content encoding: %s. Trying to deal.",
846 *compression
= UNKNOWN_METHOD
;
849 SMARTLIST_FOREACH(parsed_headers
, char *, s
, tor_free(s
));
850 smartlist_free(parsed_headers
);
855 /** Return true iff <b>body</b> doesn't start with a plausible router or
856 * running-list or directory opening. This is a sign of possible compression.
859 body_is_plausible(const char *body
, size_t len
, int purpose
)
863 return 1; /* empty bodies don't need decompression */
866 if (purpose
!= DIR_PURPOSE_FETCH_RENDDESC
) {
867 if (!strcmpstart(body
,"router") ||
868 !strcmpstart(body
,"signed-directory") ||
869 !strcmpstart(body
,"network-status") ||
870 !strcmpstart(body
,"running-routers"))
873 if (!TOR_ISPRINT(body
[i
]) && !TOR_ISSPACE(body
[i
]))
882 /** We are a client, and we've finished reading the server's
883 * response. Parse and it and act appropriately.
885 * If we're still happy with using this directory server in the future, return
886 * 0. Otherwise return -1; and the caller should consider trying the request
889 * The caller will take care of marking the connection for close.
892 connection_dir_client_reached_eof(dir_connection_t
*conn
)
897 size_t body_len
=0, orig_len
=0;
899 time_t date_header
=0;
901 compress_method_t compression
;
904 int allow_partial
= conn
->_base
.purpose
== DIR_PURPOSE_FETCH_SERVERDESC
;
905 int was_compressed
=0;
907 switch (fetch_from_buf_http(conn
->_base
.inbuf
,
908 &headers
, MAX_HEADERS_SIZE
,
909 &body
, &body_len
, MAX_DIR_SIZE
,
911 case -1: /* overflow */
912 log_warn(LD_PROTOCOL
,
913 "'fetch' response too large (server '%s:%d'). Closing.",
914 conn
->_base
.address
, conn
->_base
.port
);
918 "'fetch' response not all here, but we're at eof. Closing.");
920 /* case 1, fall through */
924 if (parse_http_response(headers
, &status_code
, &date_header
,
925 &compression
, &reason
) < 0) {
926 log_warn(LD_HTTP
,"Unparseable headers (server '%s:%d'). Closing.",
927 conn
->_base
.address
, conn
->_base
.port
);
928 tor_free(body
); tor_free(headers
);
931 if (!reason
) reason
= tor_strdup("[no reason given]");
934 "Received response from directory server '%s:%d': %d %s",
935 conn
->_base
.address
, conn
->_base
.port
, status_code
,
938 /* now check if it's got any hints for us about our IP address. */
939 if (conn
->dirconn_direct
) {
940 char *guess
= http_get_header(headers
, X_ADDRESS_HEADER
);
942 router_new_address_suggestion(guess
);
947 if (date_header
> 0) {
948 /* The date header was written very soon after we sent our request,
949 * so compute the skew as the difference between sending the request
950 * and the date header. (We used to check now-date_header, but that's
951 * inaccurate if we spend a lot of time downloading.)
953 delta
= conn
->_base
.timestamp_lastwritten
- date_header
;
954 if (abs(delta
)>ALLOW_DIRECTORY_TIME_SKEW
) {
955 int trusted
= router_digest_is_trusted_dir(conn
->identity_digest
);
956 log_fn(trusted
? LOG_WARN
: LOG_INFO
,
958 "Received directory with skewed time (server '%s:%d'): "
959 "we are %d minutes %s, or the directory is %d minutes %s.",
960 conn
->_base
.address
, conn
->_base
.port
,
961 abs(delta
)/60, delta
>0 ? "ahead" : "behind",
962 abs(delta
)/60, delta
>0 ? "behind" : "ahead");
963 skewed
= 1; /* don't check the recommended-versions line */
964 control_event_general_status(trusted
? LOG_WARN
: LOG_NOTICE
,
965 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
966 delta
, conn
->_base
.address
, conn
->_base
.port
);
968 log_debug(LD_HTTP
, "Time on received directory is within tolerance; "
969 "we are %d seconds skewed. (That's okay.)", delta
);
972 (void) skewed
; /* skewed isn't used yet. */
974 if (status_code
== 503) {
975 local_routerstatus_t
*rs
;
976 trusted_dir_server_t
*ds
;
977 time_t now
= time(NULL
);
978 log_info(LD_DIR
,"Received http status code %d (%s) from server "
979 "'%s:%d'. I'll try again soon.",
980 status_code
, escaped(reason
), conn
->_base
.address
,
982 if ((rs
= router_get_combined_status_by_digest(conn
->identity_digest
)))
983 rs
->last_dir_503_at
= now
;
984 if ((ds
= router_get_trusteddirserver_by_digest(conn
->identity_digest
)))
985 ds
->fake_status
.last_dir_503_at
= now
;
987 tor_free(body
); tor_free(headers
); tor_free(reason
);
991 plausible
= body_is_plausible(body
, body_len
, conn
->_base
.purpose
);
992 if (compression
!= NO_METHOD
|| !plausible
) {
993 char *new_body
= NULL
;
995 compress_method_t guessed
= detect_compression_method(body
, body_len
);
996 if (compression
== UNKNOWN_METHOD
|| guessed
!= compression
) {
997 /* Tell the user if we don't believe what we're told about compression.*/
998 const char *description1
, *description2
;
999 if (compression
== ZLIB_METHOD
)
1000 description1
= "as deflated";
1001 else if (compression
== GZIP_METHOD
)
1002 description1
= "as gzipped";
1003 else if (compression
== NO_METHOD
)
1004 description1
= "as uncompressed";
1006 description1
= "with an unknown Content-Encoding";
1007 if (guessed
== ZLIB_METHOD
)
1008 description2
= "deflated";
1009 else if (guessed
== GZIP_METHOD
)
1010 description2
= "gzipped";
1011 else if (!plausible
)
1012 description2
= "confusing binary junk";
1014 description2
= "uncompressed";
1016 log_info(LD_HTTP
, "HTTP body from server '%s:%d' was labeled %s, "
1017 "but it seems to be %s.%s",
1018 conn
->_base
.address
, conn
->_base
.port
, description1
,
1020 (compression
>0 && guessed
>0)?" Trying both.":"");
1022 /* Try declared compression first if we can. */
1023 if (compression
== GZIP_METHOD
|| compression
== ZLIB_METHOD
)
1024 tor_gzip_uncompress(&new_body
, &new_len
, body
, body_len
, compression
,
1025 !allow_partial
, LOG_PROTOCOL_WARN
);
1026 /* Okay, if that didn't work, and we think that it was compressed
1027 * differently, try that. */
1029 (guessed
== GZIP_METHOD
|| guessed
== ZLIB_METHOD
) &&
1030 compression
!= guessed
)
1031 tor_gzip_uncompress(&new_body
, &new_len
, body
, body_len
, guessed
,
1032 !allow_partial
, LOG_PROTOCOL_WARN
);
1033 /* If we're pretty sure that we have a compressed directory, and
1034 * we didn't manage to uncompress it, then warn and bail. */
1035 if (!plausible
&& !new_body
) {
1036 log_fn(LOG_PROTOCOL_WARN
, LD_HTTP
,
1037 "Unable to decompress HTTP body (server '%s:%d').",
1038 conn
->_base
.address
, conn
->_base
.port
);
1039 tor_free(body
); tor_free(headers
); tor_free(reason
);
1050 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_DIR
) {
1051 /* fetch/process the directory to cache it. */
1052 log_info(LD_DIR
,"Received directory (size %d) from server '%s:%d'",
1053 (int)body_len
, conn
->_base
.address
, conn
->_base
.port
);
1054 if (status_code
!= 200) {
1055 log_warn(LD_DIR
,"Received http status code %d (%s) from server "
1056 "'%s:%d' while fetching directory. I'll try again soon.",
1057 status_code
, escaped(reason
), conn
->_base
.address
,
1059 tor_free(body
); tor_free(headers
); tor_free(reason
);
1062 if (router_parse_directory(body
) < 0) {
1063 log_notice(LD_DIR
,"I failed to parse the directory I fetched from "
1064 "'%s:%d'. Ignoring.", conn
->_base
.address
, conn
->_base
.port
);
1066 note_request(was_compressed
?"dl/dir.z":"dl/dir", orig_len
);
1069 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
) {
1070 /* just update our list of running routers, if this list is new info */
1071 log_info(LD_DIR
,"Received running-routers list (size %d)", (int)body_len
);
1072 if (status_code
!= 200) {
1073 log_warn(LD_DIR
,"Received http status code %d (%s) from server "
1074 "'%s:%d' while fetching running-routers. I'll try again soon.",
1075 status_code
, escaped(reason
), conn
->_base
.address
,
1077 tor_free(body
); tor_free(headers
); tor_free(reason
);
1080 if (router_parse_runningrouters(body
)<0) {
1082 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1083 conn
->_base
.address
, conn
->_base
.port
);
1084 tor_free(body
); tor_free(headers
); tor_free(reason
);
1087 note_request(was_compressed
?"dl/running-routers.z":
1088 "dl/running-routers", orig_len
);
1091 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
) {
1092 smartlist_t
*which
= NULL
;
1093 networkstatus_source_t source
;
1095 log_info(LD_DIR
,"Received networkstatus objects (size %d) from server "
1096 "'%s:%d'",(int) body_len
, conn
->_base
.address
, conn
->_base
.port
);
1097 if (status_code
!= 200) {
1099 "Received http status code %d (%s) from server "
1100 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1101 status_code
, escaped(reason
), conn
->_base
.address
,
1102 conn
->_base
.port
, conn
->requested_resource
);
1103 tor_free(body
); tor_free(headers
); tor_free(reason
);
1104 connection_dir_download_networkstatus_failed(conn
, status_code
);
1107 note_request(was_compressed
?"dl/status.z":"dl/status", orig_len
);
1108 if (conn
->requested_resource
&&
1109 !strcmpstart(conn
->requested_resource
,"fp/")) {
1110 source
= NS_FROM_DIR_BY_FP
;
1111 which
= smartlist_create();
1112 dir_split_resource_into_fingerprints(conn
->requested_resource
+3,
1114 } else if (conn
->requested_resource
&&
1115 !strcmpstart(conn
->requested_resource
, "all")) {
1116 source
= NS_FROM_DIR_ALL
;
1117 which
= smartlist_create();
1118 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1119 trusted_dir_server_t
*, ds
,
1121 char *cp
= tor_malloc(HEX_DIGEST_LEN
+1);
1122 base16_encode(cp
, HEX_DIGEST_LEN
+1, ds
->digest
, DIGEST_LEN
);
1123 smartlist_add(which
, cp
);
1126 /* Can we even end up here? -- weasel*/
1127 source
= NS_FROM_DIR_BY_FP
;
1128 log_warn(LD_BUG
, "We received a networkstatus but we didn't ask "
1129 "for it by fp, nor did we ask for all.");
1133 char *next
= strstr(cp
, "\nnetwork-status-version");
1136 /* learn from it, and then remove it from 'which' */
1137 if (router_set_networkstatus(cp
, time(NULL
), source
, which
)<0)
1146 routers_update_all_from_networkstatus(); /*launches router downloads*/
1147 directory_info_has_arrived(time(NULL
), 0);
1149 if (smartlist_len(which
)) {
1150 dir_networkstatus_download_failed(which
, status_code
);
1152 SMARTLIST_FOREACH(which
, char *, cp
, tor_free(cp
));
1153 smartlist_free(which
);
1157 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_SERVERDESC
) {
1158 smartlist_t
*which
= NULL
;
1159 int n_asked_for
= 0;
1160 log_info(LD_DIR
,"Received server info (size %d) from server '%s:%d'",
1161 (int)body_len
, conn
->_base
.address
, conn
->_base
.port
);
1162 note_request(was_compressed
?"dl/server.z":"dl/server", orig_len
);
1163 if (conn
->requested_resource
&&
1164 !strcmpstart(conn
->requested_resource
,"d/")) {
1165 which
= smartlist_create();
1166 dir_split_resource_into_fingerprints(conn
->requested_resource
+2,
1168 n_asked_for
= smartlist_len(which
);
1170 if (status_code
!= 200) {
1171 int dir_okay
= status_code
== 404 ||
1172 (status_code
== 400 && !strcmp(reason
, "Servers unavailable."));
1173 /* 404 means that it didn't have them; no big deal.
1174 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1175 log_fn(dir_okay
? LOG_INFO
: LOG_WARN
, LD_DIR
,
1176 "Received http status code %d (%s) from server '%s:%d' "
1177 "while fetching \"/tor/server/%s\". I'll try again soon.",
1178 status_code
, escaped(reason
), conn
->_base
.address
,
1179 conn
->_base
.port
, conn
->requested_resource
);
1181 connection_dir_download_routerdesc_failed(conn
);
1183 dir_routerdesc_download_failed(which
, status_code
);
1184 SMARTLIST_FOREACH(which
, char *, cp
, tor_free(cp
));
1185 smartlist_free(which
);
1187 tor_free(body
); tor_free(headers
); tor_free(reason
);
1188 return dir_okay
? 0 : -1;
1190 /* Learn the routers, assuming we requested by fingerprint or "all".
1191 * Right now, we only use "authority" to fetch ourself, so we don't want
1192 * to risk replacing ourself with a router running at the addr:port we
1195 if (which
|| (conn
->requested_resource
&&
1196 !strcmpstart(conn
->requested_resource
, "all"))) {
1197 /* as we learn from them, we remove them from 'which' */
1198 router_load_routers_from_string(body
, SAVED_NOWHERE
, which
);
1199 directory_info_has_arrived(time(NULL
), 0);
1201 if (which
) { /* mark remaining ones as failed */
1202 log_info(LD_DIR
, "Received %d/%d routers requested from %s:%d",
1203 n_asked_for
-smartlist_len(which
), n_asked_for
,
1204 conn
->_base
.address
, (int)conn
->_base
.port
);
1205 if (smartlist_len(which
)) {
1206 dir_routerdesc_download_failed(which
, status_code
);
1208 SMARTLIST_FOREACH(which
, char *, cp
, tor_free(cp
));
1209 smartlist_free(which
);
1211 if (directory_conn_is_self_reachability_test(conn
))
1212 router_dirport_found_reachable();
1215 if (conn
->_base
.purpose
== DIR_PURPOSE_UPLOAD_DIR
) {
1216 switch (status_code
) {
1219 trusted_dir_server_t
*ds
=
1220 router_get_trusteddirserver_by_digest(conn
->identity_digest
);
1221 smartlist_t
*servers
;
1222 log_info(LD_GENERAL
,"eof (status 200) after uploading server "
1223 "descriptor: finished.");
1224 control_event_server_status(
1225 LOG_NOTICE
, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1226 conn
->_base
.address
, conn
->_base
.port
);
1228 ds
->has_accepted_serverdesc
= 1;
1229 servers
= router_get_trusted_dir_servers();
1230 SMARTLIST_FOREACH(servers
, trusted_dir_server_t
*, d
, {
1231 if ((d
->is_v1_authority
|| d
->is_v2_authority
) &&
1232 !d
->has_accepted_serverdesc
) {
1238 control_event_server_status(LOG_NOTICE
, "GOOD_SERVER_DESCRIPTOR");
1242 log_warn(LD_GENERAL
,"http status 400 (%s) response from "
1243 "dirserver '%s:%d'. Please correct.",
1244 escaped(reason
), conn
->_base
.address
, conn
->_base
.port
);
1245 control_event_server_status(LOG_WARN
,
1246 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1247 conn
->_base
.address
, conn
->_base
.port
, escaped(reason
));
1250 log_warn(LD_GENERAL
,
1251 "http status 403 (%s) response from dirserver "
1252 "'%s:%d'. Is your clock skewed? Have you mailed us your key "
1253 "fingerprint? Are you using the right key? Are you using a "
1254 "private IP address? See http://tor.eff.org/doc/"
1255 "tor-doc-server.html",escaped(reason
), conn
->_base
.address
,
1257 control_event_server_status(LOG_WARN
,
1258 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1259 conn
->_base
.address
, conn
->_base
.port
, escaped(reason
));
1262 log_warn(LD_GENERAL
,
1263 "http status %d (%s) reason unexpected while uploading "
1264 "descriptor to server '%s:%d').",
1265 status_code
, escaped(reason
), conn
->_base
.address
,
1269 /* return 0 in all cases, since we don't want to mark any
1270 * dirservers down just because they don't like us. */
1273 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_RENDDESC
) {
1274 log_info(LD_REND
,"Received rendezvous descriptor (size %d, status %d "
1276 (int)body_len
, status_code
, escaped(reason
));
1277 switch (status_code
) {
1279 if (rend_cache_store(body
, body_len
) < 0) {
1280 log_warn(LD_REND
,"Failed to store rendezvous descriptor.");
1281 /* alice's ap_stream will notice when connection_mark_for_close
1284 /* success. notify pending connections about this. */
1285 conn
->_base
.purpose
= DIR_PURPOSE_HAS_FETCHED_RENDDESC
;
1286 rend_client_desc_here(conn
->rend_query
);
1290 /* not there. pending connections will be notified when
1291 * connection_mark_for_close cleans it up. */
1295 "http status 400 (%s). Dirserver didn't like our "
1296 "rendezvous query?", escaped(reason
));
1299 log_warn(LD_REND
,"http status %d (%s) response unexpected while "
1300 "fetching hidden service descriptor (server '%s:%d').",
1301 status_code
, escaped(reason
), conn
->_base
.address
,
1307 if (conn
->_base
.purpose
== DIR_PURPOSE_UPLOAD_RENDDESC
) {
1308 switch (status_code
) {
1311 "Uploading rendezvous descriptor: finished with status "
1312 "200 (%s)", escaped(reason
));
1315 log_warn(LD_REND
,"http status 400 (%s) response from dirserver "
1316 "'%s:%d'. Malformed rendezvous descriptor?",
1317 escaped(reason
), conn
->_base
.address
, conn
->_base
.port
);
1320 log_warn(LD_REND
,"http status %d (%s) response unexpected (server "
1322 status_code
, escaped(reason
), conn
->_base
.address
,
1327 tor_free(body
); tor_free(headers
); tor_free(reason
);
1331 /** Called when a directory connection reaches EOF */
1333 connection_dir_reached_eof(dir_connection_t
*conn
)
1336 if (conn
->_base
.state
!= DIR_CONN_STATE_CLIENT_READING
) {
1337 log_info(LD_HTTP
,"conn reached eof, not reading. Closing.");
1338 connection_close_immediate(TO_CONN(conn
)); /* error: give up on flushing */
1339 connection_mark_for_close(TO_CONN(conn
));
1343 retval
= connection_dir_client_reached_eof(conn
);
1344 if (retval
== 0) /* success */
1345 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_FINISHED
;
1346 connection_mark_for_close(TO_CONN(conn
));
1350 /** If any directory object is arriving, and it's over 10MB large, we're
1351 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1352 * ask for more than 96 router descriptors at a time.)
1354 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1356 /** Read handler for directory connections. (That's connections <em>to</em>
1357 * directory servers and connections <em>at</em> directory servers.)
1360 connection_dir_process_inbuf(dir_connection_t
*conn
)
1363 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
1365 /* Directory clients write, then read data until they receive EOF;
1366 * directory servers read data until they get an HTTP command, then
1367 * write their response (when it's finished flushing, they mark for
1371 /* If we're on the dirserver side, look for a command. */
1372 if (conn
->_base
.state
== DIR_CONN_STATE_SERVER_COMMAND_WAIT
) {
1373 if (directory_handle_command(conn
) < 0) {
1374 connection_mark_for_close(TO_CONN(conn
));
1380 if (buf_datalen(conn
->_base
.inbuf
) > MAX_DIRECTORY_OBJECT_SIZE
) {
1381 log_warn(LD_HTTP
, "Too much data received from directory connection: "
1382 "denial of service attempt, or you need to upgrade?");
1383 connection_mark_for_close(TO_CONN(conn
));
1387 if (!conn
->_base
.inbuf_reached_eof
)
1388 log_debug(LD_HTTP
,"Got data, not eof. Leaving on inbuf.");
1392 /** Create an http response for the client <b>conn</b> out of
1393 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1396 write_http_status_line(dir_connection_t
*conn
, int status
,
1397 const char *reason_phrase
)
1400 if (tor_snprintf(buf
, sizeof(buf
), "HTTP/1.0 %d %s\r\n\r\n",
1401 status
, reason_phrase
) < 0) {
1402 log_warn(LD_BUG
,"Bug: status line too long.");
1405 connection_write_to_buf(buf
, strlen(buf
), TO_CONN(conn
));
1408 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1409 * with <b>type</b> as the Content-Type.
1411 * If <b>length</b> is nonnegative, it is the Content-Length.
1412 * If <b>encoding</b> is provided, it is the Content-Encoding.
1413 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1414 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1416 write_http_response_header(dir_connection_t
*conn
, ssize_t length
,
1417 const char *type
, const char *encoding
,
1420 char date
[RFC1123_TIME_LEN
+1];
1423 time_t now
= time(NULL
);
1428 format_rfc1123_time(date
, now
);
1430 tor_snprintf(cp
, sizeof(tmp
),
1431 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n",
1434 if (!is_internal_IP(conn
->_base
.addr
, 0)) {
1435 /* Don't report the source address for a localhost/private connection. */
1436 tor_snprintf(cp
, sizeof(tmp
)-(cp
-tmp
),
1437 X_ADDRESS_HEADER
"%s\r\n", conn
->_base
.address
);
1441 tor_snprintf(cp
, sizeof(tmp
)-(cp
-tmp
),
1442 "Content-Encoding: %s\r\n", encoding
);
1446 tor_snprintf(cp
, sizeof(tmp
)-(cp
-tmp
),
1447 "Content-Length: %ld\r\n", (long)length
);
1450 if (cache_lifetime
> 0) {
1451 char expbuf
[RFC1123_TIME_LEN
+1];
1452 format_rfc1123_time(expbuf
, now
+ cache_lifetime
);
1453 /* We could say 'Cache-control: max-age=%d' here if we start doing
1455 tor_snprintf(cp
, sizeof(tmp
)-(cp
-tmp
),
1456 "Expires: %s\r\n", expbuf
);
1459 /* We could say 'Cache-control: no-cache' here if we start doing
1461 strlcpy(cp
, "Pragma: no-cache\r\n", sizeof(tmp
)-(cp
-tmp
));
1464 if (sizeof(tmp
)-(cp
-tmp
) > 3)
1465 memcpy(cp
, "\r\n", 3);
1468 connection_write_to_buf(tmp
, strlen(tmp
), TO_CONN(conn
));
1471 /** Helper function: return 1 if there are any dir conns of purpose
1472 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1476 already_fetching_directory(int purpose
)
1480 connection_t
**carray
;
1482 get_connection_array(&carray
,&n
);
1485 if (conn
->type
== CONN_TYPE_DIR
&&
1486 conn
->purpose
== purpose
&&
1487 !conn
->marked_for_close
&&
1488 !router_digest_is_me(TO_DIR_CONN(conn
)->identity_digest
))
1494 #undef INSTRUMENT_DOWNLOADS
1496 #ifdef INSTRUMENT_DOWNLOADS
1498 static strmap_t
*request_bytes_map
= NULL
;
1502 note_request(const char *key
, size_t bytes
)
1505 if (!request_bytes_map
)
1506 request_bytes_map
= strmap_new();
1508 n
= strmap_get(request_bytes_map
, key
);
1510 n
= tor_malloc_zero(sizeof(uint64_t));
1511 strmap_set(request_bytes_map
, key
, n
);
1518 directory_dump_request_log(void)
1523 strmap_iter_t
*iter
;
1525 if (!request_bytes_map
)
1526 request_bytes_map
= strmap_new();
1528 lines
= smartlist_create();
1530 for (iter
= strmap_iter_init(request_bytes_map
);
1531 !strmap_iter_done(iter
);
1532 iter
= strmap_iter_next(request_bytes_map
, iter
)) {
1536 strmap_iter_get(iter
, &key
, &val
);
1538 tor_snprintf(tmp
, sizeof(tmp
), "%s "U64_FORMAT
"\n",
1539 key
, U64_PRINTF_ARG(*n
));
1540 smartlist_add(lines
, tor_strdup(tmp
));
1542 smartlist_sort_strings(lines
);
1543 result
= smartlist_join_strings(lines
, "", 0, NULL
);
1544 SMARTLIST_FOREACH(lines
, char *, cp
, tor_free(cp
));
1545 smartlist_free(lines
);
1550 note_request(const char *key
, size_t bytes
)
1557 directory_dump_request_log(void)
1559 return tor_strdup("Not supported.");
1563 /** Helper function: called when a dirserver gets a complete HTTP GET
1564 * request. Look for a request for a directory or for a rendezvous
1565 * service descriptor. On finding one, write a response into
1566 * conn-\>outbuf. If the request is unrecognized, send a 400.
1567 * Always return 0. */
1569 directory_handle_command_get(dir_connection_t
*conn
, char *headers
,
1570 char *body
, size_t body_len
)
1575 or_options_t
*options
= get_options();
1576 /* We ignore the body of a GET request. */
1580 log_debug(LD_DIRSERV
,"Received GET command.");
1582 conn
->_base
.state
= DIR_CONN_STATE_SERVER_WRITING
;
1584 if (parse_http_url(headers
, &url
) < 0) {
1585 write_http_status_line(conn
, 400, "Bad request");
1588 log_debug(LD_DIRSERV
,"rewritten url as '%s'.", url
);
1590 if (!strcmp(url
,"/tor/") || !strcmp(url
,"/tor/dir.z")) { /* dir fetch */
1591 int deflated
= !strcmp(url
,"/tor/dir.z");
1592 cached_dir_t
*d
= dirserv_get_directory();
1595 log_notice(LD_DIRSERV
,"Client asked for the mirrored directory, but we "
1596 "don't have a good one yet. Sending 503 Dir not available.");
1597 write_http_status_line(conn
, 503, "Directory unavailable");
1598 /* try to get a new one now */
1599 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR
))
1600 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR
, NULL
, 1);
1604 dlen
= deflated
? d
->dir_z_len
: d
->dir_len
;
1606 if (global_write_bucket_low(dlen
, 1)) {
1607 log_info(LD_DIRSERV
,
1608 "Client asked for the mirrored directory, but we've been "
1609 "writing too many bytes lately. Sending 503 Dir busy.");
1610 write_http_status_line(conn
, 503, "Directory busy, try again later");
1615 note_request(url
, dlen
);
1618 log_debug(LD_DIRSERV
,"Dumping %sdirectory to client.",
1619 deflated
?"deflated ":"");
1620 write_http_response_header(conn
, dlen
,
1621 deflated
?"application/octet-stream":"text/plain",
1622 deflated
?"deflate":"identity",
1623 FULL_DIR_CACHE_LIFETIME
);
1624 conn
->cached_dir
= d
;
1625 conn
->cached_dir_offset
= 0;
1627 conn
->zlib_state
= tor_zlib_new(0, ZLIB_METHOD
);
1630 /* Prime the connection with some data. */
1631 conn
->dir_spool_src
= DIR_SPOOL_CACHED_DIR
;
1632 connection_dirserv_flushed_some(conn
);
1636 if (!strcmp(url
,"/tor/running-routers") ||
1637 !strcmp(url
,"/tor/running-routers.z")) { /* running-routers fetch */
1638 int deflated
= !strcmp(url
,"/tor/running-routers.z");
1639 dlen
= dirserv_get_runningrouters(&cp
, deflated
);
1640 if (!dlen
) { /* we failed to create/cache cp */
1641 write_http_status_line(conn
, 503, "Directory unavailable");
1642 /* try to get a new one now */
1643 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST
))
1644 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST
, NULL
, 1);
1648 if (global_write_bucket_low(dlen
, 1)) {
1649 log_info(LD_DIRSERV
,
1650 "Client asked for running-routers, but we've been "
1651 "writing too many bytes lately. Sending 503 Dir busy.");
1652 write_http_status_line(conn
, 503, "Directory busy, try again later");
1656 note_request(url
, dlen
);
1658 write_http_response_header(conn
, dlen
,
1659 deflated
?"application/octet-stream":"text/plain",
1660 deflated
?"deflate":"identity",
1661 RUNNINGROUTERS_CACHE_LIFETIME
);
1662 connection_write_to_buf(cp
, strlen(cp
), TO_CONN(conn
));
1666 if (!strcmpstart(url
,"/tor/status/")) {
1667 /* v2 network status fetch. */
1668 size_t url_len
= strlen(url
);
1669 int deflated
= !strcmp(url
+url_len
-2, ".z");
1670 smartlist_t
*dir_fps
= smartlist_create();
1671 const char *request_type
= NULL
;
1672 const char *key
= url
+ strlen("/tor/status/");
1674 url
[url_len
-2] = '\0';
1675 dirserv_get_networkstatus_v2_fingerprints(dir_fps
, key
);
1676 if (!strcmpstart(key
, "fp/"))
1677 request_type
= deflated
?"/tor/status/fp.z":"/tor/status/fp";
1678 else if (!strcmpstart(key
, "authority"))
1679 request_type
= deflated
?"/tor/status/authority.z":
1680 "/tor/status/authority";
1681 else if (!strcmpstart(key
, "all"))
1682 request_type
= deflated
?"/tor/status/all.z":"/tor/status/all";
1684 request_type
= "/tor/status/?";
1686 if (!smartlist_len(dir_fps
)) { /* we failed to create/cache cp */
1687 write_http_status_line(conn
, 503, "Network status object unavailable");
1688 smartlist_free(dir_fps
);
1691 dlen
= dirserv_estimate_data_size(dir_fps
, 0, deflated
);
1692 if (global_write_bucket_low(dlen
, 2)) {
1693 log_info(LD_DIRSERV
,
1694 "Client asked for network status lists, but we've been "
1695 "writing too many bytes lately. Sending 503 Dir busy.");
1696 write_http_status_line(conn
, 503, "Directory busy, try again later");
1697 SMARTLIST_FOREACH(dir_fps
, char *, cp
, tor_free(cp
));
1698 smartlist_free(dir_fps
);
1702 // note_request(request_type,dlen);
1703 (void) request_type
;
1704 write_http_response_header(conn
, -1,
1705 deflated
?"application/octet_stream":"text/plain",
1706 deflated
?"deflate":NULL
,
1707 smartlist_len(dir_fps
) == 1 ? NETWORKSTATUS_CACHE_LIFETIME
:0);
1708 conn
->fingerprint_stack
= dir_fps
;
1710 conn
->zlib_state
= tor_zlib_new(0, ZLIB_METHOD
);
1712 /* Prime the connection with some data. */
1713 conn
->dir_spool_src
= DIR_SPOOL_NETWORKSTATUS
;
1714 connection_dirserv_flushed_some(conn
);
1719 if (!strcmpstart(url
,"/tor/server/")) {
1720 size_t url_len
= strlen(url
);
1721 int deflated
= !strcmp(url
+url_len
-2, ".z");
1724 const char *request_type
= NULL
;
1725 int cache_lifetime
= 0;
1727 url
[url_len
-2] = '\0';
1728 conn
->fingerprint_stack
= smartlist_create();
1729 res
= dirserv_get_routerdesc_fingerprints(conn
->fingerprint_stack
, url
,
1732 if (!strcmpstart(url
, "/tor/server/fp/")) {
1733 request_type
= deflated
?"/tor/server/fp.z":"/tor/server/fp";
1734 if (smartlist_len(conn
->fingerprint_stack
) == 1)
1735 cache_lifetime
= ROUTERDESC_CACHE_LIFETIME
;
1736 } else if (!strcmpstart(url
, "/tor/server/authority")) {
1737 request_type
= deflated
?"/tor/server/authority.z":
1738 "/tor/server/authority";
1739 cache_lifetime
= ROUTERDESC_CACHE_LIFETIME
;
1740 } else if (!strcmpstart(url
, "/tor/server/all")) {
1741 request_type
= deflated
?"/tor/server/all.z":"/tor/server/all";
1742 cache_lifetime
= FULL_DIR_CACHE_LIFETIME
;
1743 } else if (!strcmpstart(url
, "/tor/server/d/")) {
1744 request_type
= deflated
?"/tor/server/d.z":"/tor/server/d";
1745 if (smartlist_len(conn
->fingerprint_stack
) == 1)
1746 cache_lifetime
= ROUTERDESC_BY_DIGEST_CACHE_LIFETIME
;
1748 request_type
= "/tor/server/?";
1750 (void) request_type
; /* usable for note_request. */
1751 if (!strcmpstart(url
, "/tor/server/d/"))
1752 conn
->dir_spool_src
= DIR_SPOOL_SERVER_BY_DIGEST
;
1754 conn
->dir_spool_src
= DIR_SPOOL_SERVER_BY_FP
;
1757 write_http_status_line(conn
, 404, msg
);
1759 dlen
= dirserv_estimate_data_size(conn
->fingerprint_stack
,
1761 if (global_write_bucket_low(dlen
, 2)) {
1762 log_info(LD_DIRSERV
,
1763 "Client asked for server descriptors, but we've been "
1764 "writing too many bytes lately. Sending 503 Dir busy.");
1765 write_http_status_line(conn
, 503, "Directory busy, try again later");
1768 write_http_response_header(conn
, -1,
1769 deflated
?"application/octet_stream":"text/plain",
1770 deflated
?"deflate":NULL
, cache_lifetime
);
1772 conn
->zlib_state
= tor_zlib_new(1, ZLIB_METHOD
);
1773 /* Prime the connection with some data. */
1774 connection_dirserv_flushed_some(conn
);
1779 if (options
->HSAuthoritativeDir
&&
1780 (!strcmpstart(url
,"/tor/rendezvous/") ||
1781 !strcmpstart(url
,"/tor/rendezvous1/"))) {
1782 /* rendezvous descriptor fetch */
1785 int versioned
= !strcmpstart(url
,"/tor/rendezvous1/");
1786 const char *query
= url
+strlen("/tor/rendezvous/")+(versioned
?1:0);
1788 switch (rend_cache_lookup_desc(query
, versioned
?-1:0, &descp
, &desc_len
)) {
1790 write_http_response_header(conn
, desc_len
, "application/octet-stream",
1792 note_request("/tor/rendezvous?/", desc_len
);
1793 /* need to send descp separately, because it may include nuls */
1794 connection_write_to_buf(descp
, desc_len
, TO_CONN(conn
));
1796 case 0: /* well-formed but not present */
1797 write_http_status_line(conn
, 404, "Not found");
1799 case -1: /* not well-formed */
1800 write_http_status_line(conn
, 400, "Bad request");
1807 if (!strcmpstart(url
,"/tor/bytes.txt")) {
1808 char *bytes
= directory_dump_request_log();
1809 size_t len
= strlen(bytes
);
1810 write_http_response_header(conn
, len
, "text/plain", NULL
, 0);
1811 connection_write_to_buf(bytes
, len
, TO_CONN(conn
));
1817 if (!strcmp(url
,"/tor/robots.txt")) { /* /robots.txt will have been
1818 rewritten to /tor/robots.txt */
1819 char robots
[] = "User-agent: *\r\nDisallow: /\r\n";
1820 size_t len
= strlen(robots
);
1821 write_http_response_header(conn
, len
, "text/plain", NULL
,
1822 ROBOTS_CACHE_LIFETIME
);
1823 connection_write_to_buf(robots
, len
, TO_CONN(conn
));
1828 if (!strcmp(url
,"/tor/dir-all-weaselhack") &&
1829 (conn
->_base
.addr
== 0x7f000001ul
) &&
1830 authdir_mode(options
)) {
1831 /* XXX until weasel rewrites his scripts XXXX012 */
1832 char *new_directory
=NULL
;
1834 if (dirserv_dump_directory_to_string(&new_directory
,
1835 get_identity_key(), 1)) {
1836 log_warn(LD_BUG
, "Error creating full v1 directory.");
1837 tor_free(new_directory
);
1838 write_http_status_line(conn
, 503, "Directory unavailable");
1842 dlen
= strlen(new_directory
);
1844 write_http_response_header(conn
, dlen
, "text/plain", "identity", 0);
1846 connection_write_to_buf(new_directory
, dlen
, TO_CONN(conn
));
1847 tor_free(new_directory
);
1852 /* we didn't recognize the url */
1853 write_http_status_line(conn
, 404, "Not found");
1858 /** Helper function: called when a dirserver gets a complete HTTP POST
1859 * request. Look for an uploaded server descriptor or rendezvous
1860 * service descriptor. On finding one, process it and write a
1861 * response into conn-\>outbuf. If the request is unrecognized, send a
1862 * 400. Always return 0. */
1864 directory_handle_command_post(dir_connection_t
*conn
, char *headers
,
1865 char *body
, size_t body_len
)
1868 or_options_t
*options
= get_options();
1870 log_debug(LD_DIRSERV
,"Received POST command.");
1872 conn
->_base
.state
= DIR_CONN_STATE_SERVER_WRITING
;
1874 if (!authdir_mode(options
)) {
1875 /* we just provide cached directories; we don't want to
1876 * receive anything. */
1877 write_http_status_line(conn
, 400, "Nonauthoritative directory does not "
1878 "accept posted server descriptors");
1882 if (parse_http_url(headers
, &url
) < 0) {
1883 write_http_status_line(conn
, 400, "Bad request");
1886 log_debug(LD_DIRSERV
,"rewritten url as '%s'.", url
);
1888 if (!strcmp(url
,"/tor/")) { /* server descriptor post */
1890 int r
= dirserv_add_descriptor(body
, &msg
);
1893 dirserv_get_directory(); /* rebuild and write to disk */
1898 log_notice(LD_DIRSERV
,"Rejected router descriptor from %s.",
1899 conn
->_base
.address
);
1900 /* malformed descriptor, or something wrong */
1901 write_http_status_line(conn
, 400, msg
);
1903 case 0: /* accepted but discarded */
1904 case 2: /* accepted */
1905 write_http_status_line(conn
, 200, msg
);
1911 if (options
->HSAuthoritativeDir
&&
1912 !strcmpstart(url
,"/tor/rendezvous/publish")) {
1913 /* rendezvous descriptor post */
1914 if (rend_cache_store(body
, body_len
) < 0) {
1915 // char tmp[1024*2+1];
1916 log_fn(LOG_PROTOCOL_WARN
, LD_DIRSERV
,
1917 "Rejected rend descriptor (length %d) from %s.",
1918 (int)body_len
, conn
->_base
.address
);
1919 write_http_status_line(conn
, 400, "Invalid service descriptor rejected");
1921 write_http_status_line(conn
, 200, "Service descriptor stored");
1926 /* we didn't recognize the url */
1927 write_http_status_line(conn
, 404, "Not found");
1934 /** Called when a dirserver receives data on a directory connection;
1935 * looks for an HTTP request. If the request is complete, remove it
1936 * from the inbuf, try to process it; otherwise, leave it on the
1937 * buffer. Return a 0 on success, or -1 on error.
1940 directory_handle_command(dir_connection_t
*conn
)
1942 char *headers
=NULL
, *body
=NULL
;
1947 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
1949 switch (fetch_from_buf_http(conn
->_base
.inbuf
,
1950 &headers
, MAX_HEADERS_SIZE
,
1951 &body
, &body_len
, MAX_BODY_SIZE
, 0)) {
1952 case -1: /* overflow */
1953 log_warn(LD_DIRSERV
,
1954 "Invalid input from address '%s'. Closing.",
1955 conn
->_base
.address
);
1958 log_debug(LD_DIRSERV
,"command not all here yet.");
1960 /* case 1, fall through */
1963 http_set_address_origin(headers
, TO_CONN(conn
));
1964 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
1966 if (!strncasecmp(headers
,"GET",3))
1967 r
= directory_handle_command_get(conn
, headers
, body
, body_len
);
1968 else if (!strncasecmp(headers
,"POST",4))
1969 r
= directory_handle_command_post(conn
, headers
, body
, body_len
);
1971 log_fn(LOG_PROTOCOL_WARN
, LD_PROTOCOL
,
1972 "Got headers %s with unknown command. Closing.",
1977 tor_free(headers
); tor_free(body
);
1981 /** Write handler for directory connections; called when all data has
1982 * been flushed. Close the connection or wait for a response as
1986 connection_dir_finished_flushing(dir_connection_t
*conn
)
1989 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
1991 switch (conn
->_base
.state
) {
1992 case DIR_CONN_STATE_CLIENT_SENDING
:
1993 log_debug(LD_DIR
,"client finished sending command.");
1994 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_READING
;
1995 connection_stop_writing(TO_CONN(conn
));
1997 case DIR_CONN_STATE_SERVER_WRITING
:
1998 log_debug(LD_DIRSERV
,"Finished writing server response. Closing.");
1999 connection_mark_for_close(TO_CONN(conn
));
2002 log_warn(LD_BUG
,"Bug: called in unexpected state %d.",
2004 tor_fragile_assert();
2010 /** Connected handler for directory connections: begin sending data to the
2013 connection_dir_finished_connecting(dir_connection_t
*conn
)
2016 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
2017 tor_assert(conn
->_base
.state
== DIR_CONN_STATE_CONNECTING
);
2019 log_debug(LD_HTTP
,"Dir connection to router %s:%u established.",
2020 conn
->_base
.address
,conn
->_base
.port
);
2022 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_SENDING
; /* start flushing conn */
2026 /** Called when one or more networkstatus fetches have failed (with uppercase
2027 * fingerprints listed in <b>failed</>). Mark those fingerprints as having
2028 * failed once, unless they failed with status code 503. */
2030 dir_networkstatus_download_failed(smartlist_t
*failed
, int status_code
)
2032 if (status_code
== 503)
2034 SMARTLIST_FOREACH(failed
, const char *, fp
,
2036 char digest
[DIGEST_LEN
];
2037 trusted_dir_server_t
*dir
;
2038 base16_decode(digest
, DIGEST_LEN
, fp
, strlen(fp
));
2039 dir
= router_get_trusteddirserver_by_digest(digest
);
2042 ++dir
->n_networkstatus_failures
;
2046 /** Called when one or more routerdesc fetches have failed (with uppercase
2047 * fingerprints listed in <b>failed</b>). */
2049 dir_routerdesc_download_failed(smartlist_t
*failed
, int status_code
)
2051 char digest
[DIGEST_LEN
];
2052 local_routerstatus_t
*rs
;
2053 time_t now
= time(NULL
);
2054 int server
= server_mode(get_options()) && get_options()->DirPort
;
2055 SMARTLIST_FOREACH(failed
, const char *, cp
,
2057 base16_decode(digest
, DIGEST_LEN
, cp
, strlen(cp
));
2058 rs
= router_get_combined_status_by_digest(digest
);
2059 if (!rs
|| rs
->n_download_failures
>= MAX_ROUTERDESC_DOWNLOAD_FAILURES
)
2061 if (status_code
!= 503 || server
)
2062 ++rs
->n_download_failures
;
2064 switch (rs
->n_download_failures
) {
2065 case 0: rs
->next_attempt_at
= 0; break;
2066 case 1: rs
->next_attempt_at
= 0; break;
2067 case 2: rs
->next_attempt_at
= 0; break;
2068 case 3: rs
->next_attempt_at
= now
+60; break;
2069 case 4: rs
->next_attempt_at
= now
+60; break;
2070 case 5: rs
->next_attempt_at
= now
+60*2; break;
2071 case 6: rs
->next_attempt_at
= now
+60*5; break;
2072 case 7: rs
->next_attempt_at
= now
+60*15; break;
2073 default: rs
->next_attempt_at
= TIME_MAX
; break;
2076 switch (rs
->n_download_failures
) {
2077 case 0: rs
->next_attempt_at
= 0; break;
2078 case 1: rs
->next_attempt_at
= 0; break;
2079 case 2: rs
->next_attempt_at
= now
+60; break;
2080 case 3: rs
->next_attempt_at
= now
+60*5; break;
2081 case 4: rs
->next_attempt_at
= now
+60*10; break;
2082 default: rs
->next_attempt_at
= TIME_MAX
; break;
2085 if (rs
->next_attempt_at
== 0)
2086 log_debug(LD_DIR
, "%s failed %d time(s); I'll try again immediately.",
2087 cp
, (int)rs
->n_download_failures
);
2088 else if (rs
->next_attempt_at
< TIME_MAX
)
2089 log_debug(LD_DIR
, "%s failed %d time(s); I'll try again in %d seconds.",
2090 cp
, (int)rs
->n_download_failures
,
2091 (int)(rs
->next_attempt_at
-now
));
2093 log_debug(LD_DIR
, "%s failed %d time(s); Giving up for a while.",
2094 cp
, (int)rs
->n_download_failures
);
2097 /* update_router_descriptor_downloads(time(NULL)); */
2100 /* Given a directory <b>resource</b> request, containing zero
2101 * or more strings separated by plus signs, followed optionally by ".z", store
2102 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
2103 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
2104 * decode_hex is true, then delete all elements that aren't hex digests, and
2105 * decode the rest. If sort_uniq is true, then sort the list and remove
2109 dir_split_resource_into_fingerprints(const char *resource
,
2110 smartlist_t
*fp_out
, int *compressed_out
,
2111 int decode_hex
, int sort_uniq
)
2113 smartlist_t
*fp_tmp
= smartlist_create();
2115 smartlist_split_string(fp_tmp
, resource
, "+", 0, 0);
2117 *compressed_out
= 0;
2118 if (smartlist_len(fp_tmp
)) {
2119 char *last
= smartlist_get(fp_tmp
,smartlist_len(fp_tmp
)-1);
2120 size_t last_len
= strlen(last
);
2121 if (last_len
> 2 && !strcmp(last
+last_len
-2, ".z")) {
2122 last
[last_len
-2] = '\0';
2124 *compressed_out
= 1;
2129 char *cp
, *d
= NULL
;
2130 for (i
= 0; i
< smartlist_len(fp_tmp
); ++i
) {
2131 cp
= smartlist_get(fp_tmp
, i
);
2132 if (strlen(cp
) != HEX_DIGEST_LEN
) {
2134 "Skipping digest %s with non-standard length.", escaped(cp
));
2135 smartlist_del_keeporder(fp_tmp
, i
--);
2138 d
= tor_malloc_zero(DIGEST_LEN
);
2139 if (base16_decode(d
, DIGEST_LEN
, cp
, HEX_DIGEST_LEN
)<0) {
2140 log_info(LD_DIR
, "Skipping non-decodable digest %s", escaped(cp
));
2141 smartlist_del_keeporder(fp_tmp
, i
--);
2144 smartlist_set(fp_tmp
, i
, d
);
2152 smartlist_t
*fp_tmp2
= smartlist_create();
2155 smartlist_sort_digests(fp_tmp
);
2157 smartlist_sort_strings(fp_tmp
);
2158 if (smartlist_len(fp_tmp
))
2159 smartlist_add(fp_tmp2
, smartlist_get(fp_tmp
, 0));
2160 for (i
= 1; i
< smartlist_len(fp_tmp
); ++i
) {
2161 char *cp
= smartlist_get(fp_tmp
, i
);
2162 char *last
= smartlist_get(fp_tmp2
, smartlist_len(fp_tmp2
)-1);
2164 if ((decode_hex
&& memcmp(cp
, last
, DIGEST_LEN
))
2165 || (!decode_hex
&& strcasecmp(cp
, last
)))
2166 smartlist_add(fp_tmp2
, cp
);
2170 smartlist_free(fp_tmp
);
2173 smartlist_add_all(fp_out
, fp_tmp
);
2174 smartlist_free(fp_tmp
);