Add some "to-be-safe" escaped() wrappers to log statements in rend*.c, though I am...
[tor.git] / src / or / directory.c
blob58c989dea6dbe9862284c89e12b4b59591f452f7
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 static addr_policy_t *dir_policy = NULL;
59 #define ALLOW_DIRECTORY_TIME_SKEW 30*60 /* 30 minutes */
61 /********* END VARIABLES ************/
63 /** Parse get_options()->DirPolicy, and put the processed version in
64 * &dir_policy. Ignore port specifiers.
66 void
67 parse_dir_policy(void)
69 addr_policy_t *n;
70 if (dir_policy) {
71 addr_policy_free(dir_policy);
72 dir_policy = NULL;
74 config_parse_addr_policy(get_options()->DirPolicy, &dir_policy, -1);
75 /* ports aren't used. */
76 for (n=dir_policy; n; n = n->next) {
77 n->prt_min = 1;
78 n->prt_max = 65535;
82 /** Free storage used to hold parsed directory policy */
83 void
84 free_dir_policy(void)
86 addr_policy_free(dir_policy);
87 dir_policy = NULL;
90 /** Return 1 if <b>addr</b> is permitted to connect to our dir port,
91 * based on <b>dir_policy</b>. Else return 0.
93 int
94 dir_policy_permits_address(uint32_t addr)
96 int a;
98 if (!dir_policy) /* 'no dir policy' means 'accept' */
99 return 1;
100 a = router_compare_addr_to_addr_policy(addr, 1, dir_policy);
101 if (a==ADDR_POLICY_REJECTED)
102 return 0;
103 else if (a==ADDR_POLICY_ACCEPTED)
104 return 1;
105 log_warn(LD_BUG, "Bug: got unexpected 'maybe' answer from dir policy");
106 return 0;
109 /** Return true iff the directory purpose 'purpose' must use an
110 * anonymous connection to a directory. */
111 static int
112 purpose_is_private(uint8_t purpose)
114 if (get_options()->AllDirActionsPrivate)
115 return 1;
116 if (purpose == DIR_PURPOSE_FETCH_DIR ||
117 purpose == DIR_PURPOSE_UPLOAD_DIR ||
118 purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
119 purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
120 purpose == DIR_PURPOSE_FETCH_SERVERDESC)
121 return 0;
122 return 1;
125 /** Start a connection to every known directory server, using
126 * connection purpose 'purpose' and uploading the payload 'payload'
127 * (length 'payload_len'). The purpose should be one of
128 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
130 void
131 directory_post_to_dirservers(uint8_t purpose, const char *payload,
132 size_t payload_len)
134 smartlist_t *dirservers;
135 int post_via_tor;
136 int post_to_v1_only;
138 router_get_trusted_dir_servers(&dirservers);
139 tor_assert(dirservers);
140 /* Only old dirservers handle rendezvous descriptor publishing. */
141 post_to_v1_only = (purpose == DIR_PURPOSE_UPLOAD_RENDDESC);
142 /* This tries dirservers which we believe to be down, but ultimately, that's
143 * harmless, and we may as well err on the side of getting things uploaded.
145 SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
147 routerstatus_t *rs = &(ds->fake_status);
148 if (post_to_v1_only && !ds->is_v1_authority)
149 continue;
150 post_via_tor = purpose_is_private(purpose) ||
151 !fascist_firewall_allows_address_dir(ds->addr, ds->dir_port);
152 directory_initiate_command_routerstatus(rs, purpose, post_via_tor,
153 NULL, payload, payload_len);
157 /** Start a connection to a random running directory server, using
158 * connection purpose 'purpose' and requesting 'resource'.
159 * If <b>retry_if_no_servers</b>, then if all the possible servers seem
160 * down, mark them up and try again.
162 void
163 directory_get_from_dirserver(uint8_t purpose, const char *resource,
164 int retry_if_no_servers)
166 routerstatus_t *rs = NULL;
167 or_options_t *options = get_options();
168 int prefer_authority = server_mode(options) && options->DirPort != 0;
169 int directconn = !purpose_is_private(purpose);
171 int need_v1_support = purpose == DIR_PURPOSE_FETCH_DIR ||
172 purpose == DIR_PURPOSE_FETCH_RUNNING_LIST;
173 int need_v2_support = purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
174 purpose == DIR_PURPOSE_FETCH_SERVERDESC;
176 if (!options->FetchServerDescriptors &&
177 (need_v1_support || need_v2_support))
178 return;
180 if (directconn) {
181 if (prefer_authority) {
182 /* only ask authdirservers, and don't ask myself */
183 rs = router_pick_trusteddirserver(need_v1_support, 1, 1,
184 retry_if_no_servers);
186 if (!rs) {
187 /* anybody with a non-zero dirport will do */
188 rs = router_pick_directory_server(1, 1, need_v2_support,
189 retry_if_no_servers);
190 if (!rs) {
191 const char *which;
192 if (purpose == DIR_PURPOSE_FETCH_DIR)
193 which = "directory";
194 else if (purpose == DIR_PURPOSE_FETCH_RUNNING_LIST)
195 which = "status list";
196 else if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
197 which = "network status";
198 else // if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
199 which = "server descriptors";
200 log_info(LD_DIR,
201 "No router found for %s; falling back to dirserver list",
202 which);
203 rs = router_pick_trusteddirserver(1, 1, 1,
204 retry_if_no_servers);
205 if (!rs)
206 directconn = 0; /* last resort: try routing it via Tor */
210 if (!directconn) {
211 /* Never use fascistfirewall; we're going via Tor. */
212 if (purpose == DIR_PURPOSE_FETCH_RENDDESC) {
213 /* only ask authdirservers, any of them will do */
214 rs = router_pick_trusteddirserver(0, 0, 0, retry_if_no_servers);
215 } else {
216 /* anybody with a non-zero dirport will do. Disregard firewalls. */
217 rs = router_pick_directory_server(1, 0, need_v2_support,
218 retry_if_no_servers);
219 /* If we have any hope of building an indirect conn, we know some router
220 * descriptors. If (rs==NULL), we can't build circuits anyway, so
221 * there's no point in falling back to the authorities in this case. */
225 if (rs)
226 directory_initiate_command_routerstatus(rs, purpose, !directconn,
227 resource, NULL, 0);
228 else {
229 log_notice(LD_DIR,
230 "No running dirservers known. Will try again later. "
231 "(purpose %d)", purpose);
232 if (!purpose_is_private(purpose)) {
233 /* remember we tried them all and failed. */
234 directory_all_unreachable(time(NULL));
239 /** Launch a new connection to the directory server <b>router</b> to upload or
240 * download a service or rendezvous descriptor. <b>purpose</b> determines what
241 * kind of directory connection we're launching, and must be one of
242 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
244 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
245 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
247 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
248 * want to fetch.
250 void
251 directory_initiate_command_router(routerinfo_t *router,
252 uint8_t purpose,
253 int private_connection,
254 const char *resource,
255 const char *payload,
256 size_t payload_len)
258 directory_initiate_command(router->address, router->addr, router->dir_port,
259 router->platform,
260 router->cache_info.identity_digest,
261 purpose, private_connection, resource,
262 payload, payload_len);
265 /** Launch a new connection to the directory server <b>status</b> to upload or
266 * download a service or rendezvous descriptor. <b>purpose</b> determines what
267 * kind of directory connection we're launching, and must be one of
268 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
270 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
271 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
273 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
274 * want to fetch.
276 void
277 directory_initiate_command_routerstatus(routerstatus_t *status,
278 uint8_t purpose,
279 int private_connection,
280 const char *resource,
281 const char *payload,
282 size_t payload_len)
284 const char *platform = NULL;
285 routerinfo_t *router;
286 char address_buf[INET_NTOA_BUF_LEN];
287 struct in_addr in;
288 const char *address;
289 if ((router = router_get_by_digest(status->identity_digest))) {
290 platform = router->platform;
291 address = router->address;
292 } else {
293 in.s_addr = htonl(status->addr);
294 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
295 address = address_buf;
297 directory_initiate_command(address, status->addr, status->dir_port,
298 platform, status->identity_digest,
299 purpose, private_connection, resource,
300 payload, payload_len);
303 /** Called when we are unable to complete the client's request to a
304 * directory server: Mark the router as down and try again if possible.
306 void
307 connection_dir_request_failed(connection_t *conn)
309 if (router_digest_is_me(conn->identity_digest))
310 return; /* this was a test fetch. don't retry. */
311 router_mark_as_down(conn->identity_digest); /* don't try him again */
312 if (conn->purpose == DIR_PURPOSE_FETCH_DIR ||
313 conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
314 log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
315 conn->address, conn->port);
316 directory_get_from_dirserver(conn->purpose, NULL,
317 0 /* don't retry_if_no_servers */);
318 } else if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
319 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
320 conn->address);
321 connection_dir_download_networkstatus_failed(conn);
322 } else if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
323 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
324 conn->address);
325 connection_dir_download_routerdesc_failed(conn);
329 /** Called when an attempt to download one or more network status
330 * documents on connection <b>conn</b> failed. Decide whether to
331 * retry the fetch now, later, or never.
333 static void
334 connection_dir_download_networkstatus_failed(connection_t *conn)
336 if (!conn->requested_resource) {
337 /* We never reached directory_send_command, which means that we never
338 * opened a network connection. Either we're out of sockets, or the
339 * network is down. Either way, retrying would be pointless. */
340 return;
342 if (!strcmpstart(conn->requested_resource, "all")) {
343 /* We're a non-authoritative directory cache; try again. */
344 directory_get_from_dirserver(conn->purpose, "all.z",
345 0 /* don't retry_if_no_servers */);
346 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
347 /* We were trying to download by fingerprint; mark them all as having
348 * failed, and possibly retry them later.*/
349 smartlist_t *failed = smartlist_create();
350 dir_split_resource_into_fingerprints(conn->requested_resource+3,
351 failed, NULL, 0);
352 if (smartlist_len(failed)) {
353 dir_networkstatus_download_failed(failed);
354 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
356 smartlist_free(failed);
360 /** Called when an attempt to download one or more router descriptors
361 * on connection <b>conn</b> failed.
363 static void
364 connection_dir_download_routerdesc_failed(connection_t *conn)
366 /* Try again. No need to increment the failure count for routerdescs, since
367 * it's not their fault.*/
368 /* update_router_descriptor_downloads(time(NULL)); */
371 /** Helper for directory_initiate_command_(router|trusted_dir): send the
372 * command to a server whose address is <b>address</b>, whose IP is
373 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version is
374 * <b>platform</b>, and whose identity key digest is <b>digest</b>. The
375 * <b>platform</b> argument is optional; the others are required. */
376 static void
377 directory_initiate_command(const char *address, uint32_t addr,
378 uint16_t dir_port, const char *platform,
379 const char *digest, uint8_t purpose,
380 int private_connection, const char *resource,
381 const char *payload, size_t payload_len)
383 connection_t *conn;
385 tor_assert(address);
386 tor_assert(addr);
387 tor_assert(dir_port);
388 tor_assert(digest);
390 switch (purpose) {
391 case DIR_PURPOSE_FETCH_DIR:
392 log_debug(LD_DIR,"initiating directory fetch");
393 break;
394 case DIR_PURPOSE_FETCH_RENDDESC:
395 log_debug(LD_DIR,"initiating hidden-service descriptor fetch");
396 break;
397 case DIR_PURPOSE_UPLOAD_DIR:
398 log_debug(LD_OR,"initiating server descriptor upload");
399 break;
400 case DIR_PURPOSE_UPLOAD_RENDDESC:
401 log_debug(LD_REND,"initiating hidden-service descriptor upload");
402 break;
403 case DIR_PURPOSE_FETCH_RUNNING_LIST:
404 log_debug(LD_DIR,"initiating running-routers fetch");
405 break;
406 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
407 log_debug(LD_DIR,"initiating network-status fetch");
408 break;
409 case DIR_PURPOSE_FETCH_SERVERDESC:
410 log_debug(LD_DIR,"initiating server descriptor fetch");
411 break;
412 default:
413 log_err(LD_BUG, "Unrecognized directory connection purpose.");
414 tor_assert(0);
417 conn = connection_new(CONN_TYPE_DIR);
419 /* set up conn so it's got all the data we need to remember */
420 conn->addr = addr;
421 conn->port = dir_port;
422 conn->address = tor_strdup(address);
423 memcpy(conn->identity_digest, digest, DIGEST_LEN);
425 conn->purpose = purpose;
427 /* give it an initial state */
428 conn->state = DIR_CONN_STATE_CONNECTING;
430 if (!private_connection) {
431 /* then we want to connect directly */
433 if (get_options()->HttpProxy) {
434 addr = get_options()->HttpProxyAddr;
435 dir_port = get_options()->HttpProxyPort;
438 switch (connection_connect(conn, conn->address, addr, dir_port)) {
439 case -1:
440 connection_dir_request_failed(conn); /* retry if we want */
441 connection_free(conn);
442 return;
443 case 1:
444 conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
445 /* fall through */
446 case 0:
447 /* queue the command on the outbuf */
448 directory_send_command(conn, platform, purpose, resource,
449 payload, payload_len);
450 connection_watch_events(conn, EV_READ | EV_WRITE);
451 /* writable indicates finish, readable indicates broken link,
452 error indicates broken link in windowsland. */
454 } else { /* we want to connect via tor */
455 /* make an AP connection
456 * populate it and add it at the right state
457 * socketpair and hook up both sides
459 conn->s = connection_ap_make_bridge(conn->address, conn->port);
460 if (conn->s < 0) {
461 log_warn(LD_NET,"Making AP bridge to dirserver failed.");
462 connection_mark_for_close(conn);
463 return;
466 if (connection_add(conn) < 0) {
467 log_warn(LD_NET,"Unable to add AP bridge to dirserver.");
468 connection_mark_for_close(conn);
469 return;
471 conn->state = DIR_CONN_STATE_CLIENT_SENDING;
472 /* queue the command on the outbuf */
473 directory_send_command(conn, platform, purpose, resource,
474 payload, payload_len);
475 connection_watch_events(conn, EV_READ | EV_WRITE);
479 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
480 * are as in directory_initiate_command.
482 static void
483 directory_send_command(connection_t *conn, const char *platform,
484 int purpose, const char *resource,
485 const char *payload, size_t payload_len)
487 char proxystring[256];
488 char proxyauthstring[256];
489 char hoststring[128];
490 char *url;
491 char request[8192];
492 const char *httpcommand = NULL;
493 size_t len;
495 tor_assert(conn);
496 tor_assert(conn->type == CONN_TYPE_DIR);
498 tor_free(conn->requested_resource);
499 if (resource)
500 conn->requested_resource = tor_strdup(resource);
502 /* come up with a string for which Host: we want */
503 if (conn->port == 80) {
504 strlcpy(hoststring, conn->address, sizeof(hoststring));
505 } else {
506 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
507 conn->address, conn->port);
510 /* come up with some proxy lines, if we're using one. */
511 if (get_options()->HttpProxy) {
512 char *base64_authenticator=NULL;
513 const char *authenticator = get_options()->HttpProxyAuthenticator;
515 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
516 if (authenticator) {
517 base64_authenticator = alloc_http_authenticator(authenticator);
518 if (!base64_authenticator)
519 log_warn(LD_BUG, "Encoding http authenticator failed");
521 if (base64_authenticator) {
522 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
523 "\r\nProxy-Authorization: Basic %s",
524 base64_authenticator);
525 tor_free(base64_authenticator);
526 } else {
527 proxyauthstring[0] = 0;
529 } else {
530 proxystring[0] = 0;
531 proxyauthstring[0] = 0;
534 switch (purpose) {
535 case DIR_PURPOSE_FETCH_DIR:
536 tor_assert(!resource);
537 tor_assert(!payload);
538 log_debug(LD_DIR,
539 "Asking for compressed directory from server running %s",
540 platform?escaped(platform):"<unknown version>");
541 httpcommand = "GET";
542 url = tor_strdup("/tor/dir.z");
543 break;
544 case DIR_PURPOSE_FETCH_RUNNING_LIST:
545 tor_assert(!resource);
546 tor_assert(!payload);
547 httpcommand = "GET";
548 url = tor_strdup("/tor/running-routers");
549 break;
550 case DIR_PURPOSE_FETCH_NETWORKSTATUS:
551 httpcommand = "GET";
552 len = strlen(resource)+32;
553 url = tor_malloc(len);
554 tor_snprintf(url, len, "/tor/status/%s", resource);
555 break;
556 case DIR_PURPOSE_FETCH_SERVERDESC:
557 httpcommand = "GET";
558 len = strlen(resource)+32;
559 url = tor_malloc(len);
560 tor_snprintf(url, len, "/tor/server/%s", resource);
561 break;
562 case DIR_PURPOSE_UPLOAD_DIR:
563 tor_assert(!resource);
564 tor_assert(payload);
565 httpcommand = "POST";
566 url = tor_strdup("/tor/");
567 break;
568 case DIR_PURPOSE_FETCH_RENDDESC:
569 tor_assert(resource);
570 tor_assert(!payload);
572 /* this must be true or we wouldn't be doing the lookup */
573 tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN);
574 /* This breaks the function abstraction. */
575 strlcpy(conn->rend_query, resource, sizeof(conn->rend_query));
577 httpcommand = "GET";
578 /* Request the most recent versioned descriptor. */
579 // XXXX011
580 //tor_snprintf(url, sizeof(url), "/tor/rendezvous1/%s", resource);
581 len = strlen(resource)+32;
582 url = tor_malloc(len);
583 tor_snprintf(url, len, "/tor/rendezvous/%s", resource);
584 break;
585 case DIR_PURPOSE_UPLOAD_RENDDESC:
586 tor_assert(!resource);
587 tor_assert(payload);
588 httpcommand = "POST";
589 url = tor_strdup("/tor/rendezvous/publish");
590 break;
591 default:
592 tor_assert(0);
593 return;
596 if (strlen(proxystring) + strlen(url) >= 4096) {
597 log_warn(LD_BUG,
598 "Bug: squid does not like URLs longer than 4095 bytes, this "
599 "one is %d bytes long: %s%s",
600 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
603 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
604 connection_write_to_buf(request, strlen(request), conn);
605 connection_write_to_buf(url, strlen(url), conn);
606 tor_free(url);
608 if (!strcmp(httpcommand, "GET") && !payload) {
609 tor_snprintf(request, sizeof(request),
610 " HTTP/1.0\r\nHost: %s%s\r\n\r\n",
611 hoststring,
612 proxyauthstring);
613 } else {
614 tor_snprintf(request, sizeof(request),
615 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s\r\n\r\n",
616 payload ? (unsigned long)payload_len : 0,
617 hoststring,
618 proxyauthstring);
620 connection_write_to_buf(request, strlen(request), conn);
622 if (payload) {
623 /* then send the payload afterwards too */
624 connection_write_to_buf(payload, payload_len, conn);
628 /** Parse an HTTP request string <b>headers</b> of the form
629 * \verbatim
630 * "\%s [http[s]://]\%s HTTP/1..."
631 * \endverbatim
632 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
633 * null-terminate it. If the url doesn't start with "/tor/", rewrite it
634 * so it does. Return 0.
635 * Otherwise, return -1.
637 static int
638 parse_http_url(char *headers, char **url)
640 char *s, *start, *tmp;
642 s = (char *)eat_whitespace_no_nl(headers);
643 if (!*s) return -1;
644 s = (char *)find_whitespace(s); /* get past GET/POST */
645 if (!*s) return -1;
646 s = (char *)eat_whitespace_no_nl(s);
647 if (!*s) return -1;
648 start = s; /* this is it, assuming it's valid */
649 s = (char *)find_whitespace(start);
650 if (!*s) return -1;
652 /* tolerate the http[s] proxy style of putting the hostname in the url */
653 if (s-start >= 4 && !strcmpstart(start,"http")) {
654 tmp = start + 4;
655 if (*tmp == 's')
656 tmp++;
657 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
658 tmp = strchr(tmp+3, '/');
659 if (tmp && tmp < s) {
660 log_debug(LD_DIR,"Skipping over 'http[s]://hostname' string");
661 start = tmp;
666 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
667 *url = tor_malloc(s - start + 5);
668 strlcpy(*url,"/tor", s-start+5);
669 strlcat((*url)+4, start, s-start+1);
670 } else {
671 *url = tor_strndup(start, s-start);
673 return 0;
676 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
677 * <b>which</b>. The key should be given with a terminating colon and space;
678 * this function copies everything after, up to but not including the
679 * following \\r\\n. */
680 static char *
681 http_get_header(const char *headers, const char *which)
683 const char *cp = headers;
684 while (cp) {
685 if (!strcmpstart(cp, which)) {
686 char *eos;
687 cp += strlen(which);
688 if ((eos = strchr(cp,'\r')))
689 return tor_strndup(cp, eos-cp);
690 else
691 return tor_strdup(cp);
693 cp = strchr(cp, '\n');
694 if (cp)
695 ++cp;
697 return NULL;
700 /** Allocate and return a string describing the source of an HTTP request with
701 * headers <b>headers</b> received on <b>conn</b>. The format is either
702 * "'1.2.3.4'", or "'1.2.3.4' (forwarded for '5.6.7.8')".
704 static char *
705 http_get_origin(const char *headers, connection_t *conn)
707 char *fwd;
709 fwd = http_get_header(headers, "Forwarded-For: ");
710 if (!fwd)
711 fwd = http_get_header(headers, "X-Forwarded-For: ");
712 if (fwd) {
713 size_t len = strlen(fwd)+strlen(conn->address)+32;
714 char *result = tor_malloc(len);
715 tor_snprintf(result, len, "'%s' (forwarded for %s)", conn->address,
716 escaped(fwd));
717 tor_free(fwd);
718 return result;
719 } else {
720 size_t len = strlen(conn->address)+3;
721 char *result = tor_malloc(len);
722 tor_snprintf(result, len, "'%s'", conn->address);
723 return result;
727 /** Parse an HTTP response string <b>headers</b> of the form
728 * \verbatim
729 * "HTTP/1.\%d \%d\%s\r\n...".
730 * \endverbatim
732 * If it's well-formed, assign the status code to *<b>code</b> and
733 * return 0. Otherwise, return -1.
735 * On success: If <b>date</b> is provided, set *date to the Date
736 * header in the http headers, or 0 if no such header is found. If
737 * <b>compression</b> is provided, set *<b>compression</b> to the
738 * compression method given in the Content-Encoding header, or 0 if no
739 * such header is found, or -1 if the value of the header is not
740 * recognized. If <b>reason</b> is provided, strdup the reason string
741 * into it.
744 parse_http_response(const char *headers, int *code, time_t *date,
745 int *compression, char **reason)
747 int n1, n2;
748 char datestr[RFC1123_TIME_LEN+1];
749 smartlist_t *parsed_headers;
750 tor_assert(headers);
751 tor_assert(code);
753 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
755 if (sscanf(headers, "HTTP/1.%d %d", &n1, &n2) < 2 ||
756 (n1 != 0 && n1 != 1) ||
757 (n2 < 100 || n2 >= 600)) {
758 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
759 return -1;
761 *code = n2;
763 parsed_headers = smartlist_create();
764 smartlist_split_string(parsed_headers, headers, "\n",
765 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
766 if (reason) {
767 smartlist_t *status_line_elements = smartlist_create();
768 tor_assert(smartlist_len(parsed_headers));
769 smartlist_split_string(status_line_elements,
770 smartlist_get(parsed_headers, 0),
771 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
772 tor_assert(smartlist_len(status_line_elements) <= 3);
773 if (smartlist_len(status_line_elements) == 3) {
774 *reason = smartlist_get(status_line_elements, 2);
775 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
777 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
778 smartlist_free(status_line_elements);
780 if (date) {
781 *date = 0;
782 SMARTLIST_FOREACH(parsed_headers, const char *, s,
783 if (!strcmpstart(s, "Date: ")) {
784 strlcpy(datestr, s+6, sizeof(datestr));
785 /* This will do nothing on failure, so we don't need to check
786 the result. We shouldn't warn, since there are many other valid
787 date formats besides the one we use. */
788 parse_rfc1123_time(datestr, date);
789 break;
792 if (compression) {
793 const char *enc = NULL;
794 SMARTLIST_FOREACH(parsed_headers, const char *, s,
795 if (!strcmpstart(s, "Content-Encoding: ")) {
796 enc = s+18; break;
798 if (!enc || !strcmp(enc, "identity")) {
799 *compression = 0;
800 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
801 *compression = ZLIB_METHOD;
802 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
803 *compression = GZIP_METHOD;
804 } else {
805 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
806 escaped(enc));
807 *compression = -1;
810 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
811 smartlist_free(parsed_headers);
813 return 0;
816 /** Return true iff <b>body</b> doesn't start with a plausible router or
817 * running-list or directory opening. This is a sign of possible compression.
819 static int
820 body_is_plausible(const char *body, size_t len, int purpose)
822 int i;
823 if (len == 0)
824 return 1; /* empty bodies don't need decompression */
825 if (len < 32)
826 return 0;
827 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
828 if (!strcmpstart(body,"router") ||
829 !strcmpstart(body,"signed-directory") ||
830 !strcmpstart(body,"network-status") ||
831 !strcmpstart(body,"running-routers"))
832 return 1;
833 for (i=0;i<32;++i) {
834 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
835 return 0;
837 return 1;
838 } else {
839 return 1;
843 /** We are a client, and we've finished reading the server's
844 * response. Parse and it and act appropriately.
846 * If we're still happy with using this directory server in the future, return
847 * 0. Otherwise return -1; and the caller should consider trying the request
848 * again.
850 * The caller will take care of marking the connection for close.
852 static int
853 connection_dir_client_reached_eof(connection_t *conn)
855 char *body;
856 char *headers;
857 char *reason = NULL;
858 size_t body_len=0, orig_len=0;
859 int status_code;
860 time_t now, date_header=0;
861 int delta;
862 int compression;
863 int plausible;
864 int skewed=0;
865 int allow_partial = conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC;
866 int was_compressed=0;
868 switch (fetch_from_buf_http(conn->inbuf,
869 &headers, MAX_HEADERS_SIZE,
870 &body, &body_len, MAX_DIR_SIZE,
871 allow_partial)) {
872 case -1: /* overflow */
873 log_warn(LD_PROTOCOL,
874 "'fetch' response too large (server '%s:%d'). Closing.",
875 conn->address, conn->port);
876 return -1;
877 case 0:
878 log_info(LD_HTTP,
879 "'fetch' response not all here, but we're at eof. Closing.");
880 return -1;
881 /* case 1, fall through */
883 orig_len = body_len;
885 if (parse_http_response(headers, &status_code, &date_header,
886 &compression, &reason) < 0) {
887 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
888 conn->address, conn->port);
889 tor_free(body); tor_free(headers);
890 return -1;
892 if (!reason) reason = tor_strdup("[no reason given]");
894 log_debug(LD_DIR,
895 "Received response from directory server '%s:%d': %d %s",
896 conn->address, conn->port, status_code, escaped(reason));
898 if (date_header > 0) {
899 now = time(NULL);
900 delta = now-date_header;
901 if (abs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
902 log_fn(router_digest_is_trusted_dir(conn->identity_digest) ?
903 LOG_WARN : LOG_INFO,
904 LD_HTTP,
905 "Received directory with skewed time (server '%s:%d'): "
906 "we are %d minutes %s, or the directory is %d minutes %s.",
907 conn->address, conn->port,
908 abs(delta)/60, delta>0 ? "ahead" : "behind",
909 abs(delta)/60, delta>0 ? "behind" : "ahead");
910 skewed = 1; /* don't check the recommended-versions line */
911 } else {
912 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
913 "we are %d seconds skewed. (That's okay.)", delta);
917 if (status_code == 503) {
918 log_info(LD_DIR,"Received http status code %d (%s) from server "
919 "'%s:%d'. I'll try again soon.",
920 status_code, escaped(reason), conn->address, conn->port);
921 tor_free(body); tor_free(headers); tor_free(reason);
922 return -1;
925 plausible = body_is_plausible(body, body_len, conn->purpose);
926 if (compression || !plausible) {
927 char *new_body = NULL;
928 size_t new_len = 0;
929 int guessed = detect_compression_method(body, body_len);
930 if (compression <= 0 || guessed != compression) {
931 /* Tell the user if we don't believe what we're told about compression.*/
932 const char *description1, *description2;
933 if (compression == ZLIB_METHOD)
934 description1 = "as deflated";
935 else if (compression == GZIP_METHOD)
936 description1 = "as gzipped";
937 else if (compression == 0)
938 description1 = "as uncompressed";
939 else
940 description1 = "with an unknown Content-Encoding";
941 if (guessed == ZLIB_METHOD)
942 description2 = "deflated";
943 else if (guessed == GZIP_METHOD)
944 description2 = "gzipped";
945 else if (!plausible)
946 description2 = "confusing binary junk";
947 else
948 description2 = "uncompressed";
950 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
951 "but it seems to be %s.%s",
952 conn->address, conn->port, description1, description2,
953 (compression>0 && guessed>0)?" Trying both.":"");
955 /* Try declared compression first if we can. */
956 if (compression > 0)
957 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
958 allow_partial, LOG_PROTOCOL_WARN);
959 /* Okay, if that didn't work, and we think that it was compressed
960 * differently, try that. */
961 if (!new_body && guessed > 0 && compression != guessed)
962 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
963 allow_partial, LOG_PROTOCOL_WARN);
964 /* If we're pretty sure that we have a compressed directory, and
965 * we didn't manage to uncompress it, then warn and bail. */
966 if (!plausible && !new_body) {
967 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
968 "Unable to decompress HTTP body (server '%s:%d').",
969 conn->address, conn->port);
970 tor_free(body); tor_free(headers); tor_free(reason);
971 return -1;
973 if (new_body) {
974 tor_free(body);
975 body = new_body;
976 body_len = new_len;
977 was_compressed = 1;
981 if (conn->purpose == DIR_PURPOSE_FETCH_DIR) {
982 /* fetch/process the directory to cache it. */
983 log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
984 (int)body_len, conn->address, conn->port);
985 if (status_code != 200) {
986 log_warn(LD_DIR,"Received http status code %d (%s) from server "
987 "'%s:%d'. I'll try again soon.",
988 status_code, escaped(reason), conn->address, conn->port);
989 tor_free(body); tor_free(headers); tor_free(reason);
990 return -1;
992 if (router_parse_directory(body) < 0) {
993 log_notice(LD_DIR,"I failed to parse the directory I fetched from "
994 "'%s:%d'. Ignoring.", conn->address, conn->port);
996 note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
999 if (conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
1000 /* just update our list of running routers, if this list is new info */
1001 log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
1002 if (status_code != 200) {
1003 log_warn(LD_DIR,"Received http status code %d (%s) from server "
1004 "'%s:%d'. I'll try again soon.",
1005 status_code, escaped(reason), conn->address, conn->port);
1006 tor_free(body); tor_free(headers); tor_free(reason);
1007 return -1;
1009 if (router_parse_runningrouters(body)<0) {
1010 log_warn(LD_DIR,
1011 "Bad running-routers from server '%s:%d'. I'll try again soon.",
1012 conn->address, conn->port);
1013 tor_free(body); tor_free(headers); tor_free(reason);
1014 return -1;
1016 note_request(was_compressed?"dl/running-routers.z":
1017 "dl/running-routers", orig_len);
1020 if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
1021 smartlist_t *which = NULL;
1022 char *cp;
1023 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1024 "'%s:%d'",(int) body_len, conn->address, conn->port);
1025 if (status_code != 200) {
1026 log_warn(LD_DIR,
1027 "Received http status code %d (%s) from server "
1028 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1029 status_code, escaped(reason), conn->address, conn->port,
1030 conn->requested_resource);
1031 tor_free(body); tor_free(headers); tor_free(reason);
1032 connection_dir_download_networkstatus_failed(conn);
1033 return -1;
1035 note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
1036 if (conn->requested_resource &&
1037 !strcmpstart(conn->requested_resource,"fp/")) {
1038 which = smartlist_create();
1039 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1040 which, NULL, 0);
1042 cp = body;
1043 while (*cp) {
1044 char *next = strstr(cp, "\nnetwork-status-version");
1045 if (next)
1046 next[1] = '\0';
1047 /* learn from it, and then remove it from 'which' */
1048 if (router_set_networkstatus(cp, time(NULL), NS_FROM_DIR, which)<0)
1049 break;
1050 if (next) {
1051 next[1] = 'n';
1052 cp = next+1;
1054 else
1055 break;
1057 routers_update_all_from_networkstatus(); /*launches router downloads*/
1058 directory_info_has_arrived(time(NULL), 0);
1059 if (which) {
1060 if (smartlist_len(which)) {
1061 dir_networkstatus_download_failed(which);
1063 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1064 smartlist_free(which);
1068 if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
1069 smartlist_t *which = NULL;
1070 int n_asked_for = 0;
1071 log_info(LD_DIR,"Received server info (size %d) from server '%s:%d'",
1072 (int)body_len, conn->address, conn->port);
1073 note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
1074 if (conn->requested_resource &&
1075 !strcmpstart(conn->requested_resource,"d/")) {
1076 which = smartlist_create();
1077 dir_split_resource_into_fingerprints(conn->requested_resource+2,
1078 which, NULL, 0);
1079 n_asked_for = smartlist_len(which);
1081 if (status_code != 200) {
1082 int dir_okay = status_code == 404 ||
1083 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1084 /* 404 means that it didn't have them; no big deal.
1085 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1086 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1087 "Received http status code %d (%s) from server '%s:%d' "
1088 "while fetching \"/tor/server/%s\". I'll try again soon.",
1089 status_code, escaped(reason), conn->address, conn->port,
1090 conn->requested_resource);
1091 if (!which) {
1092 connection_dir_download_routerdesc_failed(conn);
1093 } else {
1094 dir_routerdesc_download_failed(which);
1095 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1096 smartlist_free(which);
1098 tor_free(body); tor_free(headers); tor_free(reason);
1099 return dir_okay ? 0 : -1;
1101 /* Learn the routers, assuming we requested by fingerprint or "all".
1102 * Right now, we only use "authority" to fetch ourself, so we don't want
1103 * to risk replacing ourself with a router running at the addr:port we
1104 * think we have.
1106 if (which || (conn->requested_resource &&
1107 !strcmpstart(conn->requested_resource, "all"))) {
1108 /* as we learn from them, we remove them from 'which' */
1109 router_load_routers_from_string(body, 0, which);
1110 directory_info_has_arrived(time(NULL), 0);
1112 if (which) { /* mark remaining ones as failed */
1113 log_info(LD_DIR, "Received %d/%d routers requested from %s:%d",
1114 n_asked_for-smartlist_len(which), n_asked_for,
1115 conn->address, (int)conn->port);
1116 if (smartlist_len(which)) {
1117 dir_routerdesc_download_failed(which);
1119 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1120 smartlist_free(which);
1122 if (conn->requested_resource &&
1123 !strcmpstart(conn->requested_resource,"authority")) {
1124 /* this might have been a dirport reachability test. see if it is. */
1125 routerinfo_t *me = router_get_my_routerinfo();
1126 if (me &&
1127 router_digest_is_me(conn->identity_digest) &&
1128 me->addr == conn->addr &&
1129 me->dir_port == conn->port)
1130 router_dirport_found_reachable();
1134 if (conn->purpose == DIR_PURPOSE_UPLOAD_DIR) {
1135 switch (status_code) {
1136 case 200:
1137 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1138 "descriptor: finished.");
1139 break;
1140 case 400:
1141 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1142 "dirserver '%s:%d'. Please correct.",
1143 escaped(reason), conn->address, conn->port);
1144 break;
1145 case 403:
1146 log_warn(LD_GENERAL,
1147 "http status 403 (%s) response from dirserver "
1148 "'%s:%d'. Is your clock skewed? Have you mailed us your key "
1149 "fingerprint? Are you using the right key? Are you using a "
1150 "private IP address? See http://tor.eff.org/doc/"
1151 "tor-doc-server.html",escaped(reason), conn->address, conn->port);
1152 break;
1153 default:
1154 log_warn(LD_GENERAL,
1155 "http status %d (%s) reason unexpected (server '%s:%d').",
1156 status_code, escaped(reason), conn->address, conn->port);
1157 break;
1159 /* return 0 in all cases, since we don't want to mark any
1160 * dirservers down just because they don't like us. */
1163 if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1164 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1165 "(%s))",
1166 (int)body_len, status_code, escaped(reason));
1167 switch (status_code) {
1168 case 200:
1169 if (rend_cache_store(body, body_len) < 0) {
1170 log_warn(LD_REND,"Failed to store rendezvous descriptor.");
1171 /* alice's ap_stream will notice when connection_mark_for_close
1172 * cleans it up */
1173 } else {
1174 /* success. notify pending connections about this. */
1175 conn->purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1176 rend_client_desc_here(conn->rend_query);
1178 break;
1179 case 404:
1180 /* not there. pending connections will be notified when
1181 * connection_mark_for_close cleans it up. */
1182 break;
1183 case 400:
1184 log_warn(LD_REND,
1185 "http status 400 (%s). Dirserver didn't like our "
1186 "rendezvous query?", escaped(reason));
1187 break;
1188 default:
1189 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1190 "'%s:%d').",
1191 status_code, escaped(reason), conn->address, conn->port);
1192 break;
1196 if (conn->purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
1197 switch (status_code) {
1198 case 200:
1199 log_info(LD_REND,
1200 "Uploading rendezvous descriptor: finished with status "
1201 "200 (%s)", escaped(reason));
1202 break;
1203 case 400:
1204 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1205 "'%s:%d'. Malformed rendezvous descriptor?",
1206 escaped(reason), conn->address, conn->port);
1207 break;
1208 default:
1209 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
1210 "'%s:%d').",
1211 status_code, escaped(reason), conn->address, conn->port);
1212 break;
1215 tor_free(body); tor_free(headers); tor_free(reason);
1216 return 0;
1219 /** Called when a directory connection reaches EOF */
1221 connection_dir_reached_eof(connection_t *conn)
1223 int retval;
1224 if (conn->state != DIR_CONN_STATE_CLIENT_READING) {
1225 log_info(LD_HTTP,"conn reached eof, not reading. Closing.");
1226 connection_close_immediate(conn); /* error: give up on flushing */
1227 connection_mark_for_close(conn);
1228 return -1;
1231 retval = connection_dir_client_reached_eof(conn);
1232 if (retval == 0) /* success */
1233 conn->state = DIR_CONN_STATE_CLIENT_FINISHED;
1234 connection_mark_for_close(conn);
1235 return retval;
1238 /** Read handler for directory connections. (That's connections <em>to</em>
1239 * directory servers and connections <em>at</em> directory servers.)
1242 connection_dir_process_inbuf(connection_t *conn)
1244 tor_assert(conn);
1245 tor_assert(conn->type == CONN_TYPE_DIR);
1247 /* Directory clients write, then read data until they receive EOF;
1248 * directory servers read data until they get an HTTP command, then
1249 * write their response (when it's finished flushing, they mark for
1250 * close).
1253 /* If we're on the dirserver side, look for a command. */
1254 if (conn->state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
1255 if (directory_handle_command(conn) < 0) {
1256 connection_mark_for_close(conn);
1257 return -1;
1259 return 0;
1262 /* XXX for READ states, might want to make sure inbuf isn't too big */
1264 if (!conn->inbuf_reached_eof)
1265 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
1266 return 0;
1269 /** Create an http response for the client <b>conn</b> out of
1270 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
1272 static void
1273 write_http_status_line(connection_t *conn, int status,
1274 const char *reason_phrase)
1276 char buf[256];
1277 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
1278 status, reason_phrase) < 0) {
1279 log_warn(LD_BUG,"Bug: status line too long.");
1280 return;
1282 connection_write_to_buf(buf, strlen(buf), conn);
1285 /** Helper function: return 1 if there are any dir conns of purpose
1286 * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
1287 * Else return 0.
1289 static int
1290 already_fetching_directory(int purpose)
1292 int i, n;
1293 connection_t *conn;
1294 connection_t **carray;
1296 get_connection_array(&carray,&n);
1297 for (i=0;i<n;i++) {
1298 conn = carray[i];
1299 if (conn->type == CONN_TYPE_DIR &&
1300 conn->purpose == purpose &&
1301 !conn->marked_for_close &&
1302 !router_digest_is_me(conn->identity_digest))
1303 return 1;
1305 return 0;
1308 #undef INSTRUMENT_DOWNLOADS
1310 #ifdef INSTRUMENT_DOWNLOADS
1311 /** DOCDOC */
1312 static strmap_t *request_bytes_map = NULL;
1314 /** DOCDOC */
1315 static void
1316 note_request(const char *key, size_t bytes)
1318 uint64_t *n;
1319 if (!request_bytes_map)
1320 request_bytes_map = strmap_new();
1322 n = strmap_get(request_bytes_map, key);
1323 if (!n) {
1324 n = tor_malloc_zero(sizeof(uint64_t));
1325 strmap_set(request_bytes_map, key, n);
1327 *n += bytes;
1330 /** DOCDOC */
1331 char *
1332 directory_dump_request_log(void)
1334 smartlist_t *lines;
1335 char tmp[256];
1336 char *result;
1337 strmap_iter_t *iter;
1339 if (!request_bytes_map)
1340 request_bytes_map = strmap_new();
1342 lines = smartlist_create();
1344 for (iter = strmap_iter_init(request_bytes_map);
1345 !strmap_iter_done(iter);
1346 iter = strmap_iter_next(request_bytes_map, iter)) {
1347 const char *key;
1348 void *val;
1349 uint64_t *n;
1350 strmap_iter_get(iter, &key, &val);
1351 n = val;
1352 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT"\n",
1353 key, U64_PRINTF_ARG(*n));
1354 smartlist_add(lines, tor_strdup(tmp));
1356 smartlist_sort_strings(lines);
1357 result = smartlist_join_strings(lines, "", 0, NULL);
1358 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
1359 smartlist_free(lines);
1360 return result;
1362 #else
1363 static void
1364 note_request(const char *key, size_t bytes)
1366 return;
1369 char *
1370 directory_dump_request_log(void)
1372 return tor_strdup("Not supported.");
1374 #endif
1376 /** Helper function: called when a dirserver gets a complete HTTP GET
1377 * request. Look for a request for a directory or for a rendezvous
1378 * service descriptor. On finding one, write a response into
1379 * conn-\>outbuf. If the request is unrecognized, send a 400.
1380 * Always return 0. */
1381 static int
1382 directory_handle_command_get(connection_t *conn, char *headers,
1383 char *body, size_t body_len)
1385 size_t dlen;
1386 const char *cp;
1387 char *url = NULL;
1388 char tmp[8192];
1389 char date[RFC1123_TIME_LEN+1];
1391 log_debug(LD_DIRSERV,"Received GET command.");
1393 conn->state = DIR_CONN_STATE_SERVER_WRITING;
1395 if (parse_http_url(headers, &url) < 0) {
1396 write_http_status_line(conn, 400, "Bad request");
1397 return 0;
1399 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
1401 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir.z")) { /* dir fetch */
1402 int deflated = !strcmp(url,"/tor/dir.z");
1403 dlen = dirserv_get_directory(&cp, deflated);
1405 if (dlen == 0) {
1406 log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
1407 "don't have a good one yet. Sending 503 Dir not available.");
1408 write_http_status_line(conn, 503, "Directory unavailable");
1409 /* try to get a new one now */
1410 if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR))
1411 directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1);
1412 tor_free(url);
1413 return 0;
1416 if (global_write_bucket_empty()) {
1417 log_info(LD_DIRSERV,
1418 "Client asked for the mirrored directory, but we've been "
1419 "writing too many bytes lately. Sending 503 Dir busy.");
1420 write_http_status_line(conn, 503, "Directory busy, try again later");
1421 tor_free(url);
1422 return 0;
1425 note_request(url, dlen);
1426 tor_free(url);
1428 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
1429 deflated?"deflated ":"");
1430 format_rfc1123_time(date, time(NULL));
1431 tor_snprintf(tmp, sizeof(tmp),
1432 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1433 "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
1434 date,
1435 (int)dlen,
1436 deflated?"application/octet-stream":"text/plain",
1437 deflated?"deflate":"identity");
1438 connection_write_to_buf(tmp, strlen(tmp), conn);
1439 connection_write_to_buf(cp, dlen, conn);
1440 return 0;
1443 if (!strcmp(url,"/tor/running-routers") ||
1444 !strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
1445 int deflated = !strcmp(url,"/tor/running-routers.z");
1446 dlen = dirserv_get_runningrouters(&cp, deflated);
1447 note_request(url, dlen);
1448 tor_free(url);
1449 if (!dlen) { /* we failed to create/cache cp */
1450 write_http_status_line(conn, 503, "Directory unavailable");
1451 /* try to get a new one now */
1452 if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST))
1453 directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
1454 return 0;
1457 format_rfc1123_time(date, time(NULL));
1458 tor_snprintf(tmp, sizeof(tmp),
1459 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1460 "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
1461 date,
1462 (int)dlen,
1463 deflated?"application/octet-stream":"text/plain",
1464 deflated?"deflate":"identity");
1465 connection_write_to_buf(tmp, strlen(tmp), conn);
1466 connection_write_to_buf(cp, strlen(cp), conn);
1467 return 0;
1470 if (!strcmpstart(url,"/tor/status/")) {
1471 /* v2 network status fetch. */
1472 size_t url_len = strlen(url);
1473 int deflated = !strcmp(url+url_len-2, ".z");
1474 smartlist_t *dir_objs = smartlist_create();
1475 const char *request_type = NULL;
1476 const char *key = url + strlen("/tor/status/");
1477 if (deflated)
1478 url[url_len-2] = '\0';
1479 if (dirserv_get_networkstatus_v2(dir_objs, key)) {
1480 smartlist_free(dir_objs);
1481 return 0;
1483 if (!strcmpstart(key, "fp/"))
1484 request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
1485 else if (!strcmpstart(key, "authority"))
1486 request_type = deflated?"/tor/status/authority.z":
1487 "/tor/status/authority";
1488 else if (!strcmpstart(key, "all"))
1489 request_type = deflated?"/tor/status/all.z":"/tor/status/all";
1490 else
1491 request_type = "/tor/status/?";
1492 tor_free(url);
1493 if (!smartlist_len(dir_objs)) { /* we failed to create/cache cp */
1494 write_http_status_line(conn, 503, "Network status object unavailable");
1495 smartlist_free(dir_objs);
1496 return 0;
1498 dlen = 0;
1499 SMARTLIST_FOREACH(dir_objs, cached_dir_t *, d,
1500 dlen += deflated?d->dir_z_len:d->dir_len);
1501 note_request(request_type,dlen);
1502 format_rfc1123_time(date, time(NULL));
1503 tor_snprintf(tmp, sizeof(tmp),
1504 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1505 "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
1506 date,
1507 (int)dlen,
1508 deflated?"application/octet-stream":"text/plain",
1509 deflated?"deflate":"identity");
1510 connection_write_to_buf(tmp, strlen(tmp), conn);
1511 SMARTLIST_FOREACH(dir_objs, cached_dir_t *, d,
1513 if (deflated)
1514 connection_write_to_buf(d->dir_z, d->dir_z_len, conn);
1515 else
1516 connection_write_to_buf(d->dir, d->dir_len, conn);
1518 smartlist_free(dir_objs);
1519 return 0;
1522 if (!strcmpstart(url,"/tor/server/")) {
1523 size_t url_len = strlen(url);
1524 int deflated = !strcmp(url+url_len-2, ".z");
1525 int res;
1526 const char *msg;
1527 smartlist_t *descs = smartlist_create();
1528 const char *request_type = NULL;
1529 if (deflated)
1530 url[url_len-2] = '\0';
1531 res = dirserv_get_routerdescs(descs, url, &msg);
1533 if (!strcmpstart(url, "/tor/server/fp/"))
1534 request_type = deflated?"/tor/server/fp.z":"/tor/server/fp";
1535 else if (!strcmpstart(url, "/tor/server/authority"))
1536 request_type = deflated?"/tor/server/authority.z":
1537 "/tor/server/authority";
1538 else if (!strcmpstart(url, "/tor/server/all"))
1539 request_type = deflated?"/tor/server/all.z":"/tor/server/all";
1540 else if (!strcmpstart(url, "/tor/server/d/"))
1541 request_type = deflated?"/tor/server/d.z":"/tor/server/d";
1542 else
1543 request_type = "/tor/server/?";
1544 tor_free(url);
1545 if (res < 0)
1546 write_http_status_line(conn, 404, msg);
1547 else {
1548 size_t len = 0;
1549 format_rfc1123_time(date, time(NULL));
1550 SMARTLIST_FOREACH(descs, signed_descriptor_t *, ri,
1551 len += ri->signed_descriptor_len);
1552 if (deflated) {
1553 size_t compressed_len;
1554 char *compressed;
1555 char *inp = tor_malloc(len+smartlist_len(descs)+1);
1556 char *cp = inp;
1557 SMARTLIST_FOREACH(descs, signed_descriptor_t *, ri,
1559 const char *body = signed_descriptor_get_body(ri);
1560 memcpy(cp, body, ri->signed_descriptor_len);
1561 cp += ri->signed_descriptor_len;
1562 *cp++ = '\n';
1564 *cp = '\0';
1565 /* XXXX This could be way more efficiently handled; let's see if it
1566 * shows up under oprofile. */
1567 if (tor_gzip_compress(&compressed, &compressed_len,
1568 inp, cp-inp, ZLIB_METHOD)<0) {
1569 tor_free(inp);
1570 smartlist_free(descs);
1571 return -1;
1573 tor_free(inp);
1574 tor_snprintf(tmp, sizeof(tmp),
1575 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1576 "Content-Type: application/octet-stream\r\n"
1577 "Content-Encoding: deflate\r\n\r\n",
1578 date,
1579 (int)compressed_len);
1580 note_request(request_type, compressed_len);
1581 connection_write_to_buf(tmp, strlen(tmp), conn);
1582 connection_write_to_buf(compressed, compressed_len, conn);
1583 tor_free(compressed);
1584 } else {
1585 tor_snprintf(tmp, sizeof(tmp),
1586 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1587 "Content-Type: text/plain\r\n\r\n",
1588 date,
1589 (int)len);
1590 note_request(request_type, len);
1591 connection_write_to_buf(tmp, strlen(tmp), conn);
1592 SMARTLIST_FOREACH(descs, signed_descriptor_t *, ri,
1594 const char *body = signed_descriptor_get_body(ri);
1595 connection_write_to_buf(body, ri->signed_descriptor_len, conn);
1599 smartlist_free(descs);
1600 return 0;
1603 if (!strcmpstart(url,"/tor/rendezvous/") ||
1604 !strcmpstart(url,"/tor/rendezvous1/")) {
1605 /* rendezvous descriptor fetch */
1606 const char *descp;
1607 size_t desc_len;
1608 int versioned = !strcmpstart(url,"/tor/rendezvous1/");
1609 const char *query = url+strlen("/tor/rendezvous/")+(versioned?1:0);
1611 if (!authdir_mode(get_options())) {
1612 /* We don't hand out rend descs. In fact, it could be a security
1613 * risk, since rend_cache_lookup_desc() below would provide it
1614 * if we're gone to the site recently, and 404 if we haven't.
1616 * Reject. */
1617 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
1618 "store rendezvous descriptors");
1619 tor_free(url);
1620 return 0;
1622 switch (rend_cache_lookup_desc(query, versioned?-1:0, &descp, &desc_len)) {
1623 case 1: /* valid */
1624 format_rfc1123_time(date, time(NULL));
1625 tor_snprintf(tmp, sizeof(tmp),
1626 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1627 "Content-Type: application/octet-stream\r\n\r\n",
1628 date,
1629 (int)desc_len);
1630 note_request("/tor/rendezvous?/", desc_len);
1631 connection_write_to_buf(tmp, strlen(tmp), conn);
1632 /* need to send descp separately, because it may include nuls */
1633 connection_write_to_buf(descp, desc_len, conn);
1634 break;
1635 case 0: /* well-formed but not present */
1636 write_http_status_line(conn, 404, "Not found");
1637 break;
1638 case -1: /* not well-formed */
1639 write_http_status_line(conn, 400, "Bad request");
1640 break;
1642 tor_free(url);
1643 return 0;
1646 if (!strcmpstart(url,"/tor/bytes.txt")) {
1647 char *bytes = directory_dump_request_log();
1648 size_t len = strlen(bytes);
1649 format_rfc1123_time(date, time(NULL));
1650 tor_snprintf(tmp, sizeof(tmp),
1651 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
1652 "Content-Type: text/plain\r\n\r\n",
1653 date,
1654 (int)len);
1655 connection_write_to_buf(tmp, strlen(tmp), conn);
1656 connection_write_to_buf(bytes, len, conn);
1657 tor_free(bytes);
1658 tor_free(url);
1659 return 0;
1662 /* we didn't recognize the url */
1663 write_http_status_line(conn, 404, "Not found");
1664 tor_free(url);
1665 return 0;
1668 /** Helper function: called when a dirserver gets a complete HTTP POST
1669 * request. Look for an uploaded server descriptor or rendezvous
1670 * service descriptor. On finding one, process it and write a
1671 * response into conn-\>outbuf. If the request is unrecognized, send a
1672 * 400. Always return 0. */
1673 static int
1674 directory_handle_command_post(connection_t *conn, char *headers,
1675 char *body, size_t body_len)
1677 const char *cp;
1678 char *origin = NULL;
1679 char *url = NULL;
1681 log_debug(LD_DIRSERV,"Received POST command.");
1683 conn->state = DIR_CONN_STATE_SERVER_WRITING;
1685 if (!authdir_mode(get_options())) {
1686 /* we just provide cached directories; we don't want to
1687 * receive anything. */
1688 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
1689 "accept posted server descriptors");
1690 return 0;
1693 if (parse_http_url(headers, &url) < 0) {
1694 write_http_status_line(conn, 400, "Bad request");
1695 return 0;
1697 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
1698 origin = http_get_origin(headers, conn);
1700 if (!strcmp(url,"/tor/")) { /* server descriptor post */
1701 const char *msg;
1702 int r = dirserv_add_descriptor(body, &msg);
1703 tor_assert(msg);
1704 if (r > 0)
1705 dirserv_get_directory(&cp, 0); /* rebuild and write to disk */
1706 switch (r) {
1707 case -2:
1708 case -1:
1709 case 1:
1710 log_notice(LD_DIRSERV,"Rejected router descriptor from %s.", origin);
1711 /* malformed descriptor, or something wrong */
1712 write_http_status_line(conn, 400, msg);
1713 break;
1714 case 0: /* accepted but discarded */
1715 case 2: /* accepted */
1716 write_http_status_line(conn, 200, msg);
1717 break;
1719 goto done;
1722 if (!strcmpstart(url,"/tor/rendezvous/publish")) {
1723 /* rendezvous descriptor post */
1724 if (rend_cache_store(body, body_len) < 0) {
1725 // char tmp[1024*2+1];
1726 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
1727 "Rejected rend descriptor (length %d) from %s.",
1728 (int)body_len, origin);
1729 #if 0
1730 if (body_len <= 1024) {
1731 base16_encode(tmp, sizeof(tmp), body, body_len);
1732 log_notice(LD_DIRSERV,"Body was: %s", escaped(tmp));
1734 #endif
1735 write_http_status_line(conn, 400, "Invalid service descriptor rejected");
1736 } else {
1737 write_http_status_line(conn, 200, "Service descriptor stored");
1739 goto done;
1742 /* we didn't recognize the url */
1743 write_http_status_line(conn, 404, "Not found");
1745 done:
1746 tor_free(url);
1747 tor_free(origin);
1748 return 0;
1751 /** Called when a dirserver receives data on a directory connection;
1752 * looks for an HTTP request. If the request is complete, remove it
1753 * from the inbuf, try to process it; otherwise, leave it on the
1754 * buffer. Return a 0 on success, or -1 on error.
1756 static int
1757 directory_handle_command(connection_t *conn)
1759 char *headers=NULL, *body=NULL;
1760 size_t body_len=0;
1761 int r;
1763 tor_assert(conn);
1764 tor_assert(conn->type == CONN_TYPE_DIR);
1766 switch (fetch_from_buf_http(conn->inbuf,
1767 &headers, MAX_HEADERS_SIZE,
1768 &body, &body_len, MAX_BODY_SIZE, 0)) {
1769 case -1: /* overflow */
1770 log_warn(LD_DIRSERV,
1771 "Invalid input from address '%s'. Closing.", conn->address);
1772 return -1;
1773 case 0:
1774 log_debug(LD_DIRSERV,"command not all here yet.");
1775 return 0;
1776 /* case 1, fall through */
1779 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
1781 if (!strncasecmp(headers,"GET",3))
1782 r = directory_handle_command_get(conn, headers, body, body_len);
1783 else if (!strncasecmp(headers,"POST",4))
1784 r = directory_handle_command_post(conn, headers, body, body_len);
1785 else {
1786 log_warn(LD_PROTOCOL,"Got headers %s with unknown command. Closing.",
1787 escaped(headers));
1788 r = -1;
1791 tor_free(headers); tor_free(body);
1792 return r;
1795 /** Write handler for directory connections; called when all data has
1796 * been flushed. Close the connection or wait for a response as
1797 * appropriate.
1800 connection_dir_finished_flushing(connection_t *conn)
1802 tor_assert(conn);
1803 tor_assert(conn->type == CONN_TYPE_DIR);
1805 switch (conn->state) {
1806 case DIR_CONN_STATE_CLIENT_SENDING:
1807 log_debug(LD_DIR,"client finished sending command.");
1808 conn->state = DIR_CONN_STATE_CLIENT_READING;
1809 connection_stop_writing(conn);
1810 return 0;
1811 case DIR_CONN_STATE_SERVER_WRITING:
1812 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
1813 connection_mark_for_close(conn);
1814 return 0;
1815 default:
1816 log_warn(LD_BUG,"Bug: called in unexpected state %d.", conn->state);
1817 tor_fragile_assert();
1818 return -1;
1820 return 0;
1823 /** Connected handler for directory connections: begin sending data to the
1824 * server */
1826 connection_dir_finished_connecting(connection_t *conn)
1828 tor_assert(conn);
1829 tor_assert(conn->type == CONN_TYPE_DIR);
1830 tor_assert(conn->state == DIR_CONN_STATE_CONNECTING);
1832 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
1833 conn->address,conn->port);
1835 conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
1836 return 0;
1839 /** Called when one or more networkstatus fetches have failed (with uppercase
1840 * fingerprints listed in <b>failed</>). Mark those fingerprints as having
1841 * failed once. */
1842 static void
1843 dir_networkstatus_download_failed(smartlist_t *failed)
1845 SMARTLIST_FOREACH(failed, const char *, fp,
1847 char digest[DIGEST_LEN];
1848 trusted_dir_server_t *dir;
1849 base16_decode(digest, DIGEST_LEN, fp, strlen(fp));
1850 dir = router_get_trusteddirserver_by_digest(digest);
1852 if (dir)
1853 ++dir->n_networkstatus_failures;
1857 /** Called when one or more networkstatus fetches have failed (with uppercase
1858 * fingerprints listed in <b>failed</>). */
1859 static void
1860 dir_routerdesc_download_failed(smartlist_t *failed)
1862 char digest[DIGEST_LEN];
1863 local_routerstatus_t *rs;
1864 time_t now = time(NULL);
1865 int server = server_mode(get_options()) && get_options()->DirPort;
1866 SMARTLIST_FOREACH(failed, const char *, cp,
1868 base16_decode(digest, DIGEST_LEN, cp, strlen(cp));
1869 rs = router_get_combined_status_by_digest(digest);
1870 if (!rs || rs->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
1871 continue;
1872 ++rs->n_download_failures;
1873 if (server) {
1874 switch (rs->n_download_failures) {
1875 case 1: rs->next_attempt_at = 0; break;
1876 case 2: rs->next_attempt_at = 0; break;
1877 case 3: rs->next_attempt_at = now+60; break;
1878 case 4: rs->next_attempt_at = now+60; break;
1879 case 5: rs->next_attempt_at = now+60*2; break;
1880 case 6: rs->next_attempt_at = now+60*5; break;
1881 case 7: rs->next_attempt_at = now+60*15; break;
1882 default: rs->next_attempt_at = TIME_MAX; break;
1884 } else {
1885 switch (rs->n_download_failures) {
1886 case 1: rs->next_attempt_at = 0; break;
1887 case 2: rs->next_attempt_at = now+60; break;
1888 case 3: rs->next_attempt_at = now+60*5; break;
1889 case 4: rs->next_attempt_at = now+60*10; break;
1890 default: rs->next_attempt_at = TIME_MAX; break;
1893 if (rs->next_attempt_at == 0)
1894 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
1895 cp, (int)rs->n_download_failures);
1896 else if (rs->next_attempt_at < TIME_MAX)
1897 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
1898 cp, (int)rs->n_download_failures,
1899 (int)(rs->next_attempt_at-now));
1900 else
1901 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
1902 cp, (int)rs->n_download_failures);
1905 /* update_router_descriptor_downloads(time(NULL)); */
1908 /* Given a directory <b>resource</b> request, containing zero
1909 * or more strings separated by plus signs, followed optionally by ".z", store
1910 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
1911 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
1912 * decode_hex is true, then delete all elements that aren't hex digests, and
1913 * decode the rest.
1916 dir_split_resource_into_fingerprints(const char *resource,
1917 smartlist_t *fp_out, int *compressed_out,
1918 int decode_hex)
1920 int old_len;
1921 tor_assert(fp_out);
1922 old_len = smartlist_len(fp_out);
1923 smartlist_split_string(fp_out, resource, "+", 0, 0);
1924 if (compressed_out)
1925 *compressed_out = 0;
1926 if (smartlist_len(fp_out) > old_len) {
1927 char *last = smartlist_get(fp_out,smartlist_len(fp_out)-1);
1928 size_t last_len = strlen(last);
1929 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
1930 last[last_len-2] = '\0';
1931 if (compressed_out)
1932 *compressed_out = 1;
1935 if (decode_hex) {
1936 int i;
1937 char *cp, *d = NULL;
1938 for (i = old_len; i < smartlist_len(fp_out); ++i) {
1939 cp = smartlist_get(fp_out, i);
1940 if (strlen(cp) != HEX_DIGEST_LEN) {
1941 log_info(LD_DIR,
1942 "Skipping digest %s with non-standard length.", escaped(cp));
1943 smartlist_del(fp_out, i--);
1944 goto again;
1946 d = tor_malloc_zero(DIGEST_LEN);
1947 if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
1948 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
1949 smartlist_del(fp_out, i--);
1950 goto again;
1952 smartlist_set(fp_out, i, d);
1953 d = NULL;
1954 again:
1955 tor_free(cp);
1956 tor_free(d);
1959 return 0;