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