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_needs_anonymity(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
,
50 static void note_request(const char *key
, size_t bytes
);
52 /********* START VARIABLES **********/
54 /** How far in the future do we allow a directory server to tell us it is
55 * before deciding that one of us has the wrong time? */
56 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
58 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
60 /** HTTP cache control: how long do we tell proxies they can cache each
61 * kind of document we serve? */
62 #define FULL_DIR_CACHE_LIFETIME (60*60)
63 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
64 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
65 #define ROUTERDESC_CACHE_LIFETIME (30*60)
66 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
67 #define ROBOTS_CACHE_LIFETIME (24*60*60)
69 /********* END VARIABLES ************/
71 /** Return true iff the directory purpose 'purpose' must use an
72 * anonymous connection to a directory. */
74 purpose_needs_anonymity(uint8_t purpose
)
76 if (get_options()->AllDirActionsPrivate
)
78 if (purpose
== DIR_PURPOSE_FETCH_DIR
||
79 purpose
== DIR_PURPOSE_UPLOAD_DIR
||
80 purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
||
81 purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
||
82 purpose
== DIR_PURPOSE_FETCH_SERVERDESC
||
83 purpose
== DIR_PURPOSE_FETCH_EXTRAINFO
)
88 /** Return a newly allocated string describing <b>auth</b>. */
90 authority_type_to_string(authority_type_t auth
)
93 smartlist_t
*lst
= smartlist_create();
94 if (auth
& V1_AUTHORITY
)
95 smartlist_add(lst
, (void*)"V1");
96 if (auth
& V2_AUTHORITY
)
97 smartlist_add(lst
, (void*)"V2");
98 if (auth
& BRIDGE_AUTHORITY
)
99 smartlist_add(lst
, (void*)"Bridge");
100 if (auth
& HIDSERV_AUTHORITY
)
101 smartlist_add(lst
, (void*)"Hidden service");
102 if (smartlist_len(lst
)) {
103 result
= smartlist_join_strings(lst
, ", ", 0, NULL
);
105 result
= tor_strdup("[Not an authority]");
111 /** Return true iff <b>identity_digest</b> is the digest of a router we
112 * believe to support extrainfo downloads. (If <b>is_authority</b> we do
113 * additional checking that's only valid for authorities.) */
115 router_supports_extrainfo(const char *identity_digest
, int is_authority
)
117 routerinfo_t
*ri
= router_get_by_digest(identity_digest
);
118 local_routerstatus_t
*lrs
;
121 if (ri
->caches_extra_info
)
123 if (is_authority
&& ri
->platform
&&
124 tor_version_as_new_as(ri
->platform
, "Tor 0.2.0.0-alpha-dev (r10070)"))
128 lrs
= router_get_combined_status_by_digest(identity_digest
);
129 if (lrs
&& lrs
->status
.version_supports_extrainfo_upload
)
135 /** Start a connection to every suitable directory authority, using
136 * connection purpose 'purpose' and uploading the payload 'payload'
137 * (length 'payload_len'). The purpose should be one of
138 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
140 * <b>type</b> specifies what sort of dir authorities (V1, V2,
141 * HIDSERV, BRIDGE) we should upload to.
143 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
144 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
145 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
146 * to all authorities, and the extra-info document to all authorities that
150 directory_post_to_dirservers(uint8_t purpose
, authority_type_t type
,
152 size_t payload_len
, size_t extrainfo_len
)
155 smartlist_t
*dirservers
= router_get_trusted_dir_servers();
157 tor_assert(dirservers
);
158 /* This tries dirservers which we believe to be down, but ultimately, that's
159 * harmless, and we may as well err on the side of getting things uploaded.
161 SMARTLIST_FOREACH(dirservers
, trusted_dir_server_t
*, ds
,
163 routerstatus_t
*rs
= &(ds
->fake_status
.status
);
164 size_t upload_len
= payload_len
;
166 if ((type
& ds
->type
) == 0)
169 found
= 1; /* at least one authority of this type was listed */
170 if (purpose
== DIR_PURPOSE_UPLOAD_DIR
)
171 ds
->has_accepted_serverdesc
= 0;
173 if (extrainfo_len
&& router_supports_extrainfo(ds
->digest
, 1)) {
174 upload_len
+= extrainfo_len
;
175 log_info(LD_DIR
, "Uploading an extrainfo (length %d)",
176 (int) extrainfo_len
);
178 post_via_tor
= purpose_needs_anonymity(purpose
) ||
179 !fascist_firewall_allows_address_dir(ds
->addr
, ds
->dir_port
);
180 directory_initiate_command_routerstatus(rs
, purpose
, post_via_tor
,
181 NULL
, payload
, upload_len
);
184 char *s
= authority_type_to_string(type
);
185 log_warn(LD_DIR
, "Publishing server descriptor to directory authorities "
186 "of type '%s', but no authorities of that type listed!", s
);
191 /** Start a connection to a random running directory server, using
192 * connection purpose 'purpose' and requesting 'resource'.
193 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
194 * down, mark them up and try again.
197 directory_get_from_dirserver(uint8_t purpose
, const char *resource
,
198 int retry_if_no_servers
)
200 routerstatus_t
*rs
= NULL
;
201 or_options_t
*options
= get_options();
202 int prefer_authority
= server_mode(options
) && options
->DirPort
!= 0;
203 int directconn
= !purpose_needs_anonymity(purpose
);
204 authority_type_t type
;
206 /* FFFF we could break this switch into its own function, and call
207 * it elsewhere in directory.c. -RD */
209 case DIR_PURPOSE_FETCH_EXTRAINFO
:
210 type
= EXTRAINFO_CACHE
| V2_AUTHORITY
;
212 case DIR_PURPOSE_FETCH_NETWORKSTATUS
:
213 case DIR_PURPOSE_FETCH_SERVERDESC
:
216 case DIR_PURPOSE_FETCH_DIR
:
217 case DIR_PURPOSE_FETCH_RUNNING_LIST
:
220 case DIR_PURPOSE_FETCH_RENDDESC
:
221 type
= HIDSERV_AUTHORITY
;
224 log_warn(LD_BUG
, "Unexpected purpose %d", (int)purpose
);
228 if (!options
->FetchServerDescriptors
&& type
!= HIDSERV_AUTHORITY
)
232 if (prefer_authority
) {
233 /* only ask authdirservers, and don't ask myself */
234 rs
= router_pick_trusteddirserver(type
, 1, 1,
235 retry_if_no_servers
);
238 /* anybody with a non-zero dirport will do */
239 rs
= router_pick_directory_server(1, 1, type
,
240 retry_if_no_servers
);
243 if (purpose
== DIR_PURPOSE_FETCH_DIR
)
245 else if (purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
)
246 which
= "status list";
247 else if (purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
)
248 which
= "network status";
249 else // if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
250 which
= "server descriptors";
252 "No router found for %s; falling back to dirserver list",
254 rs
= router_pick_trusteddirserver(type
, 1, 1,
255 retry_if_no_servers
);
257 directconn
= 0; /* last resort: try routing it via Tor */
262 /* Never use fascistfirewall; we're going via Tor. */
263 if (purpose
== DIR_PURPOSE_FETCH_RENDDESC
) {
264 /* only ask hidserv authorities, any of them will do */
265 rs
= router_pick_trusteddirserver(HIDSERV_AUTHORITY
, 0, 0,
266 retry_if_no_servers
);
268 /* anybody with a non-zero dirport will do. Disregard firewalls. */
269 rs
= router_pick_directory_server(1, 0, type
,
270 retry_if_no_servers
);
271 /* If we have any hope of building an indirect conn, we know some router
272 * descriptors. If (rs==NULL), we can't build circuits anyway, so
273 * there's no point in falling back to the authorities in this case. */
278 directory_initiate_command_routerstatus(rs
, purpose
, !directconn
,
282 "While fetching directory info, "
283 "no running dirservers known. Will try again later. "
284 "(purpose %d)", purpose
);
285 if (!purpose_needs_anonymity(purpose
)) {
286 /* remember we tried them all and failed. */
287 directory_all_unreachable(time(NULL
));
292 /** Launch a new connection to the directory server <b>status</b> to upload or
293 * download a server or rendezvous descriptor. <b>purpose</b> determines what
294 * kind of directory connection we're launching, and must be one of
295 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
297 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
298 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
300 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
304 directory_initiate_command_routerstatus(routerstatus_t
*status
,
306 int anonymized_connection
,
307 const char *resource
,
311 routerinfo_t
*router
;
312 char address_buf
[INET_NTOA_BUF_LEN
+1];
315 if ((router
= router_get_by_digest(status
->identity_digest
))) {
316 address
= router
->address
;
318 in
.s_addr
= htonl(status
->addr
);
319 tor_inet_ntoa(&in
, address_buf
, sizeof(address_buf
));
320 address
= address_buf
;
322 directory_initiate_command(address
, status
->addr
,
323 status
->or_port
, status
->dir_port
,
324 status
->version_supports_begindir
,
325 status
->identity_digest
,
326 purpose
, anonymized_connection
, resource
,
327 payload
, payload_len
);
330 /** Return true iff <b>conn</b> is the client side of a directory connection
331 * we launched to ourself in order to determine the reachability of our
334 directory_conn_is_self_reachability_test(dir_connection_t
*conn
)
336 if (conn
->requested_resource
&&
337 !strcmpstart(conn
->requested_resource
,"authority")) {
338 routerinfo_t
*me
= router_get_my_routerinfo();
340 router_digest_is_me(conn
->identity_digest
) &&
341 me
->addr
== conn
->_base
.addr
&&
342 me
->dir_port
== conn
->_base
.port
)
348 /** Called when we are unable to complete the client's request to a directory
349 * server due to a network error: Mark the router as down and try again if
353 connection_dir_request_failed(dir_connection_t
*conn
)
355 if (directory_conn_is_self_reachability_test(conn
)) {
356 routerinfo_t
*me
= router_get_my_routerinfo();
358 control_event_server_status(LOG_WARN
,
359 "REACHABILITY_FAILED DIRADDRESS=%s:%d",
360 me
->address
, me
->dir_port
);
361 return; /* this was a test fetch. don't retry. */
363 router_set_status(conn
->identity_digest
, 0); /* don't try him again */
364 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_DIR
||
365 conn
->_base
.purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
) {
366 log_info(LD_DIR
, "Giving up on directory server at '%s:%d'; retrying",
367 conn
->_base
.address
, conn
->_base
.port
);
368 directory_get_from_dirserver(conn
->_base
.purpose
, NULL
,
369 0 /* don't retry_if_no_servers */);
370 } else if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
) {
371 log_info(LD_DIR
, "Giving up on directory server at '%s'; retrying",
372 conn
->_base
.address
);
373 connection_dir_download_networkstatus_failed(conn
, -1);
374 } else if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_SERVERDESC
||
375 conn
->_base
.purpose
== DIR_PURPOSE_FETCH_EXTRAINFO
) {
376 log_info(LD_DIR
, "Giving up on directory server at '%s'; retrying",
377 conn
->_base
.address
);
378 connection_dir_download_routerdesc_failed(conn
);
382 /** Called when an attempt to download one or more network status
383 * documents on connection <b>conn</b> failed. Decide whether to
384 * retry the fetch now, later, or never.
387 connection_dir_download_networkstatus_failed(dir_connection_t
*conn
,
390 if (!conn
->requested_resource
) {
391 /* We never reached directory_send_command, which means that we never
392 * opened a network connection. Either we're out of sockets, or the
393 * network is down. Either way, retrying would be pointless. */
396 if (!strcmpstart(conn
->requested_resource
, "all")) {
397 /* We're a non-authoritative directory cache; try again. Ignore status
398 * code, since we don't want to keep trying forever in a tight loop
399 * if all the authorities are shutting us out. */
400 smartlist_t
*trusted_dirs
= router_get_trusted_dir_servers();
401 SMARTLIST_FOREACH(trusted_dirs
, trusted_dir_server_t
*, ds
,
402 ++ds
->n_networkstatus_failures
);
403 directory_get_from_dirserver(conn
->_base
.purpose
, "all.z",
404 0 /* don't retry_if_no_servers */);
405 } else if (!strcmpstart(conn
->requested_resource
, "fp/")) {
406 /* We were trying to download by fingerprint; mark them all as having
407 * failed, and possibly retry them later.*/
408 smartlist_t
*failed
= smartlist_create();
409 dir_split_resource_into_fingerprints(conn
->requested_resource
+3,
411 if (smartlist_len(failed
)) {
412 dir_networkstatus_download_failed(failed
, status_code
);
413 SMARTLIST_FOREACH(failed
, char *, cp
, tor_free(cp
));
415 smartlist_free(failed
);
419 /** Called when an attempt to download one or more router descriptors
420 * or extra-info documents on connection <b>conn</b> failed.
423 connection_dir_download_routerdesc_failed(dir_connection_t
*conn
)
425 /* No need to increment the failure count for routerdescs, since
426 * it's not their fault. */
428 /* No need to relaunch descriptor downloads here: we already do it
429 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
430 tor_assert(conn
->_base
.purpose
== DIR_PURPOSE_FETCH_SERVERDESC
||
431 conn
->_base
.purpose
== DIR_PURPOSE_FETCH_EXTRAINFO
);
436 /** Helper for directory_initiate_command_(router|trusted_dir): send the
437 * command to a server whose address is <b>address</b>, whose IP is
438 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
439 * <b>supports_begindir</b>, and whose identity key digest is
442 directory_initiate_command(const char *address
, uint32_t addr
,
443 uint16_t or_port
, uint16_t dir_port
,
444 int supports_begindir
,
445 const char *digest
, uint8_t purpose
,
446 int anonymized_connection
, const char *resource
,
447 const char *payload
, size_t payload_len
)
449 dir_connection_t
*conn
;
450 or_options_t
*options
= get_options();
451 int want_to_tunnel
= options
->TunnelDirConns
&& supports_begindir
&&
452 !anonymized_connection
&& or_port
&&
453 fascist_firewall_allows_address_or(addr
, or_port
);
457 tor_assert(dir_port
);
460 log_debug(LD_DIR
, "anonymized %d, want_to_tunnel %d.",
461 anonymized_connection
, want_to_tunnel
);
464 case DIR_PURPOSE_FETCH_DIR
:
465 log_debug(LD_DIR
,"initiating directory fetch");
467 case DIR_PURPOSE_FETCH_RENDDESC
:
468 log_debug(LD_DIR
,"initiating hidden-service descriptor fetch");
470 case DIR_PURPOSE_UPLOAD_DIR
:
471 log_debug(LD_OR
,"initiating server descriptor upload");
473 case DIR_PURPOSE_UPLOAD_RENDDESC
:
474 log_debug(LD_REND
,"initiating hidden-service descriptor upload");
476 case DIR_PURPOSE_FETCH_RUNNING_LIST
:
477 log_debug(LD_DIR
,"initiating running-routers fetch");
479 case DIR_PURPOSE_FETCH_NETWORKSTATUS
:
480 log_debug(LD_DIR
,"initiating network-status fetch");
482 case DIR_PURPOSE_FETCH_SERVERDESC
:
483 log_debug(LD_DIR
,"initiating server descriptor fetch");
485 case DIR_PURPOSE_FETCH_EXTRAINFO
:
486 log_debug(LD_DIR
,"initiating extra-info fetch");
489 log_err(LD_BUG
, "Unrecognized directory connection purpose.");
493 conn
= TO_DIR_CONN(connection_new(CONN_TYPE_DIR
, AF_INET
));
495 /* set up conn so it's got all the data we need to remember */
496 conn
->_base
.addr
= addr
;
497 conn
->_base
.port
= want_to_tunnel
? or_port
: dir_port
;
498 conn
->_base
.address
= tor_strdup(address
);
499 memcpy(conn
->identity_digest
, digest
, DIGEST_LEN
);
501 conn
->_base
.purpose
= purpose
;
503 /* give it an initial state */
504 conn
->_base
.state
= DIR_CONN_STATE_CONNECTING
;
506 if (!anonymized_connection
&& !want_to_tunnel
) {
507 /* then we want to connect directly */
509 conn
->dirconn_direct
= 1;
510 if (options
->HttpProxy
) {
511 addr
= options
->HttpProxyAddr
;
512 dir_port
= options
->HttpProxyPort
;
515 switch (connection_connect(TO_CONN(conn
), conn
->_base
.address
, addr
,
518 connection_dir_request_failed(conn
); /* retry if we want */
519 connection_free(TO_CONN(conn
));
522 /* start flushing conn */
523 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_SENDING
;
526 /* queue the command on the outbuf */
527 directory_send_command(conn
, purpose
, 1, resource
,
528 payload
, payload_len
);
529 connection_watch_events(TO_CONN(conn
), EV_READ
| EV_WRITE
);
530 /* writable indicates finish, readable indicates broken link,
531 error indicates broken link in windowsland. */
533 } else { /* we want to connect via tor */
534 edge_connection_t
*linked_conn
;
535 /* make an AP connection
536 * populate it and add it at the right state
539 conn
->dirconn_direct
= 0;
541 connection_ap_make_link(conn
->_base
.address
, conn
->_base
.port
,
543 anonymized_connection
?
544 SOCKS_COMMAND_CONNECT
:
545 SOCKS_COMMAND_CONNECT_DIR
);
547 log_warn(LD_NET
,"Making tunnel to dirserver failed.");
548 connection_mark_for_close(TO_CONN(conn
));
551 connection_link_connections(TO_CONN(conn
), TO_CONN(linked_conn
));
553 if (connection_add(TO_CONN(conn
)) < 0) {
554 log_warn(LD_NET
,"Unable to add connection for link to dirserver.");
555 connection_mark_for_close(TO_CONN(conn
));
558 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_SENDING
;
559 /* queue the command on the outbuf */
560 directory_send_command(conn
, purpose
, 0, resource
,
561 payload
, payload_len
);
562 connection_watch_events(TO_CONN(conn
), EV_READ
| EV_WRITE
);
563 connection_start_reading(TO_CONN(linked_conn
));
567 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
568 * are as in directory_initiate_command.
571 directory_send_command(dir_connection_t
*conn
,
572 int purpose
, int direct
, const char *resource
,
573 const char *payload
, size_t payload_len
)
575 char proxystring
[256];
576 char proxyauthstring
[256];
577 char hoststring
[128];
580 const char *httpcommand
= NULL
;
584 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
586 tor_free(conn
->requested_resource
);
588 conn
->requested_resource
= tor_strdup(resource
);
590 /* come up with a string for which Host: we want */
591 if (conn
->_base
.port
== 80) {
592 strlcpy(hoststring
, conn
->_base
.address
, sizeof(hoststring
));
594 tor_snprintf(hoststring
, sizeof(hoststring
),"%s:%d",
595 conn
->_base
.address
, conn
->_base
.port
);
598 /* come up with some proxy lines, if we're using one. */
599 if (direct
&& get_options()->HttpProxy
) {
600 char *base64_authenticator
=NULL
;
601 const char *authenticator
= get_options()->HttpProxyAuthenticator
;
603 tor_snprintf(proxystring
, sizeof(proxystring
),"http://%s", hoststring
);
605 base64_authenticator
= alloc_http_authenticator(authenticator
);
606 if (!base64_authenticator
)
607 log_warn(LD_BUG
, "Encoding http authenticator failed");
609 if (base64_authenticator
) {
610 tor_snprintf(proxyauthstring
, sizeof(proxyauthstring
),
611 "\r\nProxy-Authorization: Basic %s",
612 base64_authenticator
);
613 tor_free(base64_authenticator
);
615 proxyauthstring
[0] = 0;
619 proxyauthstring
[0] = 0;
623 case DIR_PURPOSE_FETCH_DIR
:
624 tor_assert(!resource
);
625 tor_assert(!payload
);
627 url
= tor_strdup("/tor/dir.z");
629 case DIR_PURPOSE_FETCH_RUNNING_LIST
:
630 tor_assert(!resource
);
631 tor_assert(!payload
);
633 url
= tor_strdup("/tor/running-routers");
635 case DIR_PURPOSE_FETCH_NETWORKSTATUS
:
637 len
= strlen(resource
)+32;
638 url
= tor_malloc(len
);
639 tor_snprintf(url
, len
, "/tor/status/%s", resource
);
641 case DIR_PURPOSE_FETCH_SERVERDESC
:
643 len
= strlen(resource
)+32;
644 url
= tor_malloc(len
);
645 tor_snprintf(url
, len
, "/tor/server/%s", resource
);
647 case DIR_PURPOSE_FETCH_EXTRAINFO
:
649 len
= strlen(resource
)+32;
650 url
= tor_malloc(len
);
651 tor_snprintf(url
, len
, "/tor/extra/%s", resource
);
653 case DIR_PURPOSE_UPLOAD_DIR
:
654 tor_assert(!resource
);
656 httpcommand
= "POST";
657 url
= tor_strdup("/tor/");
659 case DIR_PURPOSE_FETCH_RENDDESC
:
660 tor_assert(resource
);
661 tor_assert(!payload
);
663 /* this must be true or we wouldn't be doing the lookup */
664 tor_assert(strlen(resource
) <= REND_SERVICE_ID_LEN
);
665 /* This breaks the function abstraction. */
666 strlcpy(conn
->rend_query
, resource
, sizeof(conn
->rend_query
));
669 /* Request the most recent versioned descriptor. */
670 // (XXXX We were going to switch this to fetch rendezvous1 descriptors,
671 // but that never got testing, and it wasn't a good design.)
672 len
= strlen(resource
)+32;
673 url
= tor_malloc(len
);
674 tor_snprintf(url
, len
, "/tor/rendezvous/%s", resource
);
676 case DIR_PURPOSE_UPLOAD_RENDDESC
:
677 tor_assert(!resource
);
679 httpcommand
= "POST";
680 url
= tor_strdup("/tor/rendezvous/publish");
687 if (strlen(proxystring
) + strlen(url
) >= 4096) {
689 "Squid does not like URLs longer than 4095 bytes, and this "
690 "one is %d bytes long: %s%s",
691 (int)(strlen(proxystring
) + strlen(url
)), proxystring
, url
);
694 tor_snprintf(request
, sizeof(request
), "%s %s", httpcommand
, proxystring
);
695 connection_write_to_buf(request
, strlen(request
), TO_CONN(conn
));
696 connection_write_to_buf(url
, strlen(url
), TO_CONN(conn
));
699 if (!strcmp(httpcommand
, "GET") && !payload
) {
700 tor_snprintf(request
, sizeof(request
),
701 " HTTP/1.0\r\nHost: %s%s\r\n\r\n",
705 tor_snprintf(request
, sizeof(request
),
706 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
707 payload
? (unsigned long)payload_len
: 0,
711 connection_write_to_buf(request
, strlen(request
), TO_CONN(conn
));
714 /* then send the payload afterwards too */
715 connection_write_to_buf(payload
, payload_len
, TO_CONN(conn
));
719 /** Parse an HTTP request string <b>headers</b> of the form
721 * "\%s [http[s]://]\%s HTTP/1..."
723 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
724 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
725 * so it does. Return 0.
726 * Otherwise, return -1.
729 parse_http_url(const char *headers
, char **url
)
731 char *s
, *start
, *tmp
;
733 s
= (char *)eat_whitespace_no_nl(headers
);
735 s
= (char *)find_whitespace(s
); /* get past GET/POST */
737 s
= (char *)eat_whitespace_no_nl(s
);
739 start
= s
; /* this is it, assuming it's valid */
740 s
= (char *)find_whitespace(start
);
743 /* tolerate the http[s] proxy style of putting the hostname in the url */
744 if (s
-start
>= 4 && !strcmpstart(start
,"http")) {
748 if (s
-tmp
>= 3 && !strcmpstart(tmp
,"://")) {
749 tmp
= strchr(tmp
+3, '/');
750 if (tmp
&& tmp
< s
) {
751 log_debug(LD_DIR
,"Skipping over 'http[s]://hostname' string");
757 if (s
-start
< 5 || strcmpstart(start
,"/tor/")) { /* need to rewrite it */
758 *url
= tor_malloc(s
- start
+ 5);
759 strlcpy(*url
,"/tor", s
-start
+5);
760 strlcat((*url
)+4, start
, s
-start
+1);
762 *url
= tor_strndup(start
, s
-start
);
767 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
768 * <b>which</b>. The key should be given with a terminating colon and space;
769 * this function copies everything after, up to but not including the
770 * following \\r\\n. */
772 http_get_header(const char *headers
, const char *which
)
774 const char *cp
= headers
;
776 if (!strcmpstart(cp
, which
)) {
779 if ((eos
= strchr(cp
,'\r')))
780 return tor_strndup(cp
, eos
-cp
);
782 return tor_strdup(cp
);
784 cp
= strchr(cp
, '\n');
791 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
792 * <b>conn</b>-\>address to describe our best guess of the address that
793 * originated this HTTP request. */
795 http_set_address_origin(const char *headers
, connection_t
*conn
)
799 fwd
= http_get_header(headers
, "Forwarded-For: ");
801 fwd
= http_get_header(headers
, "X-Forwarded-For: ");
804 if (!tor_inet_aton(fwd
, &in
) || is_internal_IP(ntohl(in
.s_addr
), 0)) {
805 log_debug(LD_DIR
, "Ignoring unrecognized or internal IP %s",
810 tor_free(conn
->address
);
811 conn
->address
= tor_strdup(fwd
);
816 /** Parse an HTTP response string <b>headers</b> of the form
818 * "HTTP/1.\%d \%d\%s\r\n...".
821 * If it's well-formed, assign the status code to *<b>code</b> and
822 * return 0. Otherwise, return -1.
824 * On success: If <b>date</b> is provided, set *date to the Date
825 * header in the http headers, or 0 if no such header is found. If
826 * <b>compression</b> is provided, set *<b>compression</b> to the
827 * compression method given in the Content-Encoding header, or 0 if no
828 * such header is found, or -1 if the value of the header is not
829 * recognized. If <b>reason</b> is provided, strdup the reason string
833 parse_http_response(const char *headers
, int *code
, time_t *date
,
834 compress_method_t
*compression
, char **reason
)
837 char datestr
[RFC1123_TIME_LEN
+1];
838 smartlist_t
*parsed_headers
;
842 while (TOR_ISSPACE(*headers
)) headers
++; /* tolerate leading whitespace */
844 if (sscanf(headers
, "HTTP/1.%d %d", &n1
, &n2
) < 2 ||
845 (n1
!= 0 && n1
!= 1) ||
846 (n2
< 100 || n2
>= 600)) {
847 log_warn(LD_HTTP
,"Failed to parse header %s",escaped(headers
));
852 parsed_headers
= smartlist_create();
853 smartlist_split_string(parsed_headers
, headers
, "\n",
854 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
856 smartlist_t
*status_line_elements
= smartlist_create();
857 tor_assert(smartlist_len(parsed_headers
));
858 smartlist_split_string(status_line_elements
,
859 smartlist_get(parsed_headers
, 0),
860 " ", SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 3);
861 tor_assert(smartlist_len(status_line_elements
) <= 3);
862 if (smartlist_len(status_line_elements
) == 3) {
863 *reason
= smartlist_get(status_line_elements
, 2);
864 smartlist_set(status_line_elements
, 2, NULL
); /* Prevent free */
866 SMARTLIST_FOREACH(status_line_elements
, char *, cp
, tor_free(cp
));
867 smartlist_free(status_line_elements
);
871 SMARTLIST_FOREACH(parsed_headers
, const char *, s
,
872 if (!strcmpstart(s
, "Date: ")) {
873 strlcpy(datestr
, s
+6, sizeof(datestr
));
874 /* This will do nothing on failure, so we don't need to check
875 the result. We shouldn't warn, since there are many other valid
876 date formats besides the one we use. */
877 parse_rfc1123_time(datestr
, date
);
882 const char *enc
= NULL
;
883 SMARTLIST_FOREACH(parsed_headers
, const char *, s
,
884 if (!strcmpstart(s
, "Content-Encoding: ")) {
887 if (!enc
|| !strcmp(enc
, "identity")) {
888 *compression
= NO_METHOD
;
889 } else if (!strcmp(enc
, "deflate") || !strcmp(enc
, "x-deflate")) {
890 *compression
= ZLIB_METHOD
;
891 } else if (!strcmp(enc
, "gzip") || !strcmp(enc
, "x-gzip")) {
892 *compression
= GZIP_METHOD
;
894 log_info(LD_HTTP
, "Unrecognized content encoding: %s. Trying to deal.",
896 *compression
= UNKNOWN_METHOD
;
899 SMARTLIST_FOREACH(parsed_headers
, char *, s
, tor_free(s
));
900 smartlist_free(parsed_headers
);
905 /** Return true iff <b>body</b> doesn't start with a plausible router or
906 * running-list or directory opening. This is a sign of possible compression.
909 body_is_plausible(const char *body
, size_t len
, int purpose
)
913 return 1; /* empty bodies don't need decompression */
916 if (purpose
!= DIR_PURPOSE_FETCH_RENDDESC
) {
917 if (!strcmpstart(body
,"router") ||
918 !strcmpstart(body
,"signed-directory") ||
919 !strcmpstart(body
,"network-status") ||
920 !strcmpstart(body
,"running-routers"))
923 if (!TOR_ISPRINT(body
[i
]) && !TOR_ISSPACE(body
[i
]))
932 /** We are a client, and we've finished reading the server's
933 * response. Parse and it and act appropriately.
935 * If we're still happy with using this directory server in the future, return
936 * 0. Otherwise return -1; and the caller should consider trying the request
939 * The caller will take care of marking the connection for close.
942 connection_dir_client_reached_eof(dir_connection_t
*conn
)
947 size_t body_len
=0, orig_len
=0;
949 time_t date_header
=0;
951 compress_method_t compression
;
954 int allow_partial
= (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_SERVERDESC
||
955 conn
->_base
.purpose
== DIR_PURPOSE_FETCH_EXTRAINFO
);
956 int was_compressed
=0;
957 time_t now
= time(NULL
);
959 switch (fetch_from_buf_http(conn
->_base
.inbuf
,
960 &headers
, MAX_HEADERS_SIZE
,
961 &body
, &body_len
, MAX_DIR_DL_SIZE
,
963 case -1: /* overflow */
964 log_warn(LD_PROTOCOL
,
965 "'fetch' response too large (server '%s:%d'). Closing.",
966 conn
->_base
.address
, conn
->_base
.port
);
970 "'fetch' response not all here, but we're at eof. Closing.");
972 /* case 1, fall through */
976 if (parse_http_response(headers
, &status_code
, &date_header
,
977 &compression
, &reason
) < 0) {
978 log_warn(LD_HTTP
,"Unparseable headers (server '%s:%d'). Closing.",
979 conn
->_base
.address
, conn
->_base
.port
);
980 tor_free(body
); tor_free(headers
);
983 if (!reason
) reason
= tor_strdup("[no reason given]");
986 "Received response from directory server '%s:%d': %d %s",
987 conn
->_base
.address
, conn
->_base
.port
, status_code
,
990 /* now check if it's got any hints for us about our IP address. */
991 if (conn
->dirconn_direct
) {
992 char *guess
= http_get_header(headers
, X_ADDRESS_HEADER
);
994 router_new_address_suggestion(guess
);
999 if (date_header
> 0) {
1000 /* The date header was written very soon after we sent our request,
1001 * so compute the skew as the difference between sending the request
1002 * and the date header. (We used to check now-date_header, but that's
1003 * inaccurate if we spend a lot of time downloading.)
1005 delta
= conn
->_base
.timestamp_lastwritten
- date_header
;
1006 if (abs(delta
)>ALLOW_DIRECTORY_TIME_SKEW
) {
1007 int trusted
= router_digest_is_trusted_dir(conn
->identity_digest
);
1008 log_fn(trusted
? LOG_WARN
: LOG_INFO
,
1010 "Received directory with skewed time (server '%s:%d'): "
1011 "we are %d minutes %s, or the directory is %d minutes %s.",
1012 conn
->_base
.address
, conn
->_base
.port
,
1013 abs(delta
)/60, delta
>0 ? "ahead" : "behind",
1014 abs(delta
)/60, delta
>0 ? "behind" : "ahead");
1015 skewed
= 1; /* don't check the recommended-versions line */
1016 control_event_general_status(trusted
? LOG_WARN
: LOG_NOTICE
,
1017 "CLOCK_SKEW SKEW=%d SOURCE=DIRSERV:%s:%d",
1018 delta
, conn
->_base
.address
, conn
->_base
.port
);
1020 log_debug(LD_HTTP
, "Time on received directory is within tolerance; "
1021 "we are %d seconds skewed. (That's okay.)", delta
);
1024 (void) skewed
; /* skewed isn't used yet. */
1026 if (status_code
== 503) {
1027 local_routerstatus_t
*rs
;
1028 trusted_dir_server_t
*ds
;
1029 log_info(LD_DIR
,"Received http status code %d (%s) from server "
1030 "'%s:%d'. I'll try again soon.",
1031 status_code
, escaped(reason
), conn
->_base
.address
,
1033 if ((rs
= router_get_combined_status_by_digest(conn
->identity_digest
)))
1034 rs
->last_dir_503_at
= now
;
1035 if ((ds
= router_get_trusteddirserver_by_digest(conn
->identity_digest
)))
1036 ds
->fake_status
.last_dir_503_at
= now
;
1038 tor_free(body
); tor_free(headers
); tor_free(reason
);
1042 plausible
= body_is_plausible(body
, body_len
, conn
->_base
.purpose
);
1043 if (compression
!= NO_METHOD
|| !plausible
) {
1044 char *new_body
= NULL
;
1046 compress_method_t guessed
= detect_compression_method(body
, body_len
);
1047 if (compression
== UNKNOWN_METHOD
|| guessed
!= compression
) {
1048 /* Tell the user if we don't believe what we're told about compression.*/
1049 const char *description1
, *description2
;
1050 if (compression
== ZLIB_METHOD
)
1051 description1
= "as deflated";
1052 else if (compression
== GZIP_METHOD
)
1053 description1
= "as gzipped";
1054 else if (compression
== NO_METHOD
)
1055 description1
= "as uncompressed";
1057 description1
= "with an unknown Content-Encoding";
1058 if (guessed
== ZLIB_METHOD
)
1059 description2
= "deflated";
1060 else if (guessed
== GZIP_METHOD
)
1061 description2
= "gzipped";
1062 else if (!plausible
)
1063 description2
= "confusing binary junk";
1065 description2
= "uncompressed";
1067 log_info(LD_HTTP
, "HTTP body from server '%s:%d' was labeled %s, "
1068 "but it seems to be %s.%s",
1069 conn
->_base
.address
, conn
->_base
.port
, description1
,
1071 (compression
>0 && guessed
>0)?" Trying both.":"");
1073 /* Try declared compression first if we can. */
1074 if (compression
== GZIP_METHOD
|| compression
== ZLIB_METHOD
)
1075 tor_gzip_uncompress(&new_body
, &new_len
, body
, body_len
, compression
,
1076 !allow_partial
, LOG_PROTOCOL_WARN
);
1077 /* Okay, if that didn't work, and we think that it was compressed
1078 * differently, try that. */
1080 (guessed
== GZIP_METHOD
|| guessed
== ZLIB_METHOD
) &&
1081 compression
!= guessed
)
1082 tor_gzip_uncompress(&new_body
, &new_len
, body
, body_len
, guessed
,
1083 !allow_partial
, LOG_PROTOCOL_WARN
);
1084 /* If we're pretty sure that we have a compressed directory, and
1085 * we didn't manage to uncompress it, then warn and bail. */
1086 if (!plausible
&& !new_body
) {
1087 log_fn(LOG_PROTOCOL_WARN
, LD_HTTP
,
1088 "Unable to decompress HTTP body (server '%s:%d').",
1089 conn
->_base
.address
, conn
->_base
.port
);
1090 tor_free(body
); tor_free(headers
); tor_free(reason
);
1101 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_DIR
) {
1102 /* fetch/process the directory to cache it. */
1103 log_info(LD_DIR
,"Received directory (size %d) from server '%s:%d'",
1104 (int)body_len
, conn
->_base
.address
, conn
->_base
.port
);
1105 if (status_code
!= 200) {
1106 log_warn(LD_DIR
,"Received http status code %d (%s) from server "
1107 "'%s:%d' while fetching directory. I'll try again soon.",
1108 status_code
, escaped(reason
), conn
->_base
.address
,
1110 tor_free(body
); tor_free(headers
); tor_free(reason
);
1113 if (router_parse_directory(body
) < 0) {
1114 log_notice(LD_DIR
,"I failed to parse the directory I fetched from "
1115 "'%s:%d'. Ignoring.", conn
->_base
.address
, conn
->_base
.port
);
1117 note_request(was_compressed
?"dl/dir.z":"dl/dir", orig_len
);
1120 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_RUNNING_LIST
) {
1121 /* just update our list of running routers, if this list is new info */
1122 log_info(LD_DIR
,"Received running-routers list (size %d)", (int)body_len
);
1123 if (status_code
!= 200) {
1124 log_warn(LD_DIR
,"Received http status code %d (%s) from server "
1125 "'%s:%d' while fetching running-routers. I'll try again soon.",
1126 status_code
, escaped(reason
), conn
->_base
.address
,
1128 tor_free(body
); tor_free(headers
); tor_free(reason
);
1131 if (router_parse_runningrouters(body
)<0) {
1133 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1134 conn
->_base
.address
, conn
->_base
.port
);
1135 tor_free(body
); tor_free(headers
); tor_free(reason
);
1138 note_request(was_compressed
?"dl/running-routers.z":
1139 "dl/running-routers", orig_len
);
1142 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_NETWORKSTATUS
) {
1143 smartlist_t
*which
= NULL
;
1144 networkstatus_source_t source
;
1146 log_info(LD_DIR
,"Received networkstatus objects (size %d) from server "
1147 "'%s:%d'",(int) body_len
, conn
->_base
.address
, conn
->_base
.port
);
1148 if (status_code
!= 200) {
1149 /* XXXX020 This warning tends to freak out clients who get a 403. */
1151 "Received http status code %d (%s) from server "
1152 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1153 status_code
, escaped(reason
), conn
->_base
.address
,
1154 conn
->_base
.port
, conn
->requested_resource
);
1155 tor_free(body
); tor_free(headers
); tor_free(reason
);
1156 connection_dir_download_networkstatus_failed(conn
, status_code
);
1159 note_request(was_compressed
?"dl/status.z":"dl/status", orig_len
);
1160 if (conn
->requested_resource
&&
1161 !strcmpstart(conn
->requested_resource
,"fp/")) {
1162 source
= NS_FROM_DIR_BY_FP
;
1163 which
= smartlist_create();
1164 dir_split_resource_into_fingerprints(conn
->requested_resource
+3,
1166 } else if (conn
->requested_resource
&&
1167 !strcmpstart(conn
->requested_resource
, "all")) {
1168 source
= NS_FROM_DIR_ALL
;
1169 which
= smartlist_create();
1170 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1171 trusted_dir_server_t
*, ds
,
1173 char *hex
= tor_malloc(HEX_DIGEST_LEN
+1);
1174 base16_encode(hex
, HEX_DIGEST_LEN
+1, ds
->digest
, DIGEST_LEN
);
1175 smartlist_add(which
, hex
);
1178 /* Can we even end up here? -- weasel*/
1179 source
= NS_FROM_DIR_BY_FP
;
1180 log_warn(LD_BUG
, "We received a networkstatus but we didn't ask "
1181 "for it by fp, nor did we ask for all.");
1185 char *next
= strstr(cp
, "\nnetwork-status-version");
1188 /* learn from it, and then remove it from 'which' */
1189 if (router_set_networkstatus(cp
, now
, source
, which
)<0)
1197 routers_update_all_from_networkstatus(now
); /*launches router downloads*/
1198 directory_info_has_arrived(now
, 0);
1200 if (smartlist_len(which
)) {
1201 dir_networkstatus_download_failed(which
, status_code
);
1203 SMARTLIST_FOREACH(which
, char *, s
, tor_free(s
));
1204 smartlist_free(which
);
1208 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_SERVERDESC
||
1209 conn
->_base
.purpose
== DIR_PURPOSE_FETCH_EXTRAINFO
) {
1210 int was_ei
= conn
->_base
.purpose
== DIR_PURPOSE_FETCH_EXTRAINFO
;
1211 smartlist_t
*which
= NULL
;
1212 int n_asked_for
= 0;
1213 log_info(LD_DIR
,"Received %s (size %d) from server '%s:%d'",
1214 was_ei
? "server info" : "extra server info",
1215 (int)body_len
, conn
->_base
.address
, conn
->_base
.port
);
1217 note_request(was_compressed
?"dl/extra.z":"dl/extra", orig_len
);
1219 note_request(was_compressed
?"dl/server.z":"dl/server", orig_len
);
1220 if (conn
->requested_resource
&&
1221 !strcmpstart(conn
->requested_resource
,"d/")) {
1222 which
= smartlist_create();
1223 dir_split_resource_into_fingerprints(conn
->requested_resource
+2,
1225 n_asked_for
= smartlist_len(which
);
1227 if (status_code
!= 200) {
1228 int dir_okay
= status_code
== 404 ||
1229 (status_code
== 400 && !strcmp(reason
, "Servers unavailable."));
1230 /* 404 means that it didn't have them; no big deal.
1231 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1232 /* XXXX020 This warning tends to freak out clients who get a 403. */
1233 log_fn(dir_okay
? LOG_INFO
: LOG_WARN
, LD_DIR
,
1234 "Received http status code %d (%s) from server '%s:%d' "
1235 "while fetching \"/tor/server/%s\". I'll try again soon.",
1236 status_code
, escaped(reason
), conn
->_base
.address
,
1237 conn
->_base
.port
, conn
->requested_resource
);
1239 connection_dir_download_routerdesc_failed(conn
);
1241 dir_routerdesc_download_failed(which
, status_code
, was_ei
);
1242 SMARTLIST_FOREACH(which
, char *, cp
, tor_free(cp
));
1243 smartlist_free(which
);
1245 tor_free(body
); tor_free(headers
); tor_free(reason
);
1246 return dir_okay
? 0 : -1;
1248 /* Learn the routers, assuming we requested by fingerprint or "all".
1249 * Right now, we only use "authority" to fetch ourself, so we don't want
1250 * to risk replacing ourself with a router running at the addr:port we
1253 if (which
|| (conn
->requested_resource
&&
1254 !strcmpstart(conn
->requested_resource
, "all"))) {
1255 /* as we learn from them, we remove them from 'which' */
1257 router_load_extrainfo_from_string(body
, NULL
, SAVED_NOWHERE
, which
);
1259 router_load_routers_from_string(body
, NULL
, SAVED_NOWHERE
, which
);
1260 directory_info_has_arrived(now
, 0);
1263 if (which
) { /* mark remaining ones as failed */
1264 log_info(LD_DIR
, "Received %d/%d routers requested from %s:%d",
1265 n_asked_for
-smartlist_len(which
), n_asked_for
,
1266 conn
->_base
.address
, (int)conn
->_base
.port
);
1267 if (smartlist_len(which
)) {
1268 dir_routerdesc_download_failed(which
, status_code
, was_ei
);
1270 SMARTLIST_FOREACH(which
, char *, cp
, tor_free(cp
));
1271 smartlist_free(which
);
1273 if (directory_conn_is_self_reachability_test(conn
))
1274 router_dirport_found_reachable();
1277 if (conn
->_base
.purpose
== DIR_PURPOSE_UPLOAD_DIR
) {
1278 switch (status_code
) {
1281 trusted_dir_server_t
*ds
=
1282 router_get_trusteddirserver_by_digest(conn
->identity_digest
);
1283 smartlist_t
*servers
;
1284 log_info(LD_GENERAL
,"eof (status 200) after uploading server "
1285 "descriptor: finished.");
1286 control_event_server_status(
1287 LOG_NOTICE
, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1288 conn
->_base
.address
, conn
->_base
.port
);
1290 ds
->has_accepted_serverdesc
= 1;
1291 servers
= router_get_trusted_dir_servers();
1292 SMARTLIST_FOREACH(servers
, trusted_dir_server_t
*, d
, {
1293 if ((d
->type
& (V1_AUTHORITY
|V2_AUTHORITY
)) &&
1294 !d
->has_accepted_serverdesc
) {
1300 control_event_server_status(LOG_NOTICE
, "GOOD_SERVER_DESCRIPTOR");
1304 log_warn(LD_GENERAL
,"http status 400 (%s) response from "
1305 "dirserver '%s:%d'. Please correct.",
1306 escaped(reason
), conn
->_base
.address
, conn
->_base
.port
);
1307 control_event_server_status(LOG_WARN
,
1308 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1309 conn
->_base
.address
, conn
->_base
.port
, escaped(reason
));
1312 log_warn(LD_GENERAL
,
1313 "http status 403 (%s) response from dirserver "
1314 "'%s:%d'. Is your clock skewed? Have you mailed us your key "
1315 "fingerprint? Are you using the right key? Are you using a "
1316 "private IP address? See http://tor.eff.org/doc/"
1317 "tor-doc-server.html",escaped(reason
), conn
->_base
.address
,
1319 control_event_server_status(LOG_WARN
,
1320 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1321 conn
->_base
.address
, conn
->_base
.port
, escaped(reason
));
1324 log_warn(LD_GENERAL
,
1325 "http status %d (%s) reason unexpected while uploading "
1326 "descriptor to server '%s:%d').",
1327 status_code
, escaped(reason
), conn
->_base
.address
,
1331 /* return 0 in all cases, since we don't want to mark any
1332 * dirservers down just because they don't like us. */
1335 if (conn
->_base
.purpose
== DIR_PURPOSE_FETCH_RENDDESC
) {
1336 log_info(LD_REND
,"Received rendezvous descriptor (size %d, status %d "
1338 (int)body_len
, status_code
, escaped(reason
));
1339 switch (status_code
) {
1341 if (rend_cache_store(body
, body_len
, 0) < 0) {
1342 log_warn(LD_REND
,"Failed to store rendezvous descriptor.");
1343 /* alice's ap_stream will notice when connection_mark_for_close
1346 /* success. notify pending connections about this. */
1347 conn
->_base
.purpose
= DIR_PURPOSE_HAS_FETCHED_RENDDESC
;
1348 rend_client_desc_here(conn
->rend_query
);
1352 /* not there. pending connections will be notified when
1353 * connection_mark_for_close cleans it up. */
1357 "http status 400 (%s). Dirserver didn't like our "
1358 "rendezvous query?", escaped(reason
));
1361 log_warn(LD_REND
,"http status %d (%s) response unexpected while "
1362 "fetching hidden service descriptor (server '%s:%d').",
1363 status_code
, escaped(reason
), conn
->_base
.address
,
1369 if (conn
->_base
.purpose
== DIR_PURPOSE_UPLOAD_RENDDESC
) {
1370 switch (status_code
) {
1373 "Uploading rendezvous descriptor: finished with status "
1374 "200 (%s)", escaped(reason
));
1377 log_warn(LD_REND
,"http status 400 (%s) response from dirserver "
1378 "'%s:%d'. Malformed rendezvous descriptor?",
1379 escaped(reason
), conn
->_base
.address
, conn
->_base
.port
);
1382 log_warn(LD_REND
,"http status %d (%s) response unexpected (server "
1384 status_code
, escaped(reason
), conn
->_base
.address
,
1389 tor_free(body
); tor_free(headers
); tor_free(reason
);
1393 /** Called when a directory connection reaches EOF */
1395 connection_dir_reached_eof(dir_connection_t
*conn
)
1398 if (conn
->_base
.state
!= DIR_CONN_STATE_CLIENT_READING
) {
1399 log_info(LD_HTTP
,"conn reached eof, not reading. [state=%d] Closing.",
1401 connection_close_immediate(TO_CONN(conn
)); /* error: give up on flushing */
1402 connection_mark_for_close(TO_CONN(conn
));
1406 retval
= connection_dir_client_reached_eof(conn
);
1407 if (retval
== 0) /* success */
1408 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_FINISHED
;
1409 connection_mark_for_close(TO_CONN(conn
));
1413 /** If any directory object is arriving, and it's over 10MB large, we're
1414 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
1415 * ask for more than 96 router descriptors at a time.)
1417 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
1419 /** Read handler for directory connections. (That's connections <em>to</em>
1420 * directory servers and connections <em>at</em> directory servers.)
1423 connection_dir_process_inbuf(dir_connection_t
*conn
)
1426 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
1428 /* Directory clients write, then read data until they receive EOF;
1429 * directory servers read data until they get an HTTP command, then
1430 * write their response (when it's finished flushing, they mark for
1434 /* If we're on the dirserver side, look for a command. */
1435 if (conn
->_base
.state
== DIR_CONN_STATE_SERVER_COMMAND_WAIT
) {
1436 if (directory_handle_command(conn
) < 0) {
1437 connection_mark_for_close(TO_CONN(conn
));
1443 if (buf_datalen(conn
->_base
.inbuf
) > MAX_DIRECTORY_OBJECT_SIZE
) {
1444 log_warn(LD_HTTP
, "Too much data received from directory connection: "
1445 "denial of service attempt, or you need to upgrade?");
1446 connection_mark_for_close(TO_CONN(conn
));
1450 if (!conn
->_base
.inbuf_reached_eof
)
1451 log_debug(LD_HTTP
,"Got data, not eof. Leaving on inbuf.");
1455 /** Create an http response for the client <b>conn</b> out of
1456 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1459 write_http_status_line(dir_connection_t
*conn
, int status
,
1460 const char *reason_phrase
)
1463 if (tor_snprintf(buf
, sizeof(buf
), "HTTP/1.0 %d %s\r\n\r\n",
1464 status
, reason_phrase
? reason_phrase
: "OK") < 0) {
1465 log_warn(LD_BUG
,"status line too long.");
1468 connection_write_to_buf(buf
, strlen(buf
), TO_CONN(conn
));
1471 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
1472 * with <b>type</b> as the Content-Type.
1474 * If <b>length</b> is nonnegative, it is the Content-Length.
1475 * If <b>encoding</b> is provided, it is the Content-Encoding.
1476 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
1477 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
1479 write_http_response_header(dir_connection_t
*conn
, ssize_t length
,
1480 const char *type
, const char *encoding
,
1483 char date
[RFC1123_TIME_LEN
+1];
1486 time_t now
= time(NULL
);
1491 format_rfc1123_time(date
, now
);
1493 tor_snprintf(cp
, sizeof(tmp
),
1494 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n",
1497 if (!is_internal_IP(conn
->_base
.addr
, 0)) {
1498 /* Don't report the source address for a localhost/private connection. */
1499 tor_snprintf(cp
, sizeof(tmp
)-(cp
-tmp
),
1500 X_ADDRESS_HEADER
"%s\r\n", conn
->_base
.address
);
1504 tor_snprintf(cp
, sizeof(tmp
)-(cp
-tmp
),
1505 "Content-Encoding: %s\r\n", encoding
);
1509 tor_snprintf(cp
, sizeof(tmp
)-(cp
-tmp
),
1510 "Content-Length: %ld\r\n", (long)length
);
1513 if (cache_lifetime
> 0) {
1514 char expbuf
[RFC1123_TIME_LEN
+1];
1515 format_rfc1123_time(expbuf
, now
+ cache_lifetime
);
1516 /* We could say 'Cache-control: max-age=%d' here if we start doing
1518 tor_snprintf(cp
, sizeof(tmp
)-(cp
-tmp
),
1519 "Expires: %s\r\n", expbuf
);
1522 /* We could say 'Cache-control: no-cache' here if we start doing
1524 strlcpy(cp
, "Pragma: no-cache\r\n", sizeof(tmp
)-(cp
-tmp
));
1527 if (sizeof(tmp
)-(cp
-tmp
) > 3)
1528 memcpy(cp
, "\r\n", 3);
1531 connection_write_to_buf(tmp
, strlen(tmp
), TO_CONN(conn
));
1534 /** Helper function: return 1 if there are any dir conns of purpose
1535 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1539 already_fetching_directory(int purpose
)
1541 smartlist_t
*conns
= get_connection_array();
1542 SMARTLIST_FOREACH(conns
, connection_t
*, conn
,
1544 if (conn
->type
== CONN_TYPE_DIR
&&
1545 conn
->purpose
== purpose
&&
1546 !conn
->marked_for_close
&&
1547 !router_digest_is_me(TO_DIR_CONN(conn
)->identity_digest
))
1553 #undef INSTRUMENT_DOWNLOADS
1555 #ifdef INSTRUMENT_DOWNLOADS
1556 /** Map used to keep track of how much data we've up/downloaded in what kind
1557 * of request. Maps from request type to pointer to uint64_t. */
1558 static strmap_t
*request_bytes_map
= NULL
;
1560 /** Called when we just transmitted or received <b>bytes</b> worth of data
1561 * because of a request of type <b>key</b> (an arbitrary identifier): adds
1562 * <b>bytes</b> to the total associated with key. */
1564 note_request(const char *key
, size_t bytes
)
1567 if (!request_bytes_map
)
1568 request_bytes_map
= strmap_new();
1570 n
= strmap_get(request_bytes_map
, key
);
1572 n
= tor_malloc_zero(sizeof(uint64_t));
1573 strmap_set(request_bytes_map
, key
, n
);
1578 /** Return a newly allocated string holding a summary of bytes used per
1581 directory_dump_request_log(void)
1586 strmap_iter_t
*iter
;
1588 if (!request_bytes_map
)
1589 request_bytes_map
= strmap_new();
1591 lines
= smartlist_create();
1593 for (iter
= strmap_iter_init(request_bytes_map
);
1594 !strmap_iter_done(iter
);
1595 iter
= strmap_iter_next(request_bytes_map
, iter
)) {
1599 strmap_iter_get(iter
, &key
, &val
);
1601 tor_snprintf(tmp
, sizeof(tmp
), "%s "U64_FORMAT
"\n",
1602 key
, U64_PRINTF_ARG(*n
));
1603 smartlist_add(lines
, tor_strdup(tmp
));
1605 smartlist_sort_strings(lines
);
1606 result
= smartlist_join_strings(lines
, "", 0, NULL
);
1607 SMARTLIST_FOREACH(lines
, char *, cp
, tor_free(cp
));
1608 smartlist_free(lines
);
1613 note_request(const char *key
, size_t bytes
)
1620 directory_dump_request_log(void)
1622 return tor_strdup("Not supported.");
1626 /** Helper function: called when a dirserver gets a complete HTTP GET
1627 * request. Look for a request for a directory or for a rendezvous
1628 * service descriptor. On finding one, write a response into
1629 * conn-\>outbuf. If the request is unrecognized, send a 400.
1630 * Always return 0. */
1632 directory_handle_command_get(dir_connection_t
*conn
, const char *headers
,
1633 const char *body
, size_t body_len
)
1637 or_options_t
*options
= get_options();
1638 time_t if_modified_since
= 0;
1641 /* We ignore the body of a GET request. */
1645 log_debug(LD_DIRSERV
,"Received GET command.");
1647 conn
->_base
.state
= DIR_CONN_STATE_SERVER_WRITING
;
1649 if (parse_http_url(headers
, &url
) < 0) {
1650 write_http_status_line(conn
, 400, "Bad request");
1653 if ((header
= http_get_header(headers
, "If-Modified-Since: "))) {
1655 if (parse_http_time(header
, &tm
) == 0) {
1656 if_modified_since
= tor_timegm(&tm
);
1658 /* The correct behavior on a malformed If-Modified-Since header is to
1659 * act as if no If-Modified-Since header had been given. */
1662 log_debug(LD_DIRSERV
,"rewritten url as '%s'.", url
);
1664 if (!strcmp(url
,"/tor/") || !strcmp(url
,"/tor/dir.z")) { /* dir fetch */
1665 int deflated
= !strcmp(url
,"/tor/dir.z");
1666 cached_dir_t
*d
= dirserv_get_directory();
1669 log_notice(LD_DIRSERV
,"Client asked for the mirrored directory, but we "
1670 "don't have a good one yet. Sending 503 Dir not available.");
1671 write_http_status_line(conn
, 503, "Directory unavailable");
1672 /* try to get a new one now */
1673 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR
))
1674 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR
, NULL
, 1);
1678 if (d
->published
< if_modified_since
) {
1679 write_http_status_line(conn
, 304, "Not modified");
1684 dlen
= deflated
? d
->dir_z_len
: d
->dir_len
;
1686 if (global_write_bucket_low(TO_CONN(conn
), dlen
, 1)) {
1687 log_info(LD_DIRSERV
,
1688 "Client asked for the mirrored directory, but we've been "
1689 "writing too many bytes lately. Sending 503 Dir busy.");
1690 write_http_status_line(conn
, 503, "Directory busy, try again later");
1695 note_request(url
, dlen
);
1698 log_debug(LD_DIRSERV
,"Dumping %sdirectory to client.",
1699 deflated
?"deflated ":"");
1700 write_http_response_header(conn
, dlen
,
1701 deflated
?"application/octet-stream":"text/plain",
1702 deflated
?"deflate":"identity",
1703 FULL_DIR_CACHE_LIFETIME
);
1704 conn
->cached_dir
= d
;
1705 conn
->cached_dir_offset
= 0;
1707 conn
->zlib_state
= tor_zlib_new(0, ZLIB_METHOD
);
1710 /* Prime the connection with some data. */
1711 conn
->dir_spool_src
= DIR_SPOOL_CACHED_DIR
;
1712 connection_dirserv_flushed_some(conn
);
1716 if (!strcmp(url
,"/tor/running-routers") ||
1717 !strcmp(url
,"/tor/running-routers.z")) { /* running-routers fetch */
1718 int deflated
= !strcmp(url
,"/tor/running-routers.z");
1719 cached_dir_t
*d
= dirserv_get_runningrouters();
1721 write_http_status_line(conn
, 503, "Directory unavailable");
1722 /* try to get a new one now */
1723 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST
))
1724 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST
, NULL
, 1);
1728 if (d
->published
< if_modified_since
) {
1729 write_http_status_line(conn
, 304, "Not modified");
1733 dlen
= deflated
? d
->dir_z_len
: d
->dir_len
;
1735 if (global_write_bucket_low(TO_CONN(conn
), dlen
, 1)) {
1736 log_info(LD_DIRSERV
,
1737 "Client asked for running-routers, but we've been "
1738 "writing too many bytes lately. Sending 503 Dir busy.");
1739 write_http_status_line(conn
, 503, "Directory busy, try again later");
1743 note_request(url
, dlen
);
1745 write_http_response_header(conn
, dlen
,
1746 deflated
?"application/octet-stream":"text/plain",
1747 deflated
?"deflate":"identity",
1748 RUNNINGROUTERS_CACHE_LIFETIME
);
1749 connection_write_to_buf(deflated
? d
->dir_z
: d
->dir
, dlen
, TO_CONN(conn
));
1753 if (!strcmpstart(url
,"/tor/status/")) {
1754 /* v2 network status fetch. */
1755 size_t url_len
= strlen(url
);
1756 int deflated
= !strcmp(url
+url_len
-2, ".z");
1757 smartlist_t
*dir_fps
= smartlist_create();
1758 const char *request_type
= NULL
;
1759 const char *key
= url
+ strlen("/tor/status/");
1761 url
[url_len
-2] = '\0';
1762 dirserv_get_networkstatus_v2_fingerprints(dir_fps
, key
);
1763 if (!strcmpstart(key
, "fp/"))
1764 request_type
= deflated
?"/tor/status/fp.z":"/tor/status/fp";
1765 else if (!strcmpstart(key
, "authority"))
1766 request_type
= deflated
?"/tor/status/authority.z":
1767 "/tor/status/authority";
1768 else if (!strcmpstart(key
, "all"))
1769 request_type
= deflated
?"/tor/status/all.z":"/tor/status/all";
1771 request_type
= "/tor/status/?";
1773 if (!smartlist_len(dir_fps
)) { /* we failed to create/cache cp */
1774 write_http_status_line(conn
, 503, "Network status object unavailable");
1775 smartlist_free(dir_fps
);
1778 if (dirserv_statuses_are_old(dir_fps
, if_modified_since
)) {
1779 write_http_status_line(conn
, 304, "Not modified");
1780 smartlist_free(dir_fps
);
1784 dlen
= dirserv_estimate_data_size(dir_fps
, 0, deflated
);
1785 if (global_write_bucket_low(TO_CONN(conn
), dlen
, 2)) {
1786 log_info(LD_DIRSERV
,
1787 "Client asked for network status lists, but we've been "
1788 "writing too many bytes lately. Sending 503 Dir busy.");
1789 write_http_status_line(conn
, 503, "Directory busy, try again later");
1790 SMARTLIST_FOREACH(dir_fps
, char *, fp
, tor_free(fp
));
1791 smartlist_free(dir_fps
);
1795 // note_request(request_type,dlen);
1796 (void) request_type
;
1797 write_http_response_header(conn
, -1,
1798 deflated
?"application/octet_stream":"text/plain",
1799 deflated
?"deflate":NULL
,
1800 smartlist_len(dir_fps
) == 1 ? NETWORKSTATUS_CACHE_LIFETIME
:0);
1801 conn
->fingerprint_stack
= dir_fps
;
1803 conn
->zlib_state
= tor_zlib_new(0, ZLIB_METHOD
);
1805 /* Prime the connection with some data. */
1806 conn
->dir_spool_src
= DIR_SPOOL_NETWORKSTATUS
;
1807 connection_dirserv_flushed_some(conn
);
1812 if (!strcmpstart(url
,"/tor/server/") ||
1813 !strcmpstart(url
,"/tor/extra/")) {
1814 char *url_mem
= url
;
1815 size_t url_len
= strlen(url
);
1816 int deflated
= !strcmp(url
+url_len
-2, ".z");
1819 const char *request_type
= NULL
;
1820 int cache_lifetime
= 0;
1821 int is_extra
= !strcmpstart(url
,"/tor/extra/");
1823 url
[url_len
-2] = '\0';
1824 url
+= is_extra
? strlen("/tor/extra/") : strlen("/tor/server/");
1825 conn
->fingerprint_stack
= smartlist_create();
1826 res
= dirserv_get_routerdesc_fingerprints(conn
->fingerprint_stack
, url
,
1829 if (!strcmpstart(url
, "fp/")) {
1830 request_type
= deflated
?"/tor/server/fp.z":"/tor/server/fp";
1831 if (smartlist_len(conn
->fingerprint_stack
) == 1)
1832 cache_lifetime
= ROUTERDESC_CACHE_LIFETIME
;
1833 } else if (!strcmpstart(url
, "authority")) {
1834 request_type
= deflated
?"/tor/server/authority.z":
1835 "/tor/server/authority";
1836 cache_lifetime
= ROUTERDESC_CACHE_LIFETIME
;
1837 } else if (!strcmpstart(url
, "all")) {
1838 request_type
= deflated
?"/tor/server/all.z":"/tor/server/all";
1839 cache_lifetime
= FULL_DIR_CACHE_LIFETIME
;
1840 } else if (!strcmpstart(url
, "d/")) {
1841 request_type
= deflated
?"/tor/server/d.z":"/tor/server/d";
1842 if (smartlist_len(conn
->fingerprint_stack
) == 1)
1843 cache_lifetime
= ROUTERDESC_BY_DIGEST_CACHE_LIFETIME
;
1845 request_type
= "/tor/server/?";
1847 (void) request_type
; /* usable for note_request. */
1848 if (!strcmpstart(url
, "d/"))
1849 conn
->dir_spool_src
=
1850 is_extra
? DIR_SPOOL_EXTRA_BY_DIGEST
: DIR_SPOOL_SERVER_BY_DIGEST
;
1852 conn
->dir_spool_src
=
1853 is_extra
? DIR_SPOOL_EXTRA_BY_FP
: DIR_SPOOL_SERVER_BY_FP
;
1856 write_http_status_line(conn
, 404, msg
);
1858 dlen
= dirserv_estimate_data_size(conn
->fingerprint_stack
,
1860 if (global_write_bucket_low(TO_CONN(conn
), dlen
, 2)) {
1861 log_info(LD_DIRSERV
,
1862 "Client asked for server descriptors, but we've been "
1863 "writing too many bytes lately. Sending 503 Dir busy.");
1864 write_http_status_line(conn
, 503, "Directory busy, try again later");
1867 write_http_response_header(conn
, -1,
1868 deflated
?"application/octet_stream":"text/plain",
1869 deflated
?"deflate":NULL
, cache_lifetime
);
1871 conn
->zlib_state
= tor_zlib_new(1, ZLIB_METHOD
);
1872 /* Prime the connection with some data. */
1873 connection_dirserv_flushed_some(conn
);
1878 if (options
->HSAuthoritativeDir
&&
1879 (!strcmpstart(url
,"/tor/rendezvous/") ||
1880 !strcmpstart(url
,"/tor/rendezvous1/"))) {
1881 /* rendezvous descriptor fetch */
1884 int versioned
= !strcmpstart(url
,"/tor/rendezvous1/");
1885 const char *query
= url
+strlen("/tor/rendezvous/")+(versioned
?1:0);
1887 switch (rend_cache_lookup_desc(query
, versioned
?-1:0, &descp
, &desc_len
)) {
1889 write_http_response_header(conn
, desc_len
, "application/octet-stream",
1891 note_request("/tor/rendezvous?/", desc_len
);
1892 /* need to send descp separately, because it may include nuls */
1893 connection_write_to_buf(descp
, desc_len
, TO_CONN(conn
));
1894 /* report successful fetch to statistic */
1895 if (options
->HSAuthorityRecordStats
) {
1896 hs_usage_note_fetch_total(query
, time(NULL
));
1897 hs_usage_note_fetch_successful(query
, time(NULL
));
1900 case 0: /* well-formed but not present */
1901 write_http_status_line(conn
, 404, "Not found");
1902 /* report (unsuccessful) fetch to statistic */
1903 if (options
->HSAuthorityRecordStats
) {
1904 hs_usage_note_fetch_total(query
, time(NULL
));
1907 case -1: /* not well-formed */
1908 write_http_status_line(conn
, 400, "Bad request");
1915 if (!strcmpstart(url
,"/tor/bytes.txt")) {
1916 char *bytes
= directory_dump_request_log();
1917 size_t len
= strlen(bytes
);
1918 write_http_response_header(conn
, len
, "text/plain", NULL
, 0);
1919 connection_write_to_buf(bytes
, len
, TO_CONN(conn
));
1925 if (!strcmp(url
,"/tor/robots.txt")) { /* /robots.txt will have been
1926 rewritten to /tor/robots.txt */
1927 char robots
[] = "User-agent: *\r\nDisallow: /\r\n";
1928 size_t len
= strlen(robots
);
1929 write_http_response_header(conn
, len
, "text/plain", NULL
,
1930 ROBOTS_CACHE_LIFETIME
);
1931 connection_write_to_buf(robots
, len
, TO_CONN(conn
));
1936 if (!strcmp(url
,"/tor/dir-all-weaselhack") &&
1937 (conn
->_base
.addr
== 0x7f000001ul
) &&
1938 authdir_mode_v2(options
) &&
1939 !authdir_mode_bridge(options
)) {
1940 /* until weasel rewrites his scripts at noreply */
1941 char *new_directory
=NULL
;
1943 if (dirserv_dump_directory_to_string(&new_directory
,
1944 get_identity_key(), 1)) {
1945 log_warn(LD_BUG
, "Error creating full v1 directory.");
1946 tor_free(new_directory
);
1947 write_http_status_line(conn
, 503, "Directory unavailable");
1951 dlen
= strlen(new_directory
);
1953 write_http_response_header(conn
, dlen
, "text/plain", "identity", 0);
1955 connection_write_to_buf(new_directory
, dlen
, TO_CONN(conn
));
1956 tor_free(new_directory
);
1961 /* we didn't recognize the url */
1962 write_http_status_line(conn
, 404, "Not found");
1967 /** Helper function: called when a dirserver gets a complete HTTP POST
1968 * request. Look for an uploaded server descriptor or rendezvous
1969 * service descriptor. On finding one, process it and write a
1970 * response into conn-\>outbuf. If the request is unrecognized, send a
1971 * 400. Always return 0. */
1973 directory_handle_command_post(dir_connection_t
*conn
, const char *headers
,
1974 const char *body
, size_t body_len
)
1977 or_options_t
*options
= get_options();
1979 log_debug(LD_DIRSERV
,"Received POST command.");
1981 conn
->_base
.state
= DIR_CONN_STATE_SERVER_WRITING
;
1983 if (!authdir_mode(options
)) {
1984 /* we just provide cached directories; we don't want to
1985 * receive anything. */
1986 write_http_status_line(conn
, 400, "Nonauthoritative directory does not "
1987 "accept posted server descriptors");
1991 if (parse_http_url(headers
, &url
) < 0) {
1992 write_http_status_line(conn
, 400, "Bad request");
1995 log_debug(LD_DIRSERV
,"rewritten url as '%s'.", url
);
1997 if (authdir_mode_handles_descs(options
) &&
1998 !strcmp(url
,"/tor/")) { /* server descriptor post */
1999 const char *msg
= NULL
;
2000 uint8_t purpose
= authdir_mode_bridge(options
) ?
2001 ROUTER_PURPOSE_CONTROLLER
: ROUTER_PURPOSE_GENERAL
;
2002 int r
= dirserv_add_multiple_descriptors(body
, purpose
, &msg
);
2005 dirserv_get_directory(); /* rebuild and write to disk */
2010 log_notice(LD_DIRSERV
,
2011 "Rejected router descriptor or extra-info from %s.",
2012 conn
->_base
.address
);
2013 /* malformed descriptor, or something wrong */
2014 write_http_status_line(conn
, 400, msg
);
2016 case 0: /* accepted but discarded */
2017 case 2: /* accepted */
2018 write_http_status_line(conn
, 200, msg
);
2024 if (options
->HSAuthoritativeDir
&&
2025 !strcmpstart(url
,"/tor/rendezvous/publish")) {
2026 /* rendezvous descriptor post */
2027 if (rend_cache_store(body
, body_len
, 1) < 0) {
2028 // char tmp[1024*2+1];
2029 log_fn(LOG_PROTOCOL_WARN
, LD_DIRSERV
,
2030 "Rejected rend descriptor (length %d) from %s.",
2031 (int)body_len
, conn
->_base
.address
);
2032 write_http_status_line(conn
, 400, "Invalid service descriptor rejected");
2034 write_http_status_line(conn
, 200, "Service descriptor stored");
2039 /* we didn't recognize the url */
2040 write_http_status_line(conn
, 404, "Not found");
2047 /** Called when a dirserver receives data on a directory connection;
2048 * looks for an HTTP request. If the request is complete, remove it
2049 * from the inbuf, try to process it; otherwise, leave it on the
2050 * buffer. Return a 0 on success, or -1 on error.
2053 directory_handle_command(dir_connection_t
*conn
)
2055 char *headers
=NULL
, *body
=NULL
;
2060 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
2062 switch (fetch_from_buf_http(conn
->_base
.inbuf
,
2063 &headers
, MAX_HEADERS_SIZE
,
2064 &body
, &body_len
, MAX_DIR_UL_SIZE
, 0)) {
2065 case -1: /* overflow */
2066 log_warn(LD_DIRSERV
,
2067 "Invalid input from address '%s'. Closing.",
2068 conn
->_base
.address
);
2071 log_debug(LD_DIRSERV
,"command not all here yet.");
2073 /* case 1, fall through */
2076 http_set_address_origin(headers
, TO_CONN(conn
));
2077 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
2079 if (!strncasecmp(headers
,"GET",3))
2080 r
= directory_handle_command_get(conn
, headers
, body
, body_len
);
2081 else if (!strncasecmp(headers
,"POST",4))
2082 r
= directory_handle_command_post(conn
, headers
, body
, body_len
);
2084 log_fn(LOG_PROTOCOL_WARN
, LD_PROTOCOL
,
2085 "Got headers %s with unknown command. Closing.",
2090 tor_free(headers
); tor_free(body
);
2094 /** Write handler for directory connections; called when all data has
2095 * been flushed. Close the connection or wait for a response as
2099 connection_dir_finished_flushing(dir_connection_t
*conn
)
2102 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
2104 switch (conn
->_base
.state
) {
2105 case DIR_CONN_STATE_CLIENT_SENDING
:
2106 log_debug(LD_DIR
,"client finished sending command.");
2107 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_READING
;
2108 connection_stop_writing(TO_CONN(conn
));
2110 case DIR_CONN_STATE_SERVER_WRITING
:
2111 log_debug(LD_DIRSERV
,"Finished writing server response. Closing.");
2112 connection_mark_for_close(TO_CONN(conn
));
2115 log_warn(LD_BUG
,"called in unexpected state %d.",
2117 tor_fragile_assert();
2123 /** Connected handler for directory connections: begin sending data to the
2126 connection_dir_finished_connecting(dir_connection_t
*conn
)
2129 tor_assert(conn
->_base
.type
== CONN_TYPE_DIR
);
2130 tor_assert(conn
->_base
.state
== DIR_CONN_STATE_CONNECTING
);
2132 log_debug(LD_HTTP
,"Dir connection to router %s:%u established.",
2133 conn
->_base
.address
,conn
->_base
.port
);
2135 conn
->_base
.state
= DIR_CONN_STATE_CLIENT_SENDING
; /* start flushing conn */
2139 /** Called when one or more networkstatus fetches have failed (with uppercase
2140 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
2141 * failed once, unless they failed with status code 503. */
2143 dir_networkstatus_download_failed(smartlist_t
*failed
, int status_code
)
2145 if (status_code
== 503)
2147 SMARTLIST_FOREACH(failed
, const char *, fp
,
2149 char digest
[DIGEST_LEN
];
2150 trusted_dir_server_t
*dir
;
2151 base16_decode(digest
, DIGEST_LEN
, fp
, strlen(fp
));
2152 dir
= router_get_trusteddirserver_by_digest(digest
);
2155 ++dir
->n_networkstatus_failures
;
2159 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
2160 * fetches have failed (with uppercase fingerprints listed in
2161 * <b>failed</b>). */
2163 dir_routerdesc_download_failed(smartlist_t
*failed
, int status_code
,
2166 char digest
[DIGEST_LEN
];
2167 time_t now
= time(NULL
);
2168 int server
= server_mode(get_options()) && get_options()->DirPort
;
2169 SMARTLIST_FOREACH(failed
, const char *, cp
,
2171 download_status_t
*dls
= NULL
;
2172 base16_decode(digest
, DIGEST_LEN
, cp
, strlen(cp
));
2173 if (was_extrainfo
) {
2174 signed_descriptor_t
*sd
=
2175 router_get_by_extrainfo_digest(digest
);
2177 dls
= &sd
->ei_dl_status
;
2179 local_routerstatus_t
*rs
=
2180 router_get_combined_status_by_descriptor_digest(digest
);
2182 dls
= &rs
->dl_status
;
2184 if (!dls
|| dls
->n_download_failures
>= MAX_ROUTERDESC_DOWNLOAD_FAILURES
)
2186 if (status_code
!= 503 || server
)
2187 ++dls
->n_download_failures
;
2189 switch (dls
->n_download_failures
) {
2190 case 0: dls
->next_attempt_at
= 0; break;
2191 case 1: dls
->next_attempt_at
= 0; break;
2192 case 2: dls
->next_attempt_at
= 0; break;
2193 case 3: dls
->next_attempt_at
= now
+60; break;
2194 case 4: dls
->next_attempt_at
= now
+60; break;
2195 case 5: dls
->next_attempt_at
= now
+60*2; break;
2196 case 6: dls
->next_attempt_at
= now
+60*5; break;
2197 case 7: dls
->next_attempt_at
= now
+60*15; break;
2198 default: dls
->next_attempt_at
= TIME_MAX
; break;
2201 switch (dls
->n_download_failures
) {
2202 case 0: dls
->next_attempt_at
= 0; break;
2203 case 1: dls
->next_attempt_at
= 0; break;
2204 case 2: dls
->next_attempt_at
= now
+60; break;
2205 case 3: dls
->next_attempt_at
= now
+60*5; break;
2206 case 4: dls
->next_attempt_at
= now
+60*10; break;
2207 default: dls
->next_attempt_at
= TIME_MAX
; break;
2210 if (dls
->next_attempt_at
== 0)
2211 log_debug(LD_DIR
, "%s failed %d time(s); I'll try again immediately.",
2212 cp
, (int)dls
->n_download_failures
);
2213 else if (dls
->next_attempt_at
< TIME_MAX
)
2214 log_debug(LD_DIR
, "%s failed %d time(s); I'll try again in %d seconds.",
2215 cp
, (int)dls
->n_download_failures
,
2216 (int)(dls
->next_attempt_at
-now
));
2218 log_debug(LD_DIR
, "%s failed %d time(s); Giving up for a while.",
2219 cp
, (int)dls
->n_download_failures
);
2222 /* No need to relaunch descriptor downloads here: we already do it
2223 * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */
2226 /** Given a directory <b>resource</b> request, containing zero
2227 * or more strings separated by plus signs, followed optionally by ".z", store
2228 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
2229 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
2230 * decode_hex is true, then delete all elements that aren't hex digests, and
2231 * decode the rest. If sort_uniq is true, then sort the list and remove
2235 dir_split_resource_into_fingerprints(const char *resource
,
2236 smartlist_t
*fp_out
, int *compressed_out
,
2237 int decode_hex
, int sort_uniq
)
2239 smartlist_t
*fp_tmp
= smartlist_create();
2241 smartlist_split_string(fp_tmp
, resource
, "+", 0, 0);
2243 *compressed_out
= 0;
2244 if (smartlist_len(fp_tmp
)) {
2245 char *last
= smartlist_get(fp_tmp
,smartlist_len(fp_tmp
)-1);
2246 size_t last_len
= strlen(last
);
2247 if (last_len
> 2 && !strcmp(last
+last_len
-2, ".z")) {
2248 last
[last_len
-2] = '\0';
2250 *compressed_out
= 1;
2255 char *cp
, *d
= NULL
;
2256 for (i
= 0; i
< smartlist_len(fp_tmp
); ++i
) {
2257 cp
= smartlist_get(fp_tmp
, i
);
2258 if (strlen(cp
) != HEX_DIGEST_LEN
) {
2260 "Skipping digest %s with non-standard length.", escaped(cp
));
2261 smartlist_del_keeporder(fp_tmp
, i
--);
2264 d
= tor_malloc_zero(DIGEST_LEN
);
2265 if (base16_decode(d
, DIGEST_LEN
, cp
, HEX_DIGEST_LEN
)<0) {
2266 log_info(LD_DIR
, "Skipping non-decodable digest %s", escaped(cp
));
2267 smartlist_del_keeporder(fp_tmp
, i
--);
2270 smartlist_set(fp_tmp
, i
, d
);
2278 smartlist_t
*fp_tmp2
= smartlist_create();
2281 smartlist_sort_digests(fp_tmp
);
2283 smartlist_sort_strings(fp_tmp
);
2284 if (smartlist_len(fp_tmp
))
2285 smartlist_add(fp_tmp2
, smartlist_get(fp_tmp
, 0));
2286 for (i
= 1; i
< smartlist_len(fp_tmp
); ++i
) {
2287 char *cp
= smartlist_get(fp_tmp
, i
);
2288 char *last
= smartlist_get(fp_tmp2
, smartlist_len(fp_tmp2
)-1);
2290 if ((decode_hex
&& memcmp(cp
, last
, DIGEST_LEN
))
2291 || (!decode_hex
&& strcasecmp(cp
, last
)))
2292 smartlist_add(fp_tmp2
, cp
);
2296 smartlist_free(fp_tmp
);
2299 smartlist_add_all(fp_out
, fp_tmp
);
2300 smartlist_free(fp_tmp
);