r11278@catbus: nickm | 2007-01-23 14:22:27 -0500
[tor.git] / src / or / directory.c
blob1ea605de1aeb4ff3161850894763df52ddb4be75
1 /* Copyright 2001-2004 Roger Dingledine.
2 * Copyright 2004-2006 Roger Dingledine, Nick Mathewson. */
3 /* See LICENSE for licensing information */
4 /* $Id$ */
5 const char directory_c_id[] =
6 "$Id$";
8 #include "or.h"
10 /**
11 * \file directory.c
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.
15 **/
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
25 * do_hup() 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
33 static void
34 directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
35 const char *platform,
36 const char *digest, uint8_t purpose,
37 int private_connection, const char *resource,
38 const char *payload, size_t payload_len);
40 static void
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,
53 int status_code);
54 static void dir_routerdesc_download_failed(smartlist_t *failed,
55 int status_code);
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. */
78 static int
79 purpose_is_private(uint8_t purpose)
81 if (get_options()->AllDirActionsPrivate)
82 return 1;
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)
88 return 0;
89 return 1;
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'.
97 void
98 directory_post_to_dirservers(uint8_t purpose, const char *payload,
99 size_t payload_len)
101 smartlist_t *dirservers;
102 int post_via_tor;
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)
116 continue;
117 if (!post_to_hidserv_only &&
118 !(ds->is_v1_authority || ds->is_v2_authority))
119 continue;
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.
134 void
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 */
146 switch (purpose) {
147 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
148 case DIR_PURPOSE_FETCH_SERVERDESC:
149 type = V2_AUTHORITY;
150 break;
151 case DIR_PURPOSE_FETCH_DIR:
152 case DIR_PURPOSE_FETCH_RUNNING_LIST:
153 type = V1_AUTHORITY;
154 break;
155 case DIR_PURPOSE_FETCH_RENDDESC:
156 type = HIDSERV_AUTHORITY;
157 break;
158 default:
159 log_warn(LD_BUG, "Unexpected purpose %d", (int)purpose);
160 return;
163 if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
164 return;
166 if (directconn) {
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);
172 if (!rs) {
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);
176 if (!rs) {
177 const char *which;
178 if (purpose == DIR_PURPOSE_FETCH_DIR)
179 which = "directory";
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";
186 log_info(LD_DIR,
187 "No router found for %s; falling back to dirserver list",
188 which);
189 rs = router_pick_trusteddirserver(type, 1, 1,
190 retry_if_no_servers);
191 if (!rs)
192 directconn = 0; /* last resort: try routing it via Tor */
196 if (!directconn) {
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);
202 } else {
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. */
212 if (rs)
213 directory_initiate_command_routerstatus(rs, purpose, !directconn,
214 resource, NULL, 0);
215 else {
216 log_notice(LD_DIR,
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
236 * want to fetch.
238 void
239 directory_initiate_command_router(routerinfo_t *router,
240 uint8_t purpose,
241 int private_connection,
242 const char *resource,
243 const char *payload,
244 size_t payload_len)
246 directory_initiate_command(router->address, router->addr, router->dir_port,
247 router->platform,
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
262 * want to fetch.
264 void
265 directory_initiate_command_routerstatus(routerstatus_t *status,
266 uint8_t purpose,
267 int private_connection,
268 const char *resource,
269 const char *payload,
270 size_t payload_len)
272 const char *platform = NULL;
273 routerinfo_t *router;
274 char address_buf[INET_NTOA_BUF_LEN+1];
275 struct in_addr in;
276 const char *address;
277 if ((router = router_get_by_digest(status->identity_digest))) {
278 platform = router->platform;
279 address = router->address;
280 } else {
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
293 * dir_port. */
294 static int
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();
300 if (me &&
301 router_digest_is_me(conn->identity_digest) &&
302 me->addr == conn->_base.addr &&
303 me->dir_port == conn->_base.port)
304 return 1;
306 return 0;
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
311 * possible.
313 void
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();
328 if (me)
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.
348 static void
349 connection_dir_download_networkstatus_failed(dir_connection_t *conn,
350 int status_code)
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. */
356 return;
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,
372 failed, NULL, 0, 0);
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.
384 static void
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)); */
390 (void) conn;
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. */
398 static int
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. */
410 static void
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);
421 tor_assert(address);
422 tor_assert(addr);
423 tor_assert(dir_port);
424 tor_assert(digest);
426 log_debug(LD_DIR, "private %d, want_to_tunnel %d.",
427 private_connection, want_to_tunnel);
429 switch (purpose) {
430 case DIR_PURPOSE_FETCH_DIR:
431 log_debug(LD_DIR,"initiating directory fetch");
432 break;
433 case DIR_PURPOSE_FETCH_RENDDESC:
434 log_debug(LD_DIR,"initiating hidden-service descriptor fetch");
435 break;
436 case DIR_PURPOSE_UPLOAD_DIR:
437 log_debug(LD_OR,"initiating server descriptor upload");
438 break;
439 case DIR_PURPOSE_UPLOAD_RENDDESC:
440 log_debug(LD_REND,"initiating hidden-service descriptor upload");
441 break;
442 case DIR_PURPOSE_FETCH_RUNNING_LIST:
443 log_debug(LD_DIR,"initiating running-routers fetch");
444 break;
445 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
446 log_debug(LD_DIR,"initiating network-status fetch");
447 break;
448 case DIR_PURPOSE_FETCH_SERVERDESC:
449 log_debug(LD_DIR,"initiating server descriptor fetch");
450 break;
451 default:
452 log_err(LD_BUG, "Unrecognized directory connection purpose.");
453 tor_assert(0);
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,
479 dir_port)) {
480 case -1:
481 connection_dir_request_failed(conn); /* retry if we want */
482 connection_free(TO_CONN(conn));
483 return;
484 case 1:
485 /* start flushing conn */
486 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
487 /* fall through */
488 case 0:
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;
502 conn->_base.s =
503 connection_ap_make_bridge(conn->_base.address, conn->_base.port,
504 digest,
505 private_connection ?
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));
511 return;
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));
517 return;
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.
530 static void
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];
538 char *url;
539 char request[8192];
540 const char *httpcommand = NULL;
541 size_t len;
543 tor_assert(conn);
544 tor_assert(conn->_base.type == CONN_TYPE_DIR);
546 tor_free(conn->requested_resource);
547 if (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));
553 } else {
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);
564 if (authenticator) {
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);
574 } else {
575 proxyauthstring[0] = 0;
577 } else {
578 proxystring[0] = 0;
579 proxyauthstring[0] = 0;
582 switch (purpose) {
583 case DIR_PURPOSE_FETCH_DIR:
584 tor_assert(!resource);
585 tor_assert(!payload);
586 log_debug(LD_DIR,
587 "Asking for compressed directory from server running %s",
588 platform?escaped(platform):"<unknown version>");
589 httpcommand = "GET";
590 url = tor_strdup("/tor/dir.z");
591 break;
592 case DIR_PURPOSE_FETCH_RUNNING_LIST:
593 tor_assert(!resource);
594 tor_assert(!payload);
595 httpcommand = "GET";
596 url = tor_strdup("/tor/running-routers");
597 break;
598 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
599 httpcommand = "GET";
600 len = strlen(resource)+32;
601 url = tor_malloc(len);
602 tor_snprintf(url, len, "/tor/status/%s", resource);
603 break;
604 case DIR_PURPOSE_FETCH_SERVERDESC:
605 httpcommand = "GET";
606 len = strlen(resource)+32;
607 url = tor_malloc(len);
608 tor_snprintf(url, len, "/tor/server/%s", resource);
609 break;
610 case DIR_PURPOSE_UPLOAD_DIR:
611 tor_assert(!resource);
612 tor_assert(payload);
613 httpcommand = "POST";
614 url = tor_strdup("/tor/");
615 break;
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));
625 httpcommand = "GET";
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);
632 break;
633 case DIR_PURPOSE_UPLOAD_RENDDESC:
634 tor_assert(!resource);
635 tor_assert(payload);
636 httpcommand = "POST";
637 url = tor_strdup("/tor/rendezvous/publish");
638 break;
639 default:
640 tor_assert(0);
641 return;
644 if (strlen(proxystring) + strlen(url) >= 4096) {
645 log_warn(LD_BUG,
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));
654 tor_free(url);
656 if (!strcmp(httpcommand, "GET") && !payload) {
657 tor_snprintf(request, sizeof(request),
658 " HTTP/1.0\r\nHost: %s%s\r\n\r\n",
659 hoststring,
660 proxyauthstring);
661 } else {
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,
665 hoststring,
666 proxyauthstring);
668 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
670 if (payload) {
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
677 * \verbatim
678 * "\%s [http[s]://]\%s HTTP/1..."
679 * \endverbatim
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.
685 static int
686 parse_http_url(char *headers, char **url)
688 char *s, *start, *tmp;
690 s = (char *)eat_whitespace_no_nl(headers);
691 if (!*s) return -1;
692 s = (char *)find_whitespace(s); /* get past GET/POST */
693 if (!*s) return -1;
694 s = (char *)eat_whitespace_no_nl(s);
695 if (!*s) return -1;
696 start = s; /* this is it, assuming it's valid */
697 s = (char *)find_whitespace(start);
698 if (!*s) return -1;
700 /* tolerate the http[s] proxy style of putting the hostname in the url */
701 if (s-start >= 4 && !strcmpstart(start,"http")) {
702 tmp = start + 4;
703 if (*tmp == 's')
704 tmp++;
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");
709 start = tmp;
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);
718 } else {
719 *url = tor_strndup(start, s-start);
721 return 0;
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. */
728 static char *
729 http_get_header(const char *headers, const char *which)
731 const char *cp = headers;
732 while (cp) {
733 if (!strcmpstart(cp, which)) {
734 char *eos;
735 cp += strlen(which);
736 if ((eos = strchr(cp,'\r')))
737 return tor_strndup(cp, eos-cp);
738 else
739 return tor_strdup(cp);
741 cp = strchr(cp, '\n');
742 if (cp)
743 ++cp;
745 return NULL;
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. */
751 static void
752 http_set_address_origin(const char *headers, connection_t *conn)
754 char *fwd;
756 fwd = http_get_header(headers, "Forwarded-For: ");
757 if (!fwd)
758 fwd = http_get_header(headers, "X-Forwarded-For: ");
759 if (fwd) {
760 tor_free(conn->address);
761 conn->address = tor_strdup(escaped(fwd));
762 tor_free(fwd);
766 /** Parse an HTTP response string <b>headers</b> of the form
767 * \verbatim
768 * "HTTP/1.\%d \%d\%s\r\n...".
769 * \endverbatim
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
780 * into it.
783 parse_http_response(const char *headers, int *code, time_t *date,
784 compress_method_t *compression, char **reason)
786 int n1, n2;
787 char datestr[RFC1123_TIME_LEN+1];
788 smartlist_t *parsed_headers;
789 tor_assert(headers);
790 tor_assert(code);
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));
798 return -1;
800 *code = n2;
802 parsed_headers = smartlist_create();
803 smartlist_split_string(parsed_headers, headers, "\n",
804 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
805 if (reason) {
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);
819 if (date) {
820 *date = 0;
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);
828 break;
831 if (compression) {
832 const char *enc = NULL;
833 SMARTLIST_FOREACH(parsed_headers, const char *, s,
834 if (!strcmpstart(s, "Content-Encoding: ")) {
835 enc = s+18; break;
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;
843 } else {
844 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
845 escaped(enc));
846 *compression = UNKNOWN_METHOD;
849 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
850 smartlist_free(parsed_headers);
852 return 0;
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.
858 static int
859 body_is_plausible(const char *body, size_t len, int purpose)
861 int i;
862 if (len == 0)
863 return 1; /* empty bodies don't need decompression */
864 if (len < 32)
865 return 0;
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"))
871 return 1;
872 for (i=0;i<32;++i) {
873 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
874 return 0;
876 return 1;
877 } else {
878 return 1;
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
887 * again.
889 * The caller will take care of marking the connection for close.
891 static int
892 connection_dir_client_reached_eof(dir_connection_t *conn)
894 char *body;
895 char *headers;
896 char *reason = NULL;
897 size_t body_len=0, orig_len=0;
898 int status_code;
899 time_t date_header=0;
900 int delta;
901 compress_method_t compression;
902 int plausible;
903 int skewed=0;
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,
910 allow_partial)) {
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);
915 return -1;
916 case 0:
917 log_info(LD_HTTP,
918 "'fetch' response not all here, but we're at eof. Closing.");
919 return -1;
920 /* case 1, fall through */
922 orig_len = body_len;
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);
929 return -1;
931 if (!reason) reason = tor_strdup("[no reason given]");
933 log_debug(LD_DIR,
934 "Received response from directory server '%s:%d': %d %s",
935 conn->_base.address, conn->_base.port, status_code,
936 escaped(reason));
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);
941 if (guess) {
942 router_new_address_suggestion(guess);
943 tor_free(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,
957 LD_HTTP,
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);
967 } else {
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,
981 conn->_base.port);
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);
988 return -1;
991 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
992 if (compression != NO_METHOD || !plausible) {
993 char *new_body = NULL;
994 size_t new_len = 0;
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";
1005 else
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";
1013 else
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,
1019 description2,
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. */
1028 if (!new_body &&
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);
1040 return -1;
1042 if (new_body) {
1043 tor_free(body);
1044 body = new_body;
1045 body_len = new_len;
1046 was_compressed = 1;
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,
1058 conn->_base.port);
1059 tor_free(body); tor_free(headers); tor_free(reason);
1060 return -1;
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,
1076 conn->_base.port);
1077 tor_free(body); tor_free(headers); tor_free(reason);
1078 return -1;
1080 if (router_parse_runningrouters(body)<0) {
1081 log_warn(LD_DIR,
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);
1085 return -1;
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;
1094 char *cp;
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) {
1098 log_warn(LD_DIR,
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);
1105 return -1;
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,
1113 which, NULL, 0, 0);
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);
1125 } else {
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.");
1131 cp = body;
1132 while (*cp) {
1133 char *next = strstr(cp, "\nnetwork-status-version");
1134 if (next)
1135 next[1] = '\0';
1136 /* learn from it, and then remove it from 'which' */
1137 if (router_set_networkstatus(cp, time(NULL), source, which)<0)
1138 break;
1139 if (next) {
1140 next[1] = 'n';
1141 cp = next+1;
1143 else
1144 break;
1146 routers_update_all_from_networkstatus(); /*launches router downloads*/
1147 directory_info_has_arrived(time(NULL), 0);
1148 if (which) {
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,
1167 which, NULL, 0, 0);
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);
1180 if (!which) {
1181 connection_dir_download_routerdesc_failed(conn);
1182 } else {
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
1193 * think we have.
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) {
1217 case 200: {
1218 int all_done = 1;
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) {
1233 all_done = 0;
1234 break;
1237 if (all_done)
1238 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1240 break;
1241 case 400:
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));
1248 break;
1249 case 403:
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,
1256 conn->_base.port);
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));
1260 break;
1261 default:
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,
1266 conn->_base.port);
1267 break;
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 "
1275 "(%s))",
1276 (int)body_len, status_code, escaped(reason));
1277 switch (status_code) {
1278 case 200:
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
1282 * cleans it up */
1283 } else {
1284 /* success. notify pending connections about this. */
1285 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1286 rend_client_desc_here(conn->rend_query);
1288 break;
1289 case 404:
1290 /* not there. pending connections will be notified when
1291 * connection_mark_for_close cleans it up. */
1292 break;
1293 case 400:
1294 log_warn(LD_REND,
1295 "http status 400 (%s). Dirserver didn't like our "
1296 "rendezvous query?", escaped(reason));
1297 break;
1298 default:
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,
1302 conn->_base.port);
1303 break;
1307 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
1308 switch (status_code) {
1309 case 200:
1310 log_info(LD_REND,
1311 "Uploading rendezvous descriptor: finished with status "
1312 "200 (%s)", escaped(reason));
1313 break;
1314 case 400:
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);
1318 break;
1319 default:
1320 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1321 "'%s:%d').",
1322 status_code, escaped(reason), conn->_base.address,
1323 conn->_base.port);
1324 break;
1327 tor_free(body); tor_free(headers); tor_free(reason);
1328 return 0;
1331 /** Called when a directory connection reaches EOF */
1333 connection_dir_reached_eof(dir_connection_t *conn)
1335 int retval;
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));
1340 return -1;
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));
1347 return retval;
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)
1362 tor_assert(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
1368 * close).
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));
1375 return -1;
1377 return 0;
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));
1384 return -1;
1387 if (!conn->_base.inbuf_reached_eof)
1388 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1389 return 0;
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>.
1395 static void
1396 write_http_status_line(dir_connection_t *conn, int status,
1397 const char *reason_phrase)
1399 char buf[256];
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.");
1403 return;
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. */
1415 static void
1416 write_http_response_header(dir_connection_t *conn, ssize_t length,
1417 const char *type, const char *encoding,
1418 int cache_lifetime)
1420 char date[RFC1123_TIME_LEN+1];
1421 char tmp[1024];
1422 char *cp;
1423 time_t now = time(NULL);
1425 tor_assert(conn);
1426 tor_assert(type);
1428 format_rfc1123_time(date, now);
1429 cp = tmp;
1430 tor_snprintf(cp, sizeof(tmp),
1431 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n",
1432 date, type);
1433 cp += strlen(tmp);
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);
1438 cp += strlen(cp);
1440 if (encoding) {
1441 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1442 "Content-Encoding: %s\r\n", encoding);
1443 cp += strlen(cp);
1445 if (length >= 0) {
1446 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1447 "Content-Length: %ld\r\n", (long)length);
1448 cp += strlen(cp);
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
1454 * http/1.1 */
1455 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
1456 "Expires: %s\r\n", expbuf);
1457 cp += strlen(cp);
1458 } else {
1459 /* We could say 'Cache-control: no-cache' here if we start doing
1460 * http/1.1 */
1461 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
1462 cp += strlen(cp);
1464 if (sizeof(tmp)-(cp-tmp) > 3)
1465 memcpy(cp, "\r\n", 3);
1466 else
1467 tor_assert(0);
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.
1473 * Else return 0.
1475 static int
1476 already_fetching_directory(int purpose)
1478 int i, n;
1479 connection_t *conn;
1480 connection_t **carray;
1482 get_connection_array(&carray,&n);
1483 for (i=0;i<n;i++) {
1484 conn = carray[i];
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))
1489 return 1;
1491 return 0;
1494 #undef INSTRUMENT_DOWNLOADS
1496 #ifdef INSTRUMENT_DOWNLOADS
1497 /** DOCDOC */
1498 static strmap_t *request_bytes_map = NULL;
1500 /** DOCDOC */
1501 static void
1502 note_request(const char *key, size_t bytes)
1504 uint64_t *n;
1505 if (!request_bytes_map)
1506 request_bytes_map = strmap_new();
1508 n = strmap_get(request_bytes_map, key);
1509 if (!n) {
1510 n = tor_malloc_zero(sizeof(uint64_t));
1511 strmap_set(request_bytes_map, key, n);
1513 *n += bytes;
1516 /** DOCDOC */
1517 char *
1518 directory_dump_request_log(void)
1520 smartlist_t *lines;
1521 char tmp[256];
1522 char *result;
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)) {
1533 const char *key;
1534 void *val;
1535 uint64_t *n;
1536 strmap_iter_get(iter, &key, &val);
1537 n = 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);
1546 return result;
1548 #else
1549 static void
1550 note_request(const char *key, size_t bytes)
1552 (void)key;
1553 (void)bytes;
1556 char *
1557 directory_dump_request_log(void)
1559 return tor_strdup("Not supported.");
1561 #endif
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. */
1568 static int
1569 directory_handle_command_get(dir_connection_t *conn, char *headers,
1570 char *body, size_t body_len)
1572 size_t dlen;
1573 const char *cp;
1574 char *url = NULL;
1575 or_options_t *options = get_options();
1576 /* We ignore the body of a GET request. */
1577 (void)body;
1578 (void)body_len;
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");
1586 return 0;
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();
1594 if (!d) {
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);
1601 tor_free(url);
1602 return 0;
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");
1611 tor_free(url);
1612 return 0;
1615 note_request(url, dlen);
1616 tor_free(url);
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;
1626 if (! deflated)
1627 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
1628 ++d->refcnt;
1630 /* Prime the connection with some data. */
1631 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
1632 connection_dirserv_flushed_some(conn);
1633 return 0;
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);
1645 tor_free(url);
1646 return 0;
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");
1653 tor_free(url);
1654 return 0;
1656 note_request(url, dlen);
1657 tor_free(url);
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));
1663 return 0;
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/");
1673 if (deflated)
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";
1683 else
1684 request_type = "/tor/status/?";
1685 tor_free(url);
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);
1689 return 0;
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);
1699 return 0;
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;
1709 if (! deflated)
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);
1716 return 0;
1719 if (!strcmpstart(url,"/tor/server/")) {
1720 size_t url_len = strlen(url);
1721 int deflated = !strcmp(url+url_len-2, ".z");
1722 int res;
1723 const char *msg;
1724 const char *request_type = NULL;
1725 int cache_lifetime = 0;
1726 if (deflated)
1727 url[url_len-2] = '\0';
1728 conn->fingerprint_stack = smartlist_create();
1729 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
1730 &msg);
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;
1747 } else {
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;
1753 else
1754 conn->dir_spool_src = DIR_SPOOL_SERVER_BY_FP;
1755 tor_free(url);
1756 if (res < 0)
1757 write_http_status_line(conn, 404, msg);
1758 else {
1759 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
1760 1, deflated);
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");
1766 return 0;
1768 write_http_response_header(conn, -1,
1769 deflated?"application/octet_stream":"text/plain",
1770 deflated?"deflate":NULL, cache_lifetime);
1771 if (deflated)
1772 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
1773 /* Prime the connection with some data. */
1774 connection_dirserv_flushed_some(conn);
1776 return 0;
1779 if (options->HSAuthoritativeDir &&
1780 (!strcmpstart(url,"/tor/rendezvous/") ||
1781 !strcmpstart(url,"/tor/rendezvous1/"))) {
1782 /* rendezvous descriptor fetch */
1783 const char *descp;
1784 size_t desc_len;
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)) {
1789 case 1: /* valid */
1790 write_http_response_header(conn, desc_len, "application/octet-stream",
1791 NULL, 0);
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));
1795 break;
1796 case 0: /* well-formed but not present */
1797 write_http_status_line(conn, 404, "Not found");
1798 break;
1799 case -1: /* not well-formed */
1800 write_http_status_line(conn, 400, "Bad request");
1801 break;
1803 tor_free(url);
1804 return 0;
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));
1812 tor_free(bytes);
1813 tor_free(url);
1814 return 0;
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));
1824 tor_free(url);
1825 return 0;
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");
1839 return 0;
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);
1848 tor_free(url);
1849 return 0;
1852 /* we didn't recognize the url */
1853 write_http_status_line(conn, 404, "Not found");
1854 tor_free(url);
1855 return 0;
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. */
1863 static int
1864 directory_handle_command_post(dir_connection_t *conn, char *headers,
1865 char *body, size_t body_len)
1867 char *url = NULL;
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");
1879 return 0;
1882 if (parse_http_url(headers, &url) < 0) {
1883 write_http_status_line(conn, 400, "Bad request");
1884 return 0;
1886 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
1888 if (!strcmp(url,"/tor/")) { /* server descriptor post */
1889 const char *msg;
1890 int r = dirserv_add_descriptor(body, &msg);
1891 tor_assert(msg);
1892 if (r > 0)
1893 dirserv_get_directory(); /* rebuild and write to disk */
1894 switch (r) {
1895 case -2:
1896 case -1:
1897 case 1:
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);
1902 break;
1903 case 0: /* accepted but discarded */
1904 case 2: /* accepted */
1905 write_http_status_line(conn, 200, msg);
1906 break;
1908 goto done;
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");
1920 } else {
1921 write_http_status_line(conn, 200, "Service descriptor stored");
1923 goto done;
1926 /* we didn't recognize the url */
1927 write_http_status_line(conn, 404, "Not found");
1929 done:
1930 tor_free(url);
1931 return 0;
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.
1939 static int
1940 directory_handle_command(dir_connection_t *conn)
1942 char *headers=NULL, *body=NULL;
1943 size_t body_len=0;
1944 int r;
1946 tor_assert(conn);
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);
1956 return -1;
1957 case 0:
1958 log_debug(LD_DIRSERV,"command not all here yet.");
1959 return 0;
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);
1970 else {
1971 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
1972 "Got headers %s with unknown command. Closing.",
1973 escaped(headers));
1974 r = -1;
1977 tor_free(headers); tor_free(body);
1978 return r;
1981 /** Write handler for directory connections; called when all data has
1982 * been flushed. Close the connection or wait for a response as
1983 * appropriate.
1986 connection_dir_finished_flushing(dir_connection_t *conn)
1988 tor_assert(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));
1996 return 0;
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));
2000 return 0;
2001 default:
2002 log_warn(LD_BUG,"Bug: called in unexpected state %d.",
2003 conn->_base.state);
2004 tor_fragile_assert();
2005 return -1;
2007 return 0;
2010 /** Connected handler for directory connections: begin sending data to the
2011 * server */
2013 connection_dir_finished_connecting(dir_connection_t *conn)
2015 tor_assert(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 */
2023 return 0;
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. */
2029 static void
2030 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
2032 if (status_code == 503)
2033 return;
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);
2041 if (dir)
2042 ++dir->n_networkstatus_failures;
2046 /** Called when one or more routerdesc fetches have failed (with uppercase
2047 * fingerprints listed in <b>failed</b>). */
2048 static void
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)
2060 continue;
2061 if (status_code != 503 || server)
2062 ++rs->n_download_failures;
2063 if (server) {
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;
2075 } else {
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));
2092 else
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
2106 * all duplicates.
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();
2114 tor_assert(fp_out);
2115 smartlist_split_string(fp_tmp, resource, "+", 0, 0);
2116 if (compressed_out)
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';
2123 if (compressed_out)
2124 *compressed_out = 1;
2127 if (decode_hex) {
2128 int i;
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) {
2133 log_info(LD_DIR,
2134 "Skipping digest %s with non-standard length.", escaped(cp));
2135 smartlist_del_keeporder(fp_tmp, i--);
2136 goto again;
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--);
2142 goto again;
2144 smartlist_set(fp_tmp, i, d);
2145 d = NULL;
2146 again:
2147 tor_free(cp);
2148 tor_free(d);
2151 if (sort_uniq) {
2152 smartlist_t *fp_tmp2 = smartlist_create();
2153 int i;
2154 if (decode_hex)
2155 smartlist_sort_digests(fp_tmp);
2156 else
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);
2167 else
2168 tor_free(cp);
2170 smartlist_free(fp_tmp);
2171 fp_tmp = fp_tmp2;
2173 smartlist_add_all(fp_out, fp_tmp);
2174 smartlist_free(fp_tmp);
2175 return 0;