trivial cleanups
[tor.git] / src / or / directory.c
blob124c64684eece93d56595669da29b7765b89a738
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2009, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "or.h"
7 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
8 #ifndef OPENBSD
9 #include <malloc.h>
10 #endif
11 #endif
13 /**
14 * \file directory.c
15 * \brief Code to send and fetch directories and router
16 * descriptors via HTTP. Directories use dirserv.c to generate the
17 * results; clients use routers.c to parse them.
18 **/
20 /* In-points to directory.c:
22 * - directory_post_to_dirservers(), called from
23 * router_upload_dir_desc_to_dirservers() in router.c
24 * upload_service_descriptor() in rendservice.c
25 * - directory_get_from_dirserver(), called from
26 * rend_client_refetch_renddesc() in rendclient.c
27 * run_scheduled_events() in main.c
28 * do_hup() in main.c
29 * - connection_dir_process_inbuf(), called from
30 * connection_process_inbuf() in connection.c
31 * - connection_dir_finished_flushing(), called from
32 * connection_finished_flushing() in connection.c
33 * - connection_dir_finished_connecting(), called from
34 * connection_finished_connecting() in connection.c
36 static void directory_send_command(dir_connection_t *conn,
37 int purpose, int direct, const char *resource,
38 const char *payload, size_t payload_len,
39 int supports_conditional_consensus,
40 time_t if_modified_since);
41 static int directory_handle_command(dir_connection_t *conn);
42 static int body_is_plausible(const char *body, size_t body_len, int purpose);
43 static int purpose_needs_anonymity(uint8_t dir_purpose,
44 uint8_t router_purpose);
45 static char *http_get_header(const char *headers, const char *which);
46 static void http_set_address_origin(const char *headers, connection_t *conn);
47 static void connection_dir_download_networkstatus_failed(
48 dir_connection_t *conn, int status_code);
49 static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
50 static void connection_dir_download_cert_failed(
51 dir_connection_t *conn, int status_code);
52 static void dir_networkstatus_download_failed(smartlist_t *failed,
53 int status_code);
54 static void dir_routerdesc_download_failed(smartlist_t *failed,
55 int status_code,
56 int router_purpose,
57 int was_extrainfo,
58 int was_descriptor_digests);
59 static void note_client_request(int purpose, int compressed, size_t bytes);
60 static int client_likes_consensus(networkstatus_t *v, const char *want_url);
62 static void directory_initiate_command_rend(const char *address,
63 const tor_addr_t *addr,
64 uint16_t or_port,
65 uint16_t dir_port,
66 int supports_conditional_consensus,
67 int supports_begindir,
68 const char *digest,
69 uint8_t dir_purpose,
70 uint8_t router_purpose,
71 int anonymized_connection,
72 const char *resource,
73 const char *payload,
74 size_t payload_len,
75 time_t if_modified_since,
76 const rend_data_t *rend_query);
78 /********* START VARIABLES **********/
80 /** How far in the future do we allow a directory server to tell us it is
81 * before deciding that one of us has the wrong time? */
82 #define ALLOW_DIRECTORY_TIME_SKEW (30*60)
84 #define X_ADDRESS_HEADER "X-Your-Address-Is: "
86 /** HTTP cache control: how long do we tell proxies they can cache each
87 * kind of document we serve? */
88 #define FULL_DIR_CACHE_LIFETIME (60*60)
89 #define RUNNINGROUTERS_CACHE_LIFETIME (20*60)
90 #define DIRPORTFRONTPAGE_CACHE_LIFETIME (20*60)
91 #define NETWORKSTATUS_CACHE_LIFETIME (5*60)
92 #define ROUTERDESC_CACHE_LIFETIME (30*60)
93 #define ROUTERDESC_BY_DIGEST_CACHE_LIFETIME (48*60*60)
94 #define ROBOTS_CACHE_LIFETIME (24*60*60)
95 #define MICRODESC_CACHE_LIFETIME (48*60*60)
97 /********* END VARIABLES ************/
99 /** Return true iff the directory purpose <b>dir_purpose</b> (and if it's
100 * fetching descriptors, it's fetching them for <b>router_purpose</b>)
101 * must use an anonymous connection to a directory. */
102 static int
103 purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
105 if (get_options()->AllDirActionsPrivate)
106 return 1;
107 if (router_purpose == ROUTER_PURPOSE_BRIDGE && has_completed_circuit)
108 return 1; /* if no circuits yet, we may need this info to bootstrap. */
109 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
110 dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
111 dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
112 dir_purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS ||
113 dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
114 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
115 dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
116 dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
117 dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
118 dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
119 return 0;
120 return 1;
123 /** Return a newly allocated string describing <b>auth</b>. */
124 char *
125 authority_type_to_string(authority_type_t auth)
127 char *result;
128 smartlist_t *lst = smartlist_create();
129 if (auth & V1_AUTHORITY)
130 smartlist_add(lst, (void*)"V1");
131 if (auth & V2_AUTHORITY)
132 smartlist_add(lst, (void*)"V2");
133 if (auth & BRIDGE_AUTHORITY)
134 smartlist_add(lst, (void*)"Bridge");
135 if (auth & HIDSERV_AUTHORITY)
136 smartlist_add(lst, (void*)"Hidden service");
137 if (smartlist_len(lst)) {
138 result = smartlist_join_strings(lst, ", ", 0, NULL);
139 } else {
140 result = tor_strdup("[Not an authority]");
142 smartlist_free(lst);
143 return result;
146 /** Return a string describing a given directory connection purpose. */
147 static const char *
148 dir_conn_purpose_to_string(int purpose)
150 switch (purpose)
152 case DIR_PURPOSE_FETCH_RENDDESC:
153 return "hidden-service descriptor fetch";
154 case DIR_PURPOSE_UPLOAD_DIR:
155 return "server descriptor upload";
156 case DIR_PURPOSE_UPLOAD_RENDDESC:
157 return "hidden-service descriptor upload";
158 case DIR_PURPOSE_UPLOAD_VOTE:
159 return "server vote upload";
160 case DIR_PURPOSE_UPLOAD_SIGNATURES:
161 return "consensus signature upload";
162 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
163 return "network-status fetch";
164 case DIR_PURPOSE_FETCH_SERVERDESC:
165 return "server descriptor fetch";
166 case DIR_PURPOSE_FETCH_EXTRAINFO:
167 return "extra-info fetch";
168 case DIR_PURPOSE_FETCH_CONSENSUS:
169 return "consensus network-status fetch";
170 case DIR_PURPOSE_FETCH_CERTIFICATE:
171 return "authority cert fetch";
172 case DIR_PURPOSE_FETCH_STATUS_VOTE:
173 return "status vote fetch";
174 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
175 return "consensus signature fetch";
176 case DIR_PURPOSE_FETCH_RENDDESC_V2:
177 return "hidden-service v2 descriptor fetch";
178 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
179 return "hidden-service v2 descriptor upload";
182 log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
183 return "(unknown)";
186 /** Return true iff <b>identity_digest</b> is the digest of a router we
187 * believe to support extrainfo downloads. (If <b>is_authority</b> we do
188 * additional checking that's only valid for authorities.) */
190 router_supports_extrainfo(const char *identity_digest, int is_authority)
192 routerinfo_t *ri = router_get_by_digest(identity_digest);
194 if (ri) {
195 if (ri->caches_extra_info)
196 return 1;
197 if (is_authority && ri->platform &&
198 tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
199 return 1;
201 if (is_authority) {
202 routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
203 if (rs && rs->version_supports_extrainfo_upload)
204 return 1;
206 return 0;
209 /** Return true iff any trusted directory authority has accepted our
210 * server descriptor.
212 * We consider any authority sufficient because waiting for all of
213 * them means it never happens while any authority is down; we don't
214 * go for something more complex in the middle (like \>1/3 or \>1/2 or
215 * \>=1/2) because that doesn't seem necessary yet.
218 directories_have_accepted_server_descriptor(void)
220 smartlist_t *servers = router_get_trusted_dir_servers();
221 or_options_t *options = get_options();
222 SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
223 if ((d->type & options->_PublishServerDescriptor) &&
224 d->has_accepted_serverdesc) {
225 return 1;
228 return 0;
231 /** Start a connection to every suitable directory authority, using
232 * connection purpose 'purpose' and uploading the payload 'payload'
233 * (length 'payload_len'). dir_purpose should be one of
234 * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
236 * <b>type</b> specifies what sort of dir authorities (V1, V2,
237 * HIDSERV, BRIDGE) we should upload to.
239 * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
240 * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
241 * bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
242 * to all authorities, and the extra-info document to all authorities that
243 * support it.
245 void
246 directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
247 authority_type_t type,
248 const char *payload,
249 size_t payload_len, size_t extrainfo_len)
251 int post_via_tor;
252 smartlist_t *dirservers = router_get_trusted_dir_servers();
253 int found = 0;
254 tor_assert(dirservers);
255 /* This tries dirservers which we believe to be down, but ultimately, that's
256 * harmless, and we may as well err on the side of getting things uploaded.
258 SMARTLIST_FOREACH_BEGIN(dirservers, trusted_dir_server_t *, ds) {
259 routerstatus_t *rs = &(ds->fake_status);
260 size_t upload_len = payload_len;
261 tor_addr_t ds_addr;
263 if ((type & ds->type) == 0)
264 continue;
266 found = 1; /* at least one authority of this type was listed */
267 if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
268 ds->has_accepted_serverdesc = 0;
270 if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
271 upload_len += extrainfo_len;
272 log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
273 (int) extrainfo_len);
275 tor_addr_from_ipv4h(&ds_addr, ds->addr);
276 post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) ||
277 !fascist_firewall_allows_address_dir(&ds_addr, ds->dir_port);
278 directory_initiate_command_routerstatus(rs, dir_purpose,
279 router_purpose,
280 post_via_tor,
281 NULL, payload, upload_len, 0);
282 } SMARTLIST_FOREACH_END(ds);
283 if (!found) {
284 char *s = authority_type_to_string(type);
285 log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
286 "of type '%s', but no authorities of that type listed!", s);
287 tor_free(s);
291 /** Start a connection to a random running directory server, using
292 * connection purpose <b>dir_purpose</b>, intending to fetch descriptors
293 * of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
294 * Use <b>pds_flags</b> as arguments to router_pick_directory_server()
295 * or router_pick_trusteddirserver().
297 void
298 directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
299 const char *resource, int pds_flags)
301 routerstatus_t *rs = NULL;
302 or_options_t *options = get_options();
303 int prefer_authority = directory_fetches_from_authorities(options);
304 int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
305 authority_type_t type;
306 time_t if_modified_since = 0;
308 /* FFFF we could break this switch into its own function, and call
309 * it elsewhere in directory.c. -RD */
310 switch (dir_purpose) {
311 case DIR_PURPOSE_FETCH_EXTRAINFO:
312 type = EXTRAINFO_CACHE |
313 (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
314 V2_AUTHORITY);
315 break;
316 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
317 case DIR_PURPOSE_FETCH_SERVERDESC:
318 type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
319 V2_AUTHORITY);
320 break;
321 case DIR_PURPOSE_FETCH_RENDDESC:
322 type = HIDSERV_AUTHORITY;
323 break;
324 case DIR_PURPOSE_FETCH_STATUS_VOTE:
325 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
326 type = V3_AUTHORITY;
327 break;
328 case DIR_PURPOSE_FETCH_CONSENSUS:
329 case DIR_PURPOSE_FETCH_CERTIFICATE:
330 type = V3_AUTHORITY;
331 break;
332 default:
333 log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
334 return;
337 if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
338 networkstatus_t *v = networkstatus_get_latest_consensus();
339 if (v)
340 if_modified_since = v->valid_after + 180;
343 if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
344 return;
346 if (!get_via_tor) {
347 if (options->UseBridges && type != BRIDGE_AUTHORITY) {
348 /* want to ask a running bridge for which we have a descriptor. */
349 /* XXX022 we assume that all of our bridges can answer any
350 * possible directory question. This won't be true forever. -RD */
351 /* It certainly is not true with conditional consensus downloading,
352 * so, for now, never assume the server supports that. */
353 routerinfo_t *ri = choose_random_entry(NULL);
354 if (ri) {
355 tor_addr_t addr;
356 tor_addr_from_ipv4h(&addr, ri->addr);
357 directory_initiate_command(ri->address, &addr,
358 ri->or_port, 0,
359 0, /* don't use conditional consensus url */
360 1, ri->cache_info.identity_digest,
361 dir_purpose,
362 router_purpose,
363 0, resource, NULL, 0, if_modified_since);
364 } else
365 log_notice(LD_DIR, "Ignoring directory request, since no bridge "
366 "nodes are available yet.");
367 return;
368 } else {
369 if (prefer_authority || type == BRIDGE_AUTHORITY) {
370 /* only ask authdirservers, and don't ask myself */
371 rs = router_pick_trusteddirserver(type, pds_flags);
372 if (rs == NULL && (pds_flags & PDS_NO_EXISTING_SERVERDESC_FETCH)) {
373 /* We don't want to fetch from any authorities that we're currently
374 * fetching server descriptors from, and we got no match. Did we
375 * get no match because all the authorities have connections
376 * fetching server descriptors (in which case we should just
377 * return,) or because all the authorities are down or on fire or
378 * unreachable or something (in which case we should go on with
379 * our fallback code)? */
380 pds_flags &= ~PDS_NO_EXISTING_SERVERDESC_FETCH;
381 rs = router_pick_trusteddirserver(type, pds_flags);
382 if (rs) {
383 log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
384 "are in use.");
385 return;
389 if (!rs && type != BRIDGE_AUTHORITY) {
390 /* anybody with a non-zero dirport will do */
391 rs = router_pick_directory_server(type, pds_flags);
392 if (!rs) {
393 log_info(LD_DIR, "No router found for %s; falling back to "
394 "dirserver list.", dir_conn_purpose_to_string(dir_purpose));
395 rs = router_pick_trusteddirserver(type, pds_flags);
396 if (!rs)
397 get_via_tor = 1; /* last resort: try routing it via Tor */
401 } else { /* get_via_tor */
402 /* Never use fascistfirewall; we're going via Tor. */
403 if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
404 /* only ask hidserv authorities, any of them will do */
405 pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
406 rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, pds_flags);
407 } else {
408 /* anybody with a non-zero dirport will do. Disregard firewalls. */
409 pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
410 rs = router_pick_directory_server(type, pds_flags);
411 /* If we have any hope of building an indirect conn, we know some router
412 * descriptors. If (rs==NULL), we can't build circuits anyway, so
413 * there's no point in falling back to the authorities in this case. */
417 if (rs)
418 directory_initiate_command_routerstatus(rs, dir_purpose,
419 router_purpose,
420 get_via_tor,
421 resource, NULL, 0,
422 if_modified_since);
423 else {
424 log_notice(LD_DIR,
425 "While fetching directory info, "
426 "no running dirservers known. Will try again later. "
427 "(purpose %d)", dir_purpose);
428 if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
429 /* remember we tried them all and failed. */
430 directory_all_unreachable(time(NULL));
435 /** As directory_get_from_dirserver, but initiates a request to <i>every</i>
436 * directory authority other than ourself. Only for use by authorities when
437 * searching for missing information while voting. */
438 void
439 directory_get_from_all_authorities(uint8_t dir_purpose,
440 uint8_t router_purpose,
441 const char *resource)
443 tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
444 dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
446 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
447 trusted_dir_server_t *, ds,
449 routerstatus_t *rs;
450 if (router_digest_is_me(ds->digest))
451 continue;
452 if (!(ds->type & V3_AUTHORITY))
453 continue;
454 rs = &ds->fake_status;
455 directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
456 0, resource, NULL, 0, 0);
460 /** Same as directory_initiate_command_routerstatus(), but accepts
461 * rendezvous data to fetch a hidden service descriptor. */
462 void
463 directory_initiate_command_routerstatus_rend(routerstatus_t *status,
464 uint8_t dir_purpose,
465 uint8_t router_purpose,
466 int anonymized_connection,
467 const char *resource,
468 const char *payload,
469 size_t payload_len,
470 time_t if_modified_since,
471 const rend_data_t *rend_query)
473 routerinfo_t *router;
474 char address_buf[INET_NTOA_BUF_LEN+1];
475 struct in_addr in;
476 const char *address;
477 tor_addr_t addr;
478 router = router_get_by_digest(status->identity_digest);
479 if (!router && anonymized_connection) {
480 log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
481 "don't have its router descriptor.", status->nickname);
482 return;
483 } else if (router) {
484 address = router->address;
485 } else {
486 in.s_addr = htonl(status->addr);
487 tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
488 address = address_buf;
490 tor_addr_from_ipv4h(&addr, status->addr);
491 directory_initiate_command_rend(address, &addr,
492 status->or_port, status->dir_port,
493 status->version_supports_conditional_consensus,
494 status->version_supports_begindir,
495 status->identity_digest,
496 dir_purpose, router_purpose,
497 anonymized_connection, resource,
498 payload, payload_len, if_modified_since,
499 rend_query);
502 /** Launch a new connection to the directory server <b>status</b> to
503 * upload or download a server or rendezvous
504 * descriptor. <b>dir_purpose</b> determines what
505 * kind of directory connection we're launching, and must be one of
506 * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC|RENDDESC_V2}. <b>router_purpose</b>
507 * specifies the descriptor purposes we have in mind (currently only
508 * used for FETCH_DIR).
510 * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
511 * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
513 * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
514 * want to fetch.
516 void
517 directory_initiate_command_routerstatus(routerstatus_t *status,
518 uint8_t dir_purpose,
519 uint8_t router_purpose,
520 int anonymized_connection,
521 const char *resource,
522 const char *payload,
523 size_t payload_len,
524 time_t if_modified_since)
526 directory_initiate_command_routerstatus_rend(status, dir_purpose,
527 router_purpose,
528 anonymized_connection, resource,
529 payload, payload_len,
530 if_modified_since, NULL);
533 /** Return true iff <b>conn</b> is the client side of a directory connection
534 * we launched to ourself in order to determine the reachability of our
535 * dir_port. */
536 static int
537 directory_conn_is_self_reachability_test(dir_connection_t *conn)
539 if (conn->requested_resource &&
540 !strcmpstart(conn->requested_resource,"authority")) {
541 routerinfo_t *me = router_get_my_routerinfo();
542 if (me &&
543 router_digest_is_me(conn->identity_digest) &&
544 tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/
545 me->dir_port == conn->_base.port)
546 return 1;
548 return 0;
551 /** Called when we are unable to complete the client's request to a directory
552 * server due to a network error: Mark the router as down and try again if
553 * possible.
555 void
556 connection_dir_request_failed(dir_connection_t *conn)
558 if (directory_conn_is_self_reachability_test(conn)) {
559 return; /* this was a test fetch. don't retry. */
561 if (entry_list_is_constrained(get_options()))
562 router_set_status(conn->identity_digest, 0); /* don't try him again */
563 if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
564 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
565 conn->_base.address);
566 connection_dir_download_networkstatus_failed(conn, -1);
567 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
568 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
569 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
570 conn->_base.address);
571 connection_dir_download_routerdesc_failed(conn);
572 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
573 networkstatus_consensus_download_failed(0);
574 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
575 log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
576 conn->_base.address);
577 connection_dir_download_cert_failed(conn, 0);
578 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
579 log_info(LD_DIR, "Giving up downloading detached signatures from '%s'",
580 conn->_base.address);
581 } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
582 log_info(LD_DIR, "Giving up downloading votes from '%s'",
583 conn->_base.address);
587 /** Called when an attempt to download one or more network status
588 * documents on connection <b>conn</b> failed. Decide whether to
589 * retry the fetch now, later, or never.
591 static void
592 connection_dir_download_networkstatus_failed(dir_connection_t *conn,
593 int status_code)
595 if (!conn->requested_resource) {
596 /* We never reached directory_send_command, which means that we never
597 * opened a network connection. Either we're out of sockets, or the
598 * network is down. Either way, retrying would be pointless. */
599 return;
601 if (!strcmpstart(conn->requested_resource, "all")) {
602 /* We're a non-authoritative directory cache; try again. Ignore status
603 * code, since we don't want to keep trying forever in a tight loop
604 * if all the authorities are shutting us out. */
605 smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
606 SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
607 download_status_failed(&ds->v2_ns_dl_status, 0));
608 directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose,
609 "all.z", 0 /* don't retry_if_no_servers */);
610 } else if (!strcmpstart(conn->requested_resource, "fp/")) {
611 /* We were trying to download by fingerprint; mark them all as having
612 * failed, and possibly retry them later.*/
613 smartlist_t *failed = smartlist_create();
614 dir_split_resource_into_fingerprints(conn->requested_resource+3,
615 failed, NULL, 0);
616 if (smartlist_len(failed)) {
617 dir_networkstatus_download_failed(failed, status_code);
618 SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
620 smartlist_free(failed);
624 /** Called when an attempt to download one or more router descriptors
625 * or extra-info documents on connection <b>conn</b> failed.
627 static void
628 connection_dir_download_routerdesc_failed(dir_connection_t *conn)
630 /* No need to increment the failure count for routerdescs, since
631 * it's not their fault. */
633 /* No need to relaunch descriptor downloads here: we already do it
634 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
635 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
636 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
638 (void) conn;
641 /** Called when an attempt to fetch a certificate fails. */
642 static void
643 connection_dir_download_cert_failed(dir_connection_t *conn, int status)
645 smartlist_t *failed;
646 tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE);
648 if (!conn->requested_resource)
649 return;
650 failed = smartlist_create();
651 dir_split_resource_into_fingerprints(conn->requested_resource+3,
652 failed, NULL, DSR_HEX);
653 SMARTLIST_FOREACH(failed, char *, cp,
655 authority_cert_dl_failed(cp, status);
656 tor_free(cp);
658 smartlist_free(failed);
660 update_certificate_downloads(time(NULL));
663 /** Evaluate the situation and decide if we should use an encrypted
664 * "begindir-style" connection for this directory request.
665 * 1) If or_port is 0, or it's a direct conn and or_port is firewalled
666 * or we're a dir mirror, no.
667 * 2) If we prefer to avoid begindir conns, and we're not fetching or
668 * publishing a bridge relay descriptor, no.
669 * 3) Else yes.
671 static int
672 directory_command_should_use_begindir(or_options_t *options,
673 const tor_addr_t *addr,
674 int or_port, uint8_t router_purpose,
675 int anonymized_connection)
677 if (!or_port)
678 return 0; /* We don't know an ORPort -- no chance. */
679 if (!anonymized_connection)
680 if (!fascist_firewall_allows_address_or(addr, or_port) ||
681 directory_fetches_from_authorities(options) ||
682 (server_mode(options) && !options->Address))
683 return 0; /* We're firewalled or are acting like a relay -- also no. */
684 if (!options->TunnelDirConns &&
685 router_purpose != ROUTER_PURPOSE_BRIDGE)
686 return 0; /* We prefer to avoid using begindir conns. Fine. */
687 return 1;
690 /** Helper for directory_initiate_command_routerstatus: send the
691 * command to a server whose address is <b>address</b>, whose IP is
692 * <b>addr</b>, whose directory port is <b>dir_port</b>, whose tor version
693 * <b>supports_begindir</b>, and whose identity key digest is
694 * <b>digest</b>. */
695 void
696 directory_initiate_command(const char *address, const tor_addr_t *_addr,
697 uint16_t or_port, uint16_t dir_port,
698 int supports_conditional_consensus,
699 int supports_begindir, const char *digest,
700 uint8_t dir_purpose, uint8_t router_purpose,
701 int anonymized_connection, const char *resource,
702 const char *payload, size_t payload_len,
703 time_t if_modified_since)
705 directory_initiate_command_rend(address, _addr, or_port, dir_port,
706 supports_conditional_consensus,
707 supports_begindir, digest, dir_purpose,
708 router_purpose, anonymized_connection,
709 resource, payload, payload_len,
710 if_modified_since, NULL);
713 /** Same as directory_initiate_command(), but accepts rendezvous data to
714 * fetch a hidden service descriptor. */
715 static void
716 directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
717 uint16_t or_port, uint16_t dir_port,
718 int supports_conditional_consensus,
719 int supports_begindir, const char *digest,
720 uint8_t dir_purpose, uint8_t router_purpose,
721 int anonymized_connection,
722 const char *resource,
723 const char *payload, size_t payload_len,
724 time_t if_modified_since,
725 const rend_data_t *rend_query)
727 dir_connection_t *conn;
728 or_options_t *options = get_options();
729 int socket_error = 0;
730 int use_begindir = supports_begindir &&
731 directory_command_should_use_begindir(options, _addr,
732 or_port, router_purpose, anonymized_connection);
733 tor_addr_t addr;
735 tor_assert(address);
736 tor_assert(_addr);
737 tor_assert(or_port || dir_port);
738 tor_assert(digest);
740 tor_addr_copy(&addr, _addr);
742 log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
743 anonymized_connection, use_begindir);
745 log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
747 /* ensure that we don't make direct connections when a SOCKS server is
748 * configured. */
749 if (!anonymized_connection && !use_begindir && !options->HttpProxy &&
750 (options->Socks4Proxy || options->Socks5Proxy)) {
751 log_warn(LD_DIR, "Cannot connect to a directory server through a "
752 "SOCKS proxy!");
753 return;
756 conn = dir_connection_new(AF_INET);
758 /* set up conn so it's got all the data we need to remember */
759 tor_addr_copy(&conn->_base.addr, &addr);
760 conn->_base.port = use_begindir ? or_port : dir_port;
761 conn->_base.address = tor_strdup(address);
762 memcpy(conn->identity_digest, digest, DIGEST_LEN);
764 conn->_base.purpose = dir_purpose;
765 conn->router_purpose = router_purpose;
767 /* give it an initial state */
768 conn->_base.state = DIR_CONN_STATE_CONNECTING;
770 /* decide whether we can learn our IP address from this conn */
771 conn->dirconn_direct = !anonymized_connection;
773 /* copy rendezvous data, if any */
774 if (rend_query)
775 conn->rend_data = rend_data_dup(rend_query);
777 if (!anonymized_connection && !use_begindir) {
778 /* then we want to connect to dirport directly */
780 if (options->HttpProxy) {
781 tor_addr_copy(&addr, &options->HttpProxyAddr);
782 dir_port = options->HttpProxyPort;
785 switch (connection_connect(TO_CONN(conn), conn->_base.address, &addr,
786 dir_port, &socket_error)) {
787 case -1:
788 connection_dir_request_failed(conn); /* retry if we want */
789 /* XXX we only pass 'conn' above, not 'resource', 'payload',
790 * etc. So in many situations it can't retry! -RD */
791 connection_free(TO_CONN(conn));
792 return;
793 case 1:
794 /* start flushing conn */
795 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
796 /* fall through */
797 case 0:
798 /* queue the command on the outbuf */
799 directory_send_command(conn, dir_purpose, 1, resource,
800 payload, payload_len,
801 supports_conditional_consensus,
802 if_modified_since);
803 connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT);
804 /* writable indicates finish, readable indicates broken link,
805 error indicates broken link in windowsland. */
807 } else { /* we want to connect via a tor connection */
808 edge_connection_t *linked_conn;
810 /* If it's an anonymized connection, remember the fact that we
811 * wanted it for later: maybe we'll want it again soon. */
812 if (anonymized_connection && use_begindir)
813 rep_hist_note_used_internal(time(NULL), 0, 1);
814 else if (anonymized_connection && !use_begindir)
815 rep_hist_note_used_port(time(NULL), conn->_base.port);
817 /* make an AP connection
818 * populate it and add it at the right state
819 * hook up both sides
821 linked_conn =
822 connection_ap_make_link(conn->_base.address, conn->_base.port,
823 digest, use_begindir, conn->dirconn_direct);
824 if (!linked_conn) {
825 log_warn(LD_NET,"Making tunnel to dirserver failed.");
826 connection_mark_for_close(TO_CONN(conn));
827 return;
829 connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
831 if (connection_add(TO_CONN(conn)) < 0) {
832 log_warn(LD_NET,"Unable to add connection for link to dirserver.");
833 connection_mark_for_close(TO_CONN(conn));
834 return;
836 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
837 /* queue the command on the outbuf */
838 directory_send_command(conn, dir_purpose, 0, resource,
839 payload, payload_len,
840 supports_conditional_consensus,
841 if_modified_since);
842 connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
843 connection_start_reading(TO_CONN(linked_conn));
847 /** Return true iff anything we say on <b>conn</b> is being encrypted before
848 * we send it to the client/server. */
850 connection_dir_is_encrypted(dir_connection_t *conn)
852 /* Right now it's sufficient to see if conn is or has been linked, since
853 * the only thing it could be linked to is an edge connection on a
854 * circuit, and the only way it could have been unlinked is at the edge
855 * connection getting closed.
857 return TO_CONN(conn)->linked;
860 /** Helper for sorting
862 * sort strings alphabetically
864 static int
865 _compare_strs(const void **a, const void **b)
867 const char *s1 = *a, *s2 = *b;
868 return strcmp(s1, s2);
871 #define CONDITIONAL_CONSENSUS_FPR_LEN 3
872 #if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
873 #error "conditional consensus fingerprint length is larger than digest length"
874 #endif
876 /** Return the URL we should use for a consensus download.
878 * This url depends on whether or not the server we go to
879 * is sufficiently new to support conditional consensus downloading,
880 * i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
882 static char *
883 directory_get_consensus_url(int supports_conditional_consensus)
885 char *url;
886 size_t len;
888 if (supports_conditional_consensus) {
889 char *authority_id_list;
890 smartlist_t *authority_digests = smartlist_create();
892 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
893 trusted_dir_server_t *, ds,
895 char *hex;
896 if (!(ds->type & V3_AUTHORITY))
897 continue;
899 hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
900 base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
901 ds->v3_identity_digest, CONDITIONAL_CONSENSUS_FPR_LEN);
902 smartlist_add(authority_digests, hex);
904 smartlist_sort(authority_digests, _compare_strs);
905 authority_id_list = smartlist_join_strings(authority_digests,
906 "+", 0, NULL);
908 len = strlen(authority_id_list)+64;
909 url = tor_malloc(len);
910 tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z",
911 authority_id_list);
913 SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
914 smartlist_free(authority_digests);
915 tor_free(authority_id_list);
916 } else {
917 url = tor_strdup("/tor/status-vote/current/consensus.z");
919 return url;
922 /** Queue an appropriate HTTP command on conn-\>outbuf. The other args
923 * are as in directory_initiate_command().
925 static void
926 directory_send_command(dir_connection_t *conn,
927 int purpose, int direct, const char *resource,
928 const char *payload, size_t payload_len,
929 int supports_conditional_consensus,
930 time_t if_modified_since)
932 char proxystring[256];
933 char proxyauthstring[256];
934 char hoststring[128];
935 char imsstring[RFC1123_TIME_LEN+32];
936 char *url;
937 char request[8192];
938 const char *httpcommand = NULL;
939 size_t len;
941 tor_assert(conn);
942 tor_assert(conn->_base.type == CONN_TYPE_DIR);
944 tor_free(conn->requested_resource);
945 if (resource)
946 conn->requested_resource = tor_strdup(resource);
948 /* come up with a string for which Host: we want */
949 if (conn->_base.port == 80) {
950 strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
951 } else {
952 tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
953 conn->_base.address, conn->_base.port);
956 /* Format if-modified-since */
957 if (!if_modified_since) {
958 imsstring[0] = '\0';
959 } else {
960 char b[RFC1123_TIME_LEN+1];
961 format_rfc1123_time(b, if_modified_since);
962 tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
965 /* come up with some proxy lines, if we're using one. */
966 if (direct && get_options()->HttpProxy) {
967 char *base64_authenticator=NULL;
968 const char *authenticator = get_options()->HttpProxyAuthenticator;
970 tor_snprintf(proxystring, sizeof(proxystring),"http://%s", hoststring);
971 if (authenticator) {
972 base64_authenticator = alloc_http_authenticator(authenticator);
973 if (!base64_authenticator)
974 log_warn(LD_BUG, "Encoding http authenticator failed");
976 if (base64_authenticator) {
977 tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
978 "\r\nProxy-Authorization: Basic %s",
979 base64_authenticator);
980 tor_free(base64_authenticator);
981 } else {
982 proxyauthstring[0] = 0;
984 } else {
985 proxystring[0] = 0;
986 proxyauthstring[0] = 0;
989 switch (purpose) {
990 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
991 tor_assert(resource);
992 httpcommand = "GET";
993 len = strlen(resource)+32;
994 url = tor_malloc(len);
995 tor_snprintf(url, len, "/tor/status/%s", resource);
996 break;
997 case DIR_PURPOSE_FETCH_CONSENSUS:
998 tor_assert(!resource);
999 tor_assert(!payload);
1000 httpcommand = "GET";
1001 url = directory_get_consensus_url(supports_conditional_consensus);
1002 log_info(LD_DIR, "Downloading consensus from %s using %s",
1003 hoststring, url);
1004 break;
1005 case DIR_PURPOSE_FETCH_CERTIFICATE:
1006 tor_assert(resource);
1007 tor_assert(!payload);
1008 httpcommand = "GET";
1009 len = strlen(resource)+32;
1010 url = tor_malloc(len);
1011 tor_snprintf(url, len, "/tor/keys/%s", resource);
1012 break;
1013 case DIR_PURPOSE_FETCH_STATUS_VOTE:
1014 tor_assert(resource);
1015 tor_assert(!payload);
1016 httpcommand = "GET";
1017 len = strlen(resource)+32;
1018 url = tor_malloc(len);
1019 tor_snprintf(url, len, "/tor/status-vote/next/%s.z", resource);
1020 break;
1021 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
1022 tor_assert(!resource);
1023 tor_assert(!payload);
1024 httpcommand = "GET";
1025 url = tor_strdup("/tor/status-vote/next/consensus-signatures.z");
1026 break;
1027 case DIR_PURPOSE_FETCH_SERVERDESC:
1028 tor_assert(resource);
1029 httpcommand = "GET";
1030 len = strlen(resource)+32;
1031 url = tor_malloc(len);
1032 tor_snprintf(url, len, "/tor/server/%s", resource);
1033 break;
1034 case DIR_PURPOSE_FETCH_EXTRAINFO:
1035 tor_assert(resource);
1036 httpcommand = "GET";
1037 len = strlen(resource)+32;
1038 url = tor_malloc(len);
1039 tor_snprintf(url, len, "/tor/extra/%s", resource);
1040 break;
1041 case DIR_PURPOSE_UPLOAD_DIR:
1042 tor_assert(!resource);
1043 tor_assert(payload);
1044 httpcommand = "POST";
1045 url = tor_strdup("/tor/");
1046 break;
1047 case DIR_PURPOSE_UPLOAD_VOTE:
1048 tor_assert(!resource);
1049 tor_assert(payload);
1050 httpcommand = "POST";
1051 url = tor_strdup("/tor/post/vote");
1052 break;
1053 case DIR_PURPOSE_UPLOAD_SIGNATURES:
1054 tor_assert(!resource);
1055 tor_assert(payload);
1056 httpcommand = "POST";
1057 url = tor_strdup("/tor/post/consensus-signature");
1058 break;
1059 case DIR_PURPOSE_FETCH_RENDDESC_V2:
1060 tor_assert(resource);
1061 tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32);
1062 tor_assert(!payload);
1063 httpcommand = "GET";
1064 len = strlen(resource) + 32;
1065 url = tor_malloc(len);
1066 tor_snprintf(url, len, "/tor/rendezvous2/%s", resource);
1067 break;
1068 case DIR_PURPOSE_UPLOAD_RENDDESC:
1069 tor_assert(!resource);
1070 tor_assert(payload);
1071 httpcommand = "POST";
1072 url = tor_strdup("/tor/rendezvous/publish");
1073 break;
1074 case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
1075 tor_assert(!resource);
1076 tor_assert(payload);
1077 httpcommand = "POST";
1078 url = tor_strdup("/tor/rendezvous2/publish");
1079 break;
1080 default:
1081 tor_assert(0);
1082 return;
1085 if (strlen(proxystring) + strlen(url) >= 4096) {
1086 log_warn(LD_BUG,
1087 "Squid does not like URLs longer than 4095 bytes, and this "
1088 "one is %d bytes long: %s%s",
1089 (int)(strlen(proxystring) + strlen(url)), proxystring, url);
1092 tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
1093 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1094 connection_write_to_buf(url, strlen(url), TO_CONN(conn));
1095 tor_free(url);
1097 if (!strcmp(httpcommand, "GET") && !payload) {
1098 tor_snprintf(request, sizeof(request),
1099 " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
1100 hoststring,
1101 imsstring,
1102 proxyauthstring);
1103 } else {
1104 tor_snprintf(request, sizeof(request),
1105 " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
1106 payload ? (unsigned long)payload_len : 0,
1107 hoststring,
1108 imsstring,
1109 proxyauthstring);
1111 connection_write_to_buf(request, strlen(request), TO_CONN(conn));
1113 if (payload) {
1114 /* then send the payload afterwards too */
1115 connection_write_to_buf(payload, payload_len, TO_CONN(conn));
1119 /** Parse an HTTP request string <b>headers</b> of the form
1120 * \verbatim
1121 * "\%s [http[s]://]\%s HTTP/1..."
1122 * \endverbatim
1123 * If it's well-formed, strdup the second \%s into *<b>url</b>, and
1124 * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
1125 * so it does. Return 0.
1126 * Otherwise, return -1.
1128 static int
1129 parse_http_url(const char *headers, char **url)
1131 char *s, *start, *tmp;
1133 s = (char *)eat_whitespace_no_nl(headers);
1134 if (!*s) return -1;
1135 s = (char *)find_whitespace(s); /* get past GET/POST */
1136 if (!*s) return -1;
1137 s = (char *)eat_whitespace_no_nl(s);
1138 if (!*s) return -1;
1139 start = s; /* this is it, assuming it's valid */
1140 s = (char *)find_whitespace(start);
1141 if (!*s) return -1;
1143 /* tolerate the http[s] proxy style of putting the hostname in the url */
1144 if (s-start >= 4 && !strcmpstart(start,"http")) {
1145 tmp = start + 4;
1146 if (*tmp == 's')
1147 tmp++;
1148 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
1149 tmp = strchr(tmp+3, '/');
1150 if (tmp && tmp < s) {
1151 log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
1152 start = tmp;
1157 if (s-start < 5 || strcmpstart(start,"/tor/")) { /* need to rewrite it */
1158 *url = tor_malloc(s - start + 5);
1159 strlcpy(*url,"/tor", s-start+5);
1160 strlcat((*url)+4, start, s-start+1);
1161 } else {
1162 *url = tor_strndup(start, s-start);
1164 return 0;
1167 /** Return a copy of the first HTTP header in <b>headers</b> whose key is
1168 * <b>which</b>. The key should be given with a terminating colon and space;
1169 * this function copies everything after, up to but not including the
1170 * following \\r\\n. */
1171 static char *
1172 http_get_header(const char *headers, const char *which)
1174 const char *cp = headers;
1175 while (cp) {
1176 if (!strcasecmpstart(cp, which)) {
1177 char *eos;
1178 cp += strlen(which);
1179 if ((eos = strchr(cp,'\r')))
1180 return tor_strndup(cp, eos-cp);
1181 else
1182 return tor_strdup(cp);
1184 cp = strchr(cp, '\n');
1185 if (cp)
1186 ++cp;
1188 return NULL;
1191 /** If <b>headers</b> indicates that a proxy was involved, then rewrite
1192 * <b>conn</b>-\>address to describe our best guess of the address that
1193 * originated this HTTP request. */
1194 static void
1195 http_set_address_origin(const char *headers, connection_t *conn)
1197 char *fwd;
1199 fwd = http_get_header(headers, "Forwarded-For: ");
1200 if (!fwd)
1201 fwd = http_get_header(headers, "X-Forwarded-For: ");
1202 if (fwd) {
1203 struct in_addr in;
1204 if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) {
1205 log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s",
1206 escaped(fwd));
1207 tor_free(fwd);
1208 return;
1210 tor_free(conn->address);
1211 conn->address = tor_strdup(fwd);
1212 tor_free(fwd);
1216 /** Parse an HTTP response string <b>headers</b> of the form
1217 * \verbatim
1218 * "HTTP/1.\%d \%d\%s\r\n...".
1219 * \endverbatim
1221 * If it's well-formed, assign the status code to *<b>code</b> and
1222 * return 0. Otherwise, return -1.
1224 * On success: If <b>date</b> is provided, set *date to the Date
1225 * header in the http headers, or 0 if no such header is found. If
1226 * <b>compression</b> is provided, set *<b>compression</b> to the
1227 * compression method given in the Content-Encoding header, or 0 if no
1228 * such header is found, or -1 if the value of the header is not
1229 * recognized. If <b>reason</b> is provided, strdup the reason string
1230 * into it.
1233 parse_http_response(const char *headers, int *code, time_t *date,
1234 compress_method_t *compression, char **reason)
1236 unsigned n1, n2;
1237 char datestr[RFC1123_TIME_LEN+1];
1238 smartlist_t *parsed_headers;
1239 tor_assert(headers);
1240 tor_assert(code);
1242 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
1244 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
1245 (n1 != 0 && n1 != 1) ||
1246 (n2 < 100 || n2 >= 600)) {
1247 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
1248 return -1;
1250 *code = n2;
1252 parsed_headers = smartlist_create();
1253 smartlist_split_string(parsed_headers, headers, "\n",
1254 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
1255 if (reason) {
1256 smartlist_t *status_line_elements = smartlist_create();
1257 tor_assert(smartlist_len(parsed_headers));
1258 smartlist_split_string(status_line_elements,
1259 smartlist_get(parsed_headers, 0),
1260 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
1261 tor_assert(smartlist_len(status_line_elements) <= 3);
1262 if (smartlist_len(status_line_elements) == 3) {
1263 *reason = smartlist_get(status_line_elements, 2);
1264 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
1266 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
1267 smartlist_free(status_line_elements);
1269 if (date) {
1270 *date = 0;
1271 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1272 if (!strcmpstart(s, "Date: ")) {
1273 strlcpy(datestr, s+6, sizeof(datestr));
1274 /* This will do nothing on failure, so we don't need to check
1275 the result. We shouldn't warn, since there are many other valid
1276 date formats besides the one we use. */
1277 parse_rfc1123_time(datestr, date);
1278 break;
1281 if (compression) {
1282 const char *enc = NULL;
1283 SMARTLIST_FOREACH(parsed_headers, const char *, s,
1284 if (!strcmpstart(s, "Content-Encoding: ")) {
1285 enc = s+18; break;
1287 if (!enc || !strcmp(enc, "identity")) {
1288 *compression = NO_METHOD;
1289 } else if (!strcmp(enc, "deflate") || !strcmp(enc, "x-deflate")) {
1290 *compression = ZLIB_METHOD;
1291 } else if (!strcmp(enc, "gzip") || !strcmp(enc, "x-gzip")) {
1292 *compression = GZIP_METHOD;
1293 } else {
1294 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
1295 escaped(enc));
1296 *compression = UNKNOWN_METHOD;
1299 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
1300 smartlist_free(parsed_headers);
1302 return 0;
1305 /** Return true iff <b>body</b> doesn't start with a plausible router or
1306 * running-list or directory opening. This is a sign of possible compression.
1308 static int
1309 body_is_plausible(const char *body, size_t len, int purpose)
1311 int i;
1312 if (len == 0)
1313 return 1; /* empty bodies don't need decompression */
1314 if (len < 32)
1315 return 0;
1316 if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
1317 if (!strcmpstart(body,"router") ||
1318 !strcmpstart(body,"signed-directory") ||
1319 !strcmpstart(body,"network-status") ||
1320 !strcmpstart(body,"running-routers"))
1321 return 1;
1322 for (i=0;i<32;++i) {
1323 if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
1324 return 0;
1326 return 1;
1327 } else {
1328 return 1;
1332 /** Called when we've just fetched a bunch of router descriptors in
1333 * <b>body</b>. The list <b>which</b>, if present, holds digests for
1334 * descriptors we requested: descriptor digests if <b>descriptor_digests</b>
1335 * is true, or identity digests otherwise. Parse the descriptors, validate
1336 * them, and annotate them as having purpose <b>purpose</b> and as having been
1337 * downloaded from <b>source</b>.
1339 * Return the number of routers actually added. */
1340 static int
1341 load_downloaded_routers(const char *body, smartlist_t *which,
1342 int descriptor_digests,
1343 int router_purpose,
1344 const char *source)
1346 char buf[256];
1347 char time_buf[ISO_TIME_LEN+1];
1348 int added = 0;
1349 int general = router_purpose == ROUTER_PURPOSE_GENERAL;
1350 format_iso_time(time_buf, time(NULL));
1351 tor_assert(source);
1353 if (tor_snprintf(buf, sizeof(buf),
1354 "@downloaded-at %s\n"
1355 "@source %s\n"
1356 "%s%s%s", time_buf, escaped(source),
1357 !general ? "@purpose " : "",
1358 !general ? router_purpose_to_string(router_purpose) : "",
1359 !general ? "\n" : "")<0)
1360 return added;
1362 added = router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1363 descriptor_digests, buf);
1364 control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
1365 count_loading_descriptors_progress());
1366 return added;
1369 /** We are a client, and we've finished reading the server's
1370 * response. Parse it and act appropriately.
1372 * If we're still happy with using this directory server in the future, return
1373 * 0. Otherwise return -1; and the caller should consider trying the request
1374 * again.
1376 * The caller will take care of marking the connection for close.
1378 static int
1379 connection_dir_client_reached_eof(dir_connection_t *conn)
1381 char *body;
1382 char *headers;
1383 char *reason = NULL;
1384 size_t body_len=0, orig_len=0;
1385 int status_code;
1386 time_t date_header=0;
1387 long delta;
1388 compress_method_t compression;
1389 int plausible;
1390 int skewed=0;
1391 int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1392 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
1393 int was_compressed=0;
1394 time_t now = time(NULL);
1396 switch (fetch_from_buf_http(conn->_base.inbuf,
1397 &headers, MAX_HEADERS_SIZE,
1398 &body, &body_len, MAX_DIR_DL_SIZE,
1399 allow_partial)) {
1400 case -1: /* overflow */
1401 log_warn(LD_PROTOCOL,
1402 "'fetch' response too large (server '%s:%d'). Closing.",
1403 conn->_base.address, conn->_base.port);
1404 return -1;
1405 case 0:
1406 log_info(LD_HTTP,
1407 "'fetch' response not all here, but we're at eof. Closing.");
1408 return -1;
1409 /* case 1, fall through */
1411 orig_len = body_len;
1413 if (parse_http_response(headers, &status_code, &date_header,
1414 &compression, &reason) < 0) {
1415 log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
1416 conn->_base.address, conn->_base.port);
1417 tor_free(body); tor_free(headers);
1418 return -1;
1420 if (!reason) reason = tor_strdup("[no reason given]");
1422 log_debug(LD_DIR,
1423 "Received response from directory server '%s:%d': %d %s",
1424 conn->_base.address, conn->_base.port, status_code,
1425 escaped(reason));
1427 /* now check if it's got any hints for us about our IP address. */
1428 if (conn->dirconn_direct) {
1429 char *guess = http_get_header(headers, X_ADDRESS_HEADER);
1430 if (guess) {
1431 router_new_address_suggestion(guess, conn);
1432 tor_free(guess);
1436 if (date_header > 0) {
1437 /* The date header was written very soon after we sent our request,
1438 * so compute the skew as the difference between sending the request
1439 * and the date header. (We used to check now-date_header, but that's
1440 * inaccurate if we spend a lot of time downloading.)
1442 delta = conn->_base.timestamp_lastwritten - date_header;
1443 if (labs(delta)>ALLOW_DIRECTORY_TIME_SKEW) {
1444 char dbuf[64];
1445 int trusted = router_digest_is_trusted_dir(conn->identity_digest);
1446 format_time_interval(dbuf, sizeof(dbuf), delta);
1447 log_fn(trusted ? LOG_WARN : LOG_INFO,
1448 LD_HTTP,
1449 "Received directory with skewed time (server '%s:%d'): "
1450 "It seems that our clock is %s by %s, or that theirs is %s. "
1451 "Tor requires an accurate clock to work: please check your time, "
1452 "timezone, and date settings.",
1453 conn->_base.address, conn->_base.port,
1454 delta>0 ? "ahead" : "behind", dbuf,
1455 delta>0 ? "behind" : "ahead");
1456 skewed = 1; /* don't check the recommended-versions line */
1457 control_event_general_status(trusted ? LOG_WARN : LOG_NOTICE,
1458 "CLOCK_SKEW SKEW=%ld SOURCE=DIRSERV:%s:%d",
1459 delta, conn->_base.address, conn->_base.port);
1460 } else {
1461 log_debug(LD_HTTP, "Time on received directory is within tolerance; "
1462 "we are %ld seconds skewed. (That's okay.)", delta);
1465 (void) skewed; /* skewed isn't used yet. */
1467 if (status_code == 503) {
1468 if (body_len < 16) {
1469 routerstatus_t *rs;
1470 trusted_dir_server_t *ds;
1471 log_info(LD_DIR,"Received http status code %d (%s) from server "
1472 "'%s:%d'. I'll try again soon.",
1473 status_code, escaped(reason), conn->_base.address,
1474 conn->_base.port);
1475 if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
1476 rs->last_dir_503_at = now;
1477 if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
1478 ds->fake_status.last_dir_503_at = now;
1480 tor_free(body); tor_free(headers); tor_free(reason);
1481 return -1;
1483 /* XXXX022 Remove this once every server with bug 539 is obsolete. */
1484 log_info(LD_DIR, "Server at '%s:%d' sent us a 503 response, but included "
1485 "a body anyway. We'll pretend it gave us a 200.",
1486 conn->_base.address, conn->_base.port);
1487 status_code = 200;
1490 plausible = body_is_plausible(body, body_len, conn->_base.purpose);
1491 if (compression != NO_METHOD || !plausible) {
1492 char *new_body = NULL;
1493 size_t new_len = 0;
1494 compress_method_t guessed = detect_compression_method(body, body_len);
1495 if (compression == UNKNOWN_METHOD || guessed != compression) {
1496 /* Tell the user if we don't believe what we're told about compression.*/
1497 const char *description1, *description2;
1498 if (compression == ZLIB_METHOD)
1499 description1 = "as deflated";
1500 else if (compression == GZIP_METHOD)
1501 description1 = "as gzipped";
1502 else if (compression == NO_METHOD)
1503 description1 = "as uncompressed";
1504 else
1505 description1 = "with an unknown Content-Encoding";
1506 if (guessed == ZLIB_METHOD)
1507 description2 = "deflated";
1508 else if (guessed == GZIP_METHOD)
1509 description2 = "gzipped";
1510 else if (!plausible)
1511 description2 = "confusing binary junk";
1512 else
1513 description2 = "uncompressed";
1515 log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
1516 "but it seems to be %s.%s",
1517 conn->_base.address, conn->_base.port, description1,
1518 description2,
1519 (compression>0 && guessed>0)?" Trying both.":"");
1521 /* Try declared compression first if we can. */
1522 if (compression == GZIP_METHOD || compression == ZLIB_METHOD)
1523 tor_gzip_uncompress(&new_body, &new_len, body, body_len, compression,
1524 !allow_partial, LOG_PROTOCOL_WARN);
1525 /* Okay, if that didn't work, and we think that it was compressed
1526 * differently, try that. */
1527 if (!new_body &&
1528 (guessed == GZIP_METHOD || guessed == ZLIB_METHOD) &&
1529 compression != guessed)
1530 tor_gzip_uncompress(&new_body, &new_len, body, body_len, guessed,
1531 !allow_partial, LOG_PROTOCOL_WARN);
1532 /* If we're pretty sure that we have a compressed directory, and
1533 * we didn't manage to uncompress it, then warn and bail. */
1534 if (!plausible && !new_body) {
1535 log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
1536 "Unable to decompress HTTP body (server '%s:%d').",
1537 conn->_base.address, conn->_base.port);
1538 tor_free(body); tor_free(headers); tor_free(reason);
1539 return -1;
1541 if (new_body) {
1542 tor_free(body);
1543 body = new_body;
1544 body_len = new_len;
1545 was_compressed = 1;
1549 if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
1550 smartlist_t *which = NULL;
1551 v2_networkstatus_source_t source;
1552 char *cp;
1553 log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
1554 "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
1555 if (status_code != 200) {
1556 log_warn(LD_DIR,
1557 "Received http status code %d (%s) from server "
1558 "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
1559 status_code, escaped(reason), conn->_base.address,
1560 conn->_base.port, conn->requested_resource);
1561 tor_free(body); tor_free(headers); tor_free(reason);
1562 connection_dir_download_networkstatus_failed(conn, status_code);
1563 return -1;
1565 if (conn->requested_resource &&
1566 !strcmpstart(conn->requested_resource,"fp/")) {
1567 source = NS_FROM_DIR_BY_FP;
1568 which = smartlist_create();
1569 dir_split_resource_into_fingerprints(conn->requested_resource+3,
1570 which, NULL, 0);
1571 } else if (conn->requested_resource &&
1572 !strcmpstart(conn->requested_resource, "all")) {
1573 source = NS_FROM_DIR_ALL;
1574 which = smartlist_create();
1575 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1576 trusted_dir_server_t *, ds,
1578 char *hex = tor_malloc(HEX_DIGEST_LEN+1);
1579 base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
1580 smartlist_add(which, hex);
1582 } else {
1583 /* XXXX Can we even end up here? -- weasel*/
1584 source = NS_FROM_DIR_BY_FP;
1585 log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
1586 "for it by fp, nor did we ask for all.");
1588 cp = body;
1589 while (*cp) {
1590 char *next = strstr(cp, "\nnetwork-status-version");
1591 if (next)
1592 next[1] = '\0';
1593 /* learn from it, and then remove it from 'which' */
1594 if (router_set_networkstatus_v2(cp, now, source, which)<0)
1595 break;
1596 if (next) {
1597 next[1] = 'n';
1598 cp = next+1;
1599 } else
1600 break;
1602 /* launches router downloads as needed */
1603 routers_update_all_from_networkstatus(now, 2);
1604 directory_info_has_arrived(now, 0);
1605 if (which) {
1606 if (smartlist_len(which)) {
1607 dir_networkstatus_download_failed(which, status_code);
1609 SMARTLIST_FOREACH(which, char *, s, tor_free(s));
1610 smartlist_free(which);
1614 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
1615 int r;
1616 if (status_code != 200) {
1617 int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
1618 log(severity, LD_DIR,
1619 "Received http status code %d (%s) from server "
1620 "'%s:%d' while fetching consensus directory.",
1621 status_code, escaped(reason), conn->_base.address,
1622 conn->_base.port);
1623 tor_free(body); tor_free(headers); tor_free(reason);
1624 networkstatus_consensus_download_failed(status_code);
1625 return -1;
1627 log_info(LD_DIR,"Received consensus directory (size %d) from server "
1628 "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
1629 if ((r=networkstatus_set_current_consensus(body, "ns", 0))<0) {
1630 log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
1631 "Unable to load consensus directory downloaded from "
1632 "server '%s:%d'. I'll try again soon.",
1633 conn->_base.address, conn->_base.port);
1634 tor_free(body); tor_free(headers); tor_free(reason);
1635 networkstatus_consensus_download_failed(0);
1636 return -1;
1638 /* launches router downloads as needed */
1639 routers_update_all_from_networkstatus(now, 3);
1640 directory_info_has_arrived(now, 0);
1641 log_info(LD_DIR, "Successfully loaded consensus.");
1644 if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
1645 if (status_code != 200) {
1646 log_warn(LD_DIR,
1647 "Received http status code %d (%s) from server "
1648 "'%s:%d' while fetching \"/tor/keys/%s\".",
1649 status_code, escaped(reason), conn->_base.address,
1650 conn->_base.port, conn->requested_resource);
1651 connection_dir_download_cert_failed(conn, status_code);
1652 tor_free(body); tor_free(headers); tor_free(reason);
1653 return -1;
1655 log_info(LD_DIR,"Received authority certificates (size %d) from server "
1656 "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
1657 if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) {
1658 log_warn(LD_DIR, "Unable to parse fetched certificates");
1659 /* if we fetched more than one and only some failed, the successful
1660 * ones got flushed to disk so it's safe to call this on them */
1661 connection_dir_download_cert_failed(conn, status_code);
1662 } else {
1663 directory_info_has_arrived(now, 0);
1664 log_info(LD_DIR, "Successfully loaded certificates from fetch.");
1667 if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
1668 const char *msg;
1669 int st;
1670 log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
1671 (int)body_len, conn->_base.address, conn->_base.port);
1672 if (status_code != 200) {
1673 log_warn(LD_DIR,
1674 "Received http status code %d (%s) from server "
1675 "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
1676 status_code, escaped(reason), conn->_base.address,
1677 conn->_base.port, conn->requested_resource);
1678 tor_free(body); tor_free(headers); tor_free(reason);
1679 return -1;
1681 dirvote_add_vote(body, &msg, &st);
1682 if (st > 299) {
1683 log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
1684 } else {
1685 log_info(LD_DIR, "Added vote(s) successfully [msg: %s]", msg);
1688 if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
1689 const char *msg = NULL;
1690 log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
1691 (int)body_len, conn->_base.address, conn->_base.port);
1692 if (status_code != 200) {
1693 log_warn(LD_DIR,
1694 "Received http status code %d (%s) from server '%s:%d' while fetching "
1695 "\"/tor/status-vote/next/consensus-signatures.z\".",
1696 status_code, escaped(reason), conn->_base.address,
1697 conn->_base.port);
1698 tor_free(body); tor_free(headers); tor_free(reason);
1699 return -1;
1701 if (dirvote_add_signatures(body, conn->_base.address, &msg)<0) {
1702 log_warn(LD_DIR, "Problem adding detached signatures from %s:%d: %s",
1703 conn->_base.address, conn->_base.port, msg?msg:"???");
1707 if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
1708 conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
1709 int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
1710 smartlist_t *which = NULL;
1711 int n_asked_for = 0;
1712 int descriptor_digests = conn->requested_resource &&
1713 !strcmpstart(conn->requested_resource,"d/");
1714 log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
1715 was_ei ? "extra server info" : "server info",
1716 (int)body_len, conn->_base.address, conn->_base.port);
1717 if (conn->requested_resource &&
1718 (!strcmpstart(conn->requested_resource,"d/") ||
1719 !strcmpstart(conn->requested_resource,"fp/"))) {
1720 which = smartlist_create();
1721 dir_split_resource_into_fingerprints(conn->requested_resource +
1722 (descriptor_digests ? 2 : 3),
1723 which, NULL, 0);
1724 n_asked_for = smartlist_len(which);
1726 if (status_code != 200) {
1727 int dir_okay = status_code == 404 ||
1728 (status_code == 400 && !strcmp(reason, "Servers unavailable."));
1729 /* 404 means that it didn't have them; no big deal.
1730 * Older (pre-0.1.1.8) servers said 400 Servers unavailable instead. */
1731 log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
1732 "Received http status code %d (%s) from server '%s:%d' "
1733 "while fetching \"/tor/server/%s\". I'll try again soon.",
1734 status_code, escaped(reason), conn->_base.address,
1735 conn->_base.port, conn->requested_resource);
1736 if (!which) {
1737 connection_dir_download_routerdesc_failed(conn);
1738 } else {
1739 dir_routerdesc_download_failed(which, status_code,
1740 conn->router_purpose,
1741 was_ei, descriptor_digests);
1742 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1743 smartlist_free(which);
1745 tor_free(body); tor_free(headers); tor_free(reason);
1746 return dir_okay ? 0 : -1;
1748 /* Learn the routers, assuming we requested by fingerprint or "all"
1749 * or "authority".
1751 * We use "authority" to fetch our own descriptor for
1752 * testing, and to fetch bridge descriptors for bootstrapping. Ignore
1753 * the output of "authority" requests unless we are using bridges,
1754 * since otherwise they'll be the response from reachability tests,
1755 * and we don't really want to add that to our routerlist. */
1756 if (which || (conn->requested_resource &&
1757 (!strcmpstart(conn->requested_resource, "all") ||
1758 (!strcmpstart(conn->requested_resource, "authority") &&
1759 get_options()->UseBridges)))) {
1760 /* as we learn from them, we remove them from 'which' */
1761 if (was_ei) {
1762 router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
1763 descriptor_digests);
1764 } else {
1765 //router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
1766 // descriptor_digests, conn->router_purpose);
1767 if (load_downloaded_routers(body, which, descriptor_digests,
1768 conn->router_purpose,
1769 conn->_base.address))
1770 directory_info_has_arrived(now, 0);
1773 if (which) { /* mark remaining ones as failed */
1774 log_info(LD_DIR, "Received %d/%d %s requested from %s:%d",
1775 n_asked_for-smartlist_len(which), n_asked_for,
1776 was_ei ? "extra-info documents" : "router descriptors",
1777 conn->_base.address, (int)conn->_base.port);
1778 if (smartlist_len(which)) {
1779 dir_routerdesc_download_failed(which, status_code,
1780 conn->router_purpose,
1781 was_ei, descriptor_digests);
1783 SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
1784 smartlist_free(which);
1786 if (directory_conn_is_self_reachability_test(conn))
1787 router_dirport_found_reachable();
1790 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
1791 switch (status_code) {
1792 case 200: {
1793 trusted_dir_server_t *ds =
1794 router_get_trusteddirserver_by_digest(conn->identity_digest);
1795 char *rejected_hdr = http_get_header(headers,
1796 "X-Descriptor-Not-New: ");
1797 int rejected = 0;
1798 if (rejected_hdr) {
1799 if (!strcmp(rejected_hdr, "Yes")) {
1800 log_info(LD_GENERAL,
1801 "Authority '%s' declined our descriptor (not new)",
1802 ds->nickname);
1803 /* XXXX use this information; be sure to upload next one
1804 * sooner. -NM */
1805 /* XXXX021 On further thought, the task above implies that we're
1806 * basing our regenerate-descriptor time on when we uploaded the
1807 * last descriptor, not on the published time of the last
1808 * descriptor. If those are different, that's a bad thing to
1809 * do. -NM */
1810 rejected = 1;
1812 tor_free(rejected_hdr);
1814 log_info(LD_GENERAL,"eof (status 200) after uploading server "
1815 "descriptor: finished.");
1816 control_event_server_status(
1817 LOG_NOTICE, "ACCEPTED_SERVER_DESCRIPTOR DIRAUTH=%s:%d",
1818 conn->_base.address, conn->_base.port);
1820 ds->has_accepted_serverdesc = 1;
1821 if (directories_have_accepted_server_descriptor())
1822 control_event_server_status(LOG_NOTICE, "GOOD_SERVER_DESCRIPTOR");
1824 break;
1825 case 400:
1826 log_warn(LD_GENERAL,"http status 400 (%s) response from "
1827 "dirserver '%s:%d'. Please correct.",
1828 escaped(reason), conn->_base.address, conn->_base.port);
1829 control_event_server_status(LOG_WARN,
1830 "BAD_SERVER_DESCRIPTOR DIRAUTH=%s:%d REASON=\"%s\"",
1831 conn->_base.address, conn->_base.port, escaped(reason));
1832 break;
1833 default:
1834 log_warn(LD_GENERAL,
1835 "http status %d (%s) reason unexpected while uploading "
1836 "descriptor to server '%s:%d').",
1837 status_code, escaped(reason), conn->_base.address,
1838 conn->_base.port);
1839 break;
1841 /* return 0 in all cases, since we don't want to mark any
1842 * dirservers down just because they don't like us. */
1845 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
1846 switch (status_code) {
1847 case 200: {
1848 log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
1849 conn->_base.address, conn->_base.port);
1851 break;
1852 case 400:
1853 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1854 "vote to dirserver '%s:%d'. Please correct.",
1855 escaped(reason), conn->_base.address, conn->_base.port);
1856 break;
1857 default:
1858 log_warn(LD_GENERAL,
1859 "http status %d (%s) reason unexpected while uploading "
1860 "vote to server '%s:%d').",
1861 status_code, escaped(reason), conn->_base.address,
1862 conn->_base.port);
1863 break;
1865 /* return 0 in all cases, since we don't want to mark any
1866 * dirservers down just because they don't like us. */
1869 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_SIGNATURES) {
1870 switch (status_code) {
1871 case 200: {
1872 log_notice(LD_DIR,"Uploaded signature(s) to dirserver %s:%d",
1873 conn->_base.address, conn->_base.port);
1875 break;
1876 case 400:
1877 log_warn(LD_DIR,"http status 400 (%s) response after uploading "
1878 "signatures to dirserver '%s:%d'. Please correct.",
1879 escaped(reason), conn->_base.address, conn->_base.port);
1880 break;
1881 default:
1882 log_warn(LD_GENERAL,
1883 "http status %d (%s) reason unexpected while uploading "
1884 "signatures to server '%s:%d').",
1885 status_code, escaped(reason), conn->_base.address,
1886 conn->_base.port);
1887 break;
1889 /* return 0 in all cases, since we don't want to mark any
1890 * dirservers down just because they don't like us. */
1893 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
1894 tor_assert(conn->rend_data);
1895 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1896 "(%s))",
1897 (int)body_len, status_code, escaped(reason));
1898 switch (status_code) {
1899 case 200:
1900 if (rend_cache_store(body, body_len, 0) < -1) {
1901 log_warn(LD_REND,"Failed to parse rendezvous descriptor.");
1902 /* Any pending rendezvous attempts will notice when
1903 * connection_about_to_close_connection()
1904 * cleans this dir conn up. */
1905 /* We could retry. But since v0 descriptors are going out of
1906 * style, it isn't worth the hassle. We'll do better in v2. */
1907 } else {
1908 /* Success, or at least there's a v2 descriptor already
1909 * present. Notify pending connections about this. */
1910 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1911 rend_client_desc_trynow(conn->rend_data->onion_address);
1913 break;
1914 case 404:
1915 /* Not there. Pending connections will be notified when
1916 * connection_about_to_close_connection() cleans this conn up. */
1917 break;
1918 case 400:
1919 log_warn(LD_REND,
1920 "http status 400 (%s). Dirserver didn't like our "
1921 "rendezvous query?", escaped(reason));
1922 break;
1923 default:
1924 log_warn(LD_REND,"http status %d (%s) response unexpected while "
1925 "fetching hidden service descriptor (server '%s:%d').",
1926 status_code, escaped(reason), conn->_base.address,
1927 conn->_base.port);
1928 break;
1932 if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
1933 tor_assert(conn->rend_data);
1934 log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
1935 "(%s))",
1936 (int)body_len, status_code, escaped(reason));
1937 switch (status_code) {
1938 case 200:
1939 switch (rend_cache_store_v2_desc_as_client(body, conn->rend_data)) {
1940 case -2:
1941 log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
1942 "Retrying at another directory.");
1943 /* We'll retry when connection_about_to_close_connection()
1944 * cleans this dir conn up. */
1945 break;
1946 case -1:
1947 /* We already have a v0 descriptor here. Ignoring this one
1948 * and _not_ performing another request. */
1949 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1950 "descriptor, but we already have a v0 descriptor.");
1951 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1952 break;
1953 default:
1954 /* success. notify pending connections about this. */
1955 log_info(LD_REND, "Successfully fetched v2 rendezvous "
1956 "descriptor.");
1957 conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
1958 rend_client_desc_trynow(conn->rend_data->onion_address);
1959 break;
1961 break;
1962 case 404:
1963 /* Not there. We'll retry when
1964 * connection_about_to_close_connection() cleans this conn up. */
1965 log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
1966 "Retrying at another directory.");
1967 break;
1968 case 400:
1969 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1970 "http status 400 (%s). Dirserver didn't like our "
1971 "v2 rendezvous query? Retrying at another directory.",
1972 escaped(reason));
1973 break;
1974 default:
1975 log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
1976 "http status %d (%s) response unexpected while "
1977 "fetching v2 hidden service descriptor (server '%s:%d'). "
1978 "Retrying at another directory.",
1979 status_code, escaped(reason), conn->_base.address,
1980 conn->_base.port);
1981 break;
1985 if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
1986 conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
1987 log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
1988 "(%s))",
1989 status_code, escaped(reason));
1990 switch (status_code) {
1991 case 200:
1992 log_info(LD_REND,
1993 "Uploading rendezvous descriptor: finished with status "
1994 "200 (%s)", escaped(reason));
1995 break;
1996 case 400:
1997 log_warn(LD_REND,"http status 400 (%s) response from dirserver "
1998 "'%s:%d'. Malformed rendezvous descriptor?",
1999 escaped(reason), conn->_base.address, conn->_base.port);
2000 break;
2001 default:
2002 log_warn(LD_REND,"http status %d (%s) response unexpected (server "
2003 "'%s:%d').",
2004 status_code, escaped(reason), conn->_base.address,
2005 conn->_base.port);
2006 break;
2009 note_client_request(conn->_base.purpose, was_compressed, orig_len);
2010 tor_free(body); tor_free(headers); tor_free(reason);
2011 return 0;
2014 /** Called when a directory connection reaches EOF. */
2016 connection_dir_reached_eof(dir_connection_t *conn)
2018 int retval;
2019 if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
2020 log_info(LD_HTTP,"conn reached eof, not reading. [state=%d] Closing.",
2021 conn->_base.state);
2022 connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
2023 connection_mark_for_close(TO_CONN(conn));
2024 return -1;
2027 retval = connection_dir_client_reached_eof(conn);
2028 if (retval == 0) /* success */
2029 conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
2030 connection_mark_for_close(TO_CONN(conn));
2031 return retval;
2034 /** If any directory object is arriving, and it's over 10MB large, we're
2035 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
2036 * ask for more than 96 router descriptors at a time.)
2038 #define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
2040 /** Read handler for directory connections. (That's connections <em>to</em>
2041 * directory servers and connections <em>at</em> directory servers.)
2044 connection_dir_process_inbuf(dir_connection_t *conn)
2046 tor_assert(conn);
2047 tor_assert(conn->_base.type == CONN_TYPE_DIR);
2049 /* Directory clients write, then read data until they receive EOF;
2050 * directory servers read data until they get an HTTP command, then
2051 * write their response (when it's finished flushing, they mark for
2052 * close).
2055 /* If we're on the dirserver side, look for a command. */
2056 if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
2057 if (directory_handle_command(conn) < 0) {
2058 connection_mark_for_close(TO_CONN(conn));
2059 return -1;
2061 return 0;
2064 if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
2065 log_warn(LD_HTTP, "Too much data received from directory connection: "
2066 "denial of service attempt, or you need to upgrade?");
2067 connection_mark_for_close(TO_CONN(conn));
2068 return -1;
2071 if (!conn->_base.inbuf_reached_eof)
2072 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
2073 return 0;
2076 /** Create an http response for the client <b>conn</b> out of
2077 * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
2079 static void
2080 write_http_status_line(dir_connection_t *conn, int status,
2081 const char *reason_phrase)
2083 char buf[256];
2084 if (tor_snprintf(buf, sizeof(buf), "HTTP/1.0 %d %s\r\n\r\n",
2085 status, reason_phrase ? reason_phrase : "OK") < 0) {
2086 log_warn(LD_BUG,"status line too long.");
2087 return;
2089 connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
2092 /** Write the header for an HTTP/1.0 response onto <b>conn</b>-\>outbuf,
2093 * with <b>type</b> as the Content-Type.
2095 * If <b>length</b> is nonnegative, it is the Content-Length.
2096 * If <b>encoding</b> is provided, it is the Content-Encoding.
2097 * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
2098 * up to cache_lifetime seconds. Otherwise, the content may not be cached. */
2099 static void
2100 write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
2101 const char *type, const char *encoding,
2102 const char *extra_headers,
2103 long cache_lifetime)
2105 char date[RFC1123_TIME_LEN+1];
2106 char tmp[1024];
2107 char *cp;
2108 time_t now = time(NULL);
2110 tor_assert(conn);
2112 format_rfc1123_time(date, now);
2113 cp = tmp;
2114 tor_snprintf(cp, sizeof(tmp),
2115 "HTTP/1.0 200 OK\r\nDate: %s\r\n",
2116 date);
2117 cp += strlen(tmp);
2118 if (type) {
2119 tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
2120 cp += strlen(cp);
2122 if (!is_local_addr(&conn->_base.addr)) {
2123 /* Don't report the source address for a nearby/private connection.
2124 * Otherwise we tend to mis-report in cases where incoming ports are
2125 * being forwarded to a Tor server running behind the firewall. */
2126 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2127 X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
2128 cp += strlen(cp);
2130 if (encoding) {
2131 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2132 "Content-Encoding: %s\r\n", encoding);
2133 cp += strlen(cp);
2135 if (length >= 0) {
2136 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2137 "Content-Length: %ld\r\n", (long)length);
2138 cp += strlen(cp);
2140 if (cache_lifetime > 0) {
2141 char expbuf[RFC1123_TIME_LEN+1];
2142 format_rfc1123_time(expbuf, now + cache_lifetime);
2143 /* We could say 'Cache-control: max-age=%d' here if we start doing
2144 * http/1.1 */
2145 tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
2146 "Expires: %s\r\n", expbuf);
2147 cp += strlen(cp);
2148 } else if (cache_lifetime == 0) {
2149 /* We could say 'Cache-control: no-cache' here if we start doing
2150 * http/1.1 */
2151 strlcpy(cp, "Pragma: no-cache\r\n", sizeof(tmp)-(cp-tmp));
2152 cp += strlen(cp);
2154 if (extra_headers) {
2155 strlcpy(cp, extra_headers, sizeof(tmp)-(cp-tmp));
2156 cp += strlen(cp);
2158 if (sizeof(tmp)-(cp-tmp) > 3)
2159 memcpy(cp, "\r\n", 3);
2160 else
2161 tor_assert(0);
2162 connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
2165 /** As write_http_response_header_impl, but sets encoding and content-typed
2166 * based on whether the response will be <b>compressed</b> or not. */
2167 static void
2168 write_http_response_header(dir_connection_t *conn, ssize_t length,
2169 int compressed, long cache_lifetime)
2171 write_http_response_header_impl(conn, length,
2172 compressed?"application/octet-stream":"text/plain",
2173 compressed?"deflate":"identity",
2174 NULL,
2175 cache_lifetime);
2178 #ifdef INSTRUMENT_DOWNLOADS
2179 typedef struct request_t {
2180 uint64_t bytes; /**< How many bytes have we transferred? */
2181 uint64_t count; /**< How many requests have we made? */
2182 } request_t;
2184 /** Map used to keep track of how much data we've up/downloaded in what kind
2185 * of request. Maps from request type to pointer to request_t. */
2186 static strmap_t *request_map = NULL;
2188 /** Record that a client request of <b>purpose</b> was made, and that
2189 * <b>bytes</b> bytes of possibly <b>compressed</b> data were sent/received.
2190 * Used to keep track of how much we've up/downloaded in what kind of
2191 * request. */
2192 static void
2193 note_client_request(int purpose, int compressed, size_t bytes)
2195 char *key;
2196 const char *kind = NULL;
2197 switch (purpose) {
2198 case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS: kind = "dl/status"; break;
2199 case DIR_PURPOSE_FETCH_CONSENSUS: kind = "dl/consensus"; break;
2200 case DIR_PURPOSE_FETCH_CERTIFICATE: kind = "dl/cert"; break;
2201 case DIR_PURPOSE_FETCH_STATUS_VOTE: kind = "dl/vote"; break;
2202 case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: kind = "dl/detached_sig";
2203 break;
2204 case DIR_PURPOSE_FETCH_SERVERDESC: kind = "dl/server"; break;
2205 case DIR_PURPOSE_FETCH_EXTRAINFO: kind = "dl/extra"; break;
2206 case DIR_PURPOSE_UPLOAD_DIR: kind = "dl/ul-dir"; break;
2207 case DIR_PURPOSE_UPLOAD_VOTE: kind = "dl/ul-vote"; break;
2208 case DIR_PURPOSE_UPLOAD_SIGNATURES: kind = "dl/ul-sig"; break;
2209 case DIR_PURPOSE_FETCH_RENDDESC: kind = "dl/rend"; break;
2210 case DIR_PURPOSE_FETCH_RENDDESC_V2: kind = "dl/rend2"; break;
2211 case DIR_PURPOSE_UPLOAD_RENDDESC: kind = "dl/ul-rend"; break;
2212 case DIR_PURPOSE_UPLOAD_RENDDESC_V2: kind = "dl/ul-rend2"; break;
2214 if (kind) {
2215 key = tor_malloc(256);
2216 tor_snprintf(key, 256, "%s%s", kind, compressed?".z":"");
2217 } else {
2218 key = tor_malloc(256);
2219 tor_snprintf(key, 256, "unknown purpose (%d)%s",
2220 purpose, compressed?".z":"");
2222 note_request(key, bytes);
2223 tor_free(key);
2226 /** Helper: initialize the request map to instrument downloads. */
2227 static void
2228 ensure_request_map_initialized(void)
2230 if (!request_map)
2231 request_map = strmap_new();
2234 /** Called when we just transmitted or received <b>bytes</b> worth of data
2235 * because of a request of type <b>key</b> (an arbitrary identifier): adds
2236 * <b>bytes</b> to the total associated with key. */
2237 void
2238 note_request(const char *key, size_t bytes)
2240 request_t *r;
2241 ensure_request_map_initialized();
2243 r = strmap_get(request_map, key);
2244 if (!r) {
2245 r = tor_malloc_zero(sizeof(request_t));
2246 strmap_set(request_map, key, r);
2248 r->bytes += bytes;
2249 r->count++;
2252 /** Return a newly allocated string holding a summary of bytes used per
2253 * request type. */
2254 char *
2255 directory_dump_request_log(void)
2257 smartlist_t *lines;
2258 char tmp[256];
2259 char *result;
2260 strmap_iter_t *iter;
2262 ensure_request_map_initialized();
2264 lines = smartlist_create();
2266 for (iter = strmap_iter_init(request_map);
2267 !strmap_iter_done(iter);
2268 iter = strmap_iter_next(request_map, iter)) {
2269 const char *key;
2270 void *val;
2271 request_t *r;
2272 strmap_iter_get(iter, &key, &val);
2273 r = val;
2274 tor_snprintf(tmp, sizeof(tmp), "%s "U64_FORMAT" "U64_FORMAT"\n",
2275 key, U64_PRINTF_ARG(r->bytes), U64_PRINTF_ARG(r->count));
2276 smartlist_add(lines, tor_strdup(tmp));
2278 smartlist_sort_strings(lines);
2279 result = smartlist_join_strings(lines, "", 0, NULL);
2280 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
2281 smartlist_free(lines);
2282 return result;
2284 #else
2285 static void
2286 note_client_request(int purpose, int compressed, size_t bytes)
2288 (void)purpose;
2289 (void)compressed;
2290 (void)bytes;
2293 void
2294 note_request(const char *key, size_t bytes)
2296 (void)key;
2297 (void)bytes;
2300 char *
2301 directory_dump_request_log(void)
2303 return tor_strdup("Not supported.");
2305 #endif
2307 /** Decide whether a client would accept the consensus we have.
2309 * Clients can say they only want a consensus if it's signed by more
2310 * than half the authorities in a list. They pass this list in
2311 * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
2313 * <b>fpr</b> may be an abbreviated fingerprint, i.e. only a left substring
2314 * of the full authority identity digest. (Only strings of even length,
2315 * i.e. encodings of full bytes, are handled correctly. In the case
2316 * of an odd number of hex digits the last one is silently ignored.)
2318 * Returns 1 if more than half of the requested authorities signed the
2319 * consensus, 0 otherwise.
2322 client_likes_consensus(networkstatus_t *v, const char *want_url)
2324 smartlist_t *want_authorities = smartlist_create();
2325 int need_at_least;
2326 int have = 0;
2328 dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0);
2329 need_at_least = smartlist_len(want_authorities)/2+1;
2330 SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, d) {
2331 char want_digest[DIGEST_LEN];
2332 size_t want_len = strlen(d)/2;
2333 if (want_len > DIGEST_LEN)
2334 want_len = DIGEST_LEN;
2336 if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) {
2337 log_warn(LD_DIR,"Failed to decode requested authority digest %s.", d);
2338 continue;
2341 SMARTLIST_FOREACH_BEGIN(v->voters, networkstatus_voter_info_t *, vi) {
2342 if (smartlist_len(vi->sigs) &&
2343 !memcmp(vi->identity_digest, want_digest, want_len)) {
2344 have++;
2345 break;
2347 } SMARTLIST_FOREACH_END(vi);
2349 /* early exit, if we already have enough */
2350 if (have >= need_at_least)
2351 break;
2352 } SMARTLIST_FOREACH_END(d);
2354 SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
2355 smartlist_free(want_authorities);
2356 return (have >= need_at_least);
2359 /** Helper function: called when a dirserver gets a complete HTTP GET
2360 * request. Look for a request for a directory or for a rendezvous
2361 * service descriptor. On finding one, write a response into
2362 * conn-\>outbuf. If the request is unrecognized, send a 400.
2363 * Always return 0. */
2364 static int
2365 directory_handle_command_get(dir_connection_t *conn, const char *headers,
2366 const char *body, size_t body_len)
2368 size_t dlen;
2369 char *url, *url_mem, *header;
2370 or_options_t *options = get_options();
2371 time_t if_modified_since = 0;
2372 int compressed;
2373 size_t url_len;
2375 /* We ignore the body of a GET request. */
2376 (void)body;
2377 (void)body_len;
2379 log_debug(LD_DIRSERV,"Received GET command.");
2381 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
2383 if (parse_http_url(headers, &url) < 0) {
2384 write_http_status_line(conn, 400, "Bad request");
2385 return 0;
2387 if ((header = http_get_header(headers, "If-Modified-Since: "))) {
2388 struct tm tm;
2389 if (parse_http_time(header, &tm) == 0) {
2390 if_modified_since = tor_timegm(&tm);
2392 /* The correct behavior on a malformed If-Modified-Since header is to
2393 * act as if no If-Modified-Since header had been given. */
2394 tor_free(header);
2396 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
2398 url_mem = url;
2399 url_len = strlen(url);
2400 compressed = url_len > 2 && !strcmp(url+url_len-2, ".z");
2401 if (compressed) {
2402 url[url_len-2] = '\0';
2403 url_len -= 2;
2406 if (!strcmp(url,"/tor/")) {
2407 const char *frontpage = get_dirportfrontpage();
2409 if (frontpage) {
2410 dlen = strlen(frontpage);
2411 /* Let's return a disclaimer page (users shouldn't use V1 anymore,
2412 and caches don't fetch '/', so this is safe). */
2414 /* [We don't check for write_bucket_low here, since we want to serve
2415 * this page no matter what.] */
2416 note_request(url, dlen);
2417 write_http_response_header_impl(conn, dlen, "text/html", "identity",
2418 NULL, DIRPORTFRONTPAGE_CACHE_LIFETIME);
2419 connection_write_to_buf(frontpage, dlen, TO_CONN(conn));
2420 goto done;
2422 /* if no disclaimer file, fall through and continue */
2425 if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* v1 dir fetch */
2426 cached_dir_t *d = dirserv_get_directory();
2428 if (!d) {
2429 log_info(LD_DIRSERV,"Client asked for the mirrored directory, but we "
2430 "don't have a good one yet. Sending 503 Dir not available.");
2431 write_http_status_line(conn, 503, "Directory unavailable");
2432 goto done;
2434 if (d->published < if_modified_since) {
2435 write_http_status_line(conn, 304, "Not modified");
2436 goto done;
2439 dlen = compressed ? d->dir_z_len : d->dir_len;
2441 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2442 log_debug(LD_DIRSERV,
2443 "Client asked for the mirrored directory, but we've been "
2444 "writing too many bytes lately. Sending 503 Dir busy.");
2445 write_http_status_line(conn, 503, "Directory busy, try again later");
2446 goto done;
2449 note_request(url, dlen);
2451 log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
2452 compressed?"compressed ":"");
2453 write_http_response_header(conn, dlen, compressed,
2454 FULL_DIR_CACHE_LIFETIME);
2455 conn->cached_dir = d;
2456 conn->cached_dir_offset = 0;
2457 if (!compressed)
2458 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2459 ++d->refcnt;
2461 /* Prime the connection with some data. */
2462 conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
2463 connection_dirserv_flushed_some(conn);
2464 goto done;
2467 if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
2468 cached_dir_t *d = dirserv_get_runningrouters();
2469 if (!d) {
2470 write_http_status_line(conn, 503, "Directory unavailable");
2471 goto done;
2473 if (d->published < if_modified_since) {
2474 write_http_status_line(conn, 304, "Not modified");
2475 goto done;
2477 dlen = compressed ? d->dir_z_len : d->dir_len;
2479 if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
2480 log_info(LD_DIRSERV,
2481 "Client asked for running-routers, but we've been "
2482 "writing too many bytes lately. Sending 503 Dir busy.");
2483 write_http_status_line(conn, 503, "Directory busy, try again later");
2484 goto done;
2486 note_request(url, dlen);
2487 write_http_response_header(conn, dlen, compressed,
2488 RUNNINGROUTERS_CACHE_LIFETIME);
2489 connection_write_to_buf(compressed ? d->dir_z : d->dir, dlen,
2490 TO_CONN(conn));
2491 goto done;
2494 if (!strcmpstart(url,"/tor/status/")
2495 || !strcmpstart(url, "/tor/status-vote/current/consensus")) {
2496 /* v2 or v3 network status fetch. */
2497 smartlist_t *dir_fps = smartlist_create();
2498 int is_v3 = !strcmpstart(url, "/tor/status-vote");
2499 geoip_client_action_t act =
2500 is_v3 ? GEOIP_CLIENT_NETWORKSTATUS : GEOIP_CLIENT_NETWORKSTATUS_V2;
2501 const char *request_type = NULL;
2502 const char *key = url + strlen("/tor/status/");
2503 long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
2505 if (!is_v3) {
2506 dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
2507 if (!strcmpstart(key, "fp/"))
2508 request_type = compressed?"/tor/status/fp.z":"/tor/status/fp";
2509 else if (!strcmpstart(key, "authority"))
2510 request_type = compressed?"/tor/status/authority.z":
2511 "/tor/status/authority";
2512 else if (!strcmpstart(key, "all"))
2513 request_type = compressed?"/tor/status/all.z":"/tor/status/all";
2514 else
2515 request_type = "/tor/status/?";
2516 } else {
2517 networkstatus_t *v = networkstatus_get_latest_consensus();
2518 time_t now = time(NULL);
2519 const char *want_fps = NULL;
2520 char *flavor = NULL;
2521 #define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/"
2522 #define CONSENSUS_FLAVORED_PREFIX "/tor/status-vote/current/consensus-"
2523 /* figure out the flavor if any, and who we wanted to sign the thing */
2524 if (!strcmpstart(url, CONSENSUS_FLAVORED_PREFIX)) {
2525 const char *f, *cp;
2526 f = url + strlen(CONSENSUS_FLAVORED_PREFIX);
2527 cp = strchr(f, '/');
2528 if (cp) {
2529 want_fps = cp+1;
2530 flavor = tor_strndup(f, cp-f);
2531 } else {
2532 flavor = tor_strdup(f);
2534 } else {
2535 if (!strcmpstart(url, CONSENSUS_URL_PREFIX))
2536 want_fps = url+strlen(CONSENSUS_URL_PREFIX);
2539 /* XXXX MICRODESC NM NM should check document of correct flavor */
2540 if (v && want_fps &&
2541 !client_likes_consensus(v, want_fps)) {
2542 write_http_status_line(conn, 404, "Consensus not signed by sufficient "
2543 "number of requested authorities");
2544 smartlist_free(dir_fps);
2545 geoip_note_ns_response(act, GEOIP_REJECT_NOT_ENOUGH_SIGS);
2546 tor_free(flavor);
2547 goto done;
2551 char *fp = tor_malloc_zero(DIGEST_LEN);
2552 if (flavor)
2553 strlcpy(fp, flavor, DIGEST_LEN);
2554 tor_free(flavor);
2555 smartlist_add(dir_fps, fp);
2557 request_type = compressed?"v3.z":"v3";
2558 lifetime = (v && v->fresh_until > now) ? v->fresh_until - now : 0;
2561 if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
2562 write_http_status_line(conn, 503, "Network status object unavailable");
2563 smartlist_free(dir_fps);
2564 geoip_note_ns_response(act, GEOIP_REJECT_UNAVAILABLE);
2565 goto done;
2568 if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
2569 write_http_status_line(conn, 404, "Not found");
2570 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2571 smartlist_free(dir_fps);
2572 geoip_note_ns_response(act, GEOIP_REJECT_NOT_FOUND);
2573 goto done;
2574 } else if (!smartlist_len(dir_fps)) {
2575 write_http_status_line(conn, 304, "Not modified");
2576 SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
2577 smartlist_free(dir_fps);
2578 geoip_note_ns_response(act, GEOIP_REJECT_NOT_MODIFIED);
2579 goto done;
2582 dlen = dirserv_estimate_data_size(dir_fps, 0, compressed);
2583 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2584 log_debug(LD_DIRSERV,
2585 "Client asked for network status lists, but we've been "
2586 "writing too many bytes lately. Sending 503 Dir busy.");
2587 write_http_status_line(conn, 503, "Directory busy, try again later");
2588 SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
2589 smartlist_free(dir_fps);
2590 geoip_note_ns_response(act, GEOIP_REJECT_BUSY);
2591 goto done;
2595 struct in_addr in;
2596 if (tor_inet_aton((TO_CONN(conn))->address, &in)) {
2597 geoip_note_client_seen(act, ntohl(in.s_addr), time(NULL));
2598 geoip_note_ns_response(act, GEOIP_SUCCESS);
2599 /* Note that a request for a network status has started, so that we
2600 * can measure the download time later on. */
2601 if (TO_CONN(conn)->dirreq_id)
2602 geoip_start_dirreq(TO_CONN(conn)->dirreq_id, dlen, act,
2603 DIRREQ_TUNNELED);
2604 else
2605 geoip_start_dirreq(TO_CONN(conn)->global_identifier, dlen, act,
2606 DIRREQ_DIRECT);
2610 // note_request(request_type,dlen);
2611 (void) request_type;
2612 write_http_response_header(conn, -1, compressed,
2613 smartlist_len(dir_fps) == 1 ? lifetime : 0);
2614 conn->fingerprint_stack = dir_fps;
2615 if (! compressed)
2616 conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
2618 /* Prime the connection with some data. */
2619 conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
2620 connection_dirserv_flushed_some(conn);
2621 goto done;
2624 if (!strcmpstart(url,"/tor/status-vote/current/") ||
2625 !strcmpstart(url,"/tor/status-vote/next/")) {
2626 /* XXXX If-modified-since is only implemented for the current
2627 * consensus: that's probably fine, since it's the only vote document
2628 * people fetch much. */
2629 int current;
2630 ssize_t body_len = 0;
2631 ssize_t estimated_len = 0;
2632 smartlist_t *items = smartlist_create();
2633 smartlist_t *dir_items = smartlist_create();
2634 int lifetime = 60; /* XXXX022 should actually use vote intervals. */
2635 url += strlen("/tor/status-vote/");
2636 current = !strcmpstart(url, "current/");
2637 url = strchr(url, '/');
2638 tor_assert(url);
2639 ++url;
2640 if (!strcmp(url, "consensus")) {
2641 const char *item;
2642 tor_assert(!current); /* we handle current consensus specially above,
2643 * since it wants to be spooled. */
2644 if ((item = dirvote_get_pending_consensus(FLAV_NS)))
2645 smartlist_add(items, (char*)item);
2646 } else if (!current && !strcmp(url, "consensus-signatures")) {
2647 /* XXXX the spec says that we should implement
2648 * current/consensus-signatures too. It doesn't seem to be needed,
2649 * though. */
2650 const char *item;
2651 if ((item=dirvote_get_pending_detached_signatures()))
2652 smartlist_add(items, (char*)item);
2653 } else if (!strcmp(url, "authority")) {
2654 const cached_dir_t *d;
2655 int flags = DGV_BY_ID |
2656 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2657 if ((d=dirvote_get_vote(NULL, flags)))
2658 smartlist_add(dir_items, (cached_dir_t*)d);
2659 } else {
2660 const cached_dir_t *d;
2661 smartlist_t *fps = smartlist_create();
2662 int flags;
2663 if (!strcmpstart(url, "d/")) {
2664 url += 2;
2665 flags = DGV_INCLUDE_PENDING | DGV_INCLUDE_PREVIOUS;
2666 } else {
2667 flags = DGV_BY_ID |
2668 (current ? DGV_INCLUDE_PREVIOUS : DGV_INCLUDE_PENDING);
2670 dir_split_resource_into_fingerprints(url, fps, NULL,
2671 DSR_HEX|DSR_SORT_UNIQ);
2672 SMARTLIST_FOREACH(fps, char *, fp, {
2673 if ((d = dirvote_get_vote(fp, flags)))
2674 smartlist_add(dir_items, (cached_dir_t*)d);
2675 tor_free(fp);
2677 smartlist_free(fps);
2679 if (!smartlist_len(dir_items) && !smartlist_len(items)) {
2680 write_http_status_line(conn, 404, "Not found");
2681 goto vote_done;
2683 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2684 body_len += compressed ? d->dir_z_len : d->dir_len);
2685 estimated_len += body_len;
2686 SMARTLIST_FOREACH(items, const char *, item, {
2687 size_t ln = strlen(item);
2688 if (compressed) {
2689 estimated_len += ln/2;
2690 } else {
2691 body_len += ln; estimated_len += ln;
2695 if (global_write_bucket_low(TO_CONN(conn), estimated_len, 2)) {
2696 write_http_status_line(conn, 503, "Directory busy, try again later.");
2697 goto vote_done;
2699 write_http_response_header(conn, body_len ? body_len : -1, compressed,
2700 lifetime);
2702 if (smartlist_len(items)) {
2703 if (compressed) {
2704 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2705 SMARTLIST_FOREACH(items, const char *, c,
2706 connection_write_to_buf_zlib(c, strlen(c), conn, 0));
2707 connection_write_to_buf_zlib("", 0, conn, 1);
2708 } else {
2709 SMARTLIST_FOREACH(items, const char *, c,
2710 connection_write_to_buf(c, strlen(c), TO_CONN(conn)));
2712 } else {
2713 SMARTLIST_FOREACH(dir_items, cached_dir_t *, d,
2714 connection_write_to_buf(compressed ? d->dir_z : d->dir,
2715 compressed ? d->dir_z_len : d->dir_len,
2716 TO_CONN(conn)));
2718 vote_done:
2719 smartlist_free(items);
2720 smartlist_free(dir_items);
2721 goto done;
2724 if (!strcmpstart(url, "/tor/micro/d/")) {
2725 smartlist_t *fps = smartlist_create();
2727 dir_split_resource_into_fingerprints(url+strlen("/tor/micro/d/"),
2728 fps, NULL,
2729 DSR_DIGEST256|DSR_BASE64|DSR_SORT_UNIQ);
2731 if (!dirserv_have_any_microdesc(fps)) {
2732 write_http_status_line(conn, 404, "Not found");
2733 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
2734 smartlist_free(fps);
2735 goto done;
2737 dlen = dirserv_estimate_microdesc_size(fps, compressed);
2738 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2739 log_info(LD_DIRSERV,
2740 "Client asked for server descriptors, but we've been "
2741 "writing too many bytes lately. Sending 503 Dir busy.");
2742 write_http_status_line(conn, 503, "Directory busy, try again later");
2743 SMARTLIST_FOREACH(fps, char *, fp, tor_free(fp));
2744 smartlist_free(fps);
2745 goto done;
2748 write_http_response_header(conn, -1, compressed, MICRODESC_CACHE_LIFETIME);
2749 conn->dir_spool_src = DIR_SPOOL_MICRODESC;
2750 conn->fingerprint_stack = fps;
2752 if (compressed)
2753 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2755 connection_dirserv_flushed_some(conn);
2756 goto done;
2759 if (!strcmpstart(url,"/tor/server/") ||
2760 (!options->BridgeAuthoritativeDir &&
2761 !options->BridgeRelay && !strcmpstart(url,"/tor/extra/"))) {
2762 int res;
2763 const char *msg;
2764 const char *request_type = NULL;
2765 int cache_lifetime = 0;
2766 int is_extra = !strcmpstart(url,"/tor/extra/");
2767 url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
2768 conn->fingerprint_stack = smartlist_create();
2769 res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
2770 &msg,
2771 !connection_dir_is_encrypted(conn),
2772 is_extra);
2774 if (!strcmpstart(url, "fp/")) {
2775 request_type = compressed?"/tor/server/fp.z":"/tor/server/fp";
2776 if (smartlist_len(conn->fingerprint_stack) == 1)
2777 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2778 } else if (!strcmpstart(url, "authority")) {
2779 request_type = compressed?"/tor/server/authority.z":
2780 "/tor/server/authority";
2781 cache_lifetime = ROUTERDESC_CACHE_LIFETIME;
2782 } else if (!strcmpstart(url, "all")) {
2783 request_type = compressed?"/tor/server/all.z":"/tor/server/all";
2784 cache_lifetime = FULL_DIR_CACHE_LIFETIME;
2785 } else if (!strcmpstart(url, "d/")) {
2786 request_type = compressed?"/tor/server/d.z":"/tor/server/d";
2787 if (smartlist_len(conn->fingerprint_stack) == 1)
2788 cache_lifetime = ROUTERDESC_BY_DIGEST_CACHE_LIFETIME;
2789 } else {
2790 request_type = "/tor/server/?";
2792 (void) request_type; /* usable for note_request. */
2793 if (!strcmpstart(url, "d/"))
2794 conn->dir_spool_src =
2795 is_extra ? DIR_SPOOL_EXTRA_BY_DIGEST : DIR_SPOOL_SERVER_BY_DIGEST;
2796 else
2797 conn->dir_spool_src =
2798 is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
2800 if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
2801 conn->dir_spool_src)) {
2802 res = -1;
2803 msg = "Not found";
2806 if (res < 0)
2807 write_http_status_line(conn, 404, msg);
2808 else {
2809 dlen = dirserv_estimate_data_size(conn->fingerprint_stack,
2810 1, compressed);
2811 if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
2812 log_info(LD_DIRSERV,
2813 "Client asked for server descriptors, but we've been "
2814 "writing too many bytes lately. Sending 503 Dir busy.");
2815 write_http_status_line(conn, 503, "Directory busy, try again later");
2816 conn->dir_spool_src = DIR_SPOOL_NONE;
2817 goto done;
2819 write_http_response_header(conn, -1, compressed, cache_lifetime);
2820 if (compressed)
2821 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2822 /* Prime the connection with some data. */
2823 connection_dirserv_flushed_some(conn);
2825 goto done;
2828 if (!strcmpstart(url,"/tor/keys/")) {
2829 smartlist_t *certs = smartlist_create();
2830 ssize_t len = -1;
2831 if (!strcmp(url, "/tor/keys/all")) {
2832 authority_cert_get_all(certs);
2833 } else if (!strcmp(url, "/tor/keys/authority")) {
2834 authority_cert_t *cert = get_my_v3_authority_cert();
2835 if (cert)
2836 smartlist_add(certs, cert);
2837 } else if (!strcmpstart(url, "/tor/keys/fp/")) {
2838 smartlist_t *fps = smartlist_create();
2839 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/fp/"),
2840 fps, NULL,
2841 DSR_HEX|DSR_SORT_UNIQ);
2842 SMARTLIST_FOREACH(fps, char *, d, {
2843 authority_cert_t *c = authority_cert_get_newest_by_id(d);
2844 if (c) smartlist_add(certs, c);
2845 tor_free(d);
2847 smartlist_free(fps);
2848 } else if (!strcmpstart(url, "/tor/keys/sk/")) {
2849 smartlist_t *fps = smartlist_create();
2850 dir_split_resource_into_fingerprints(url+strlen("/tor/keys/sk/"),
2851 fps, NULL,
2852 DSR_HEX|DSR_SORT_UNIQ);
2853 SMARTLIST_FOREACH(fps, char *, d, {
2854 authority_cert_t *c = authority_cert_get_by_sk_digest(d);
2855 if (c) smartlist_add(certs, c);
2856 tor_free(d);
2858 smartlist_free(fps);
2859 } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) {
2860 smartlist_t *fp_sks = smartlist_create();
2861 dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"),
2862 fp_sks);
2863 SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, {
2864 authority_cert_t *c = authority_cert_get_by_digests(pair->first,
2865 pair->second);
2866 if (c) smartlist_add(certs, c);
2867 tor_free(pair);
2869 smartlist_free(fp_sks);
2870 } else {
2871 write_http_status_line(conn, 400, "Bad request");
2872 goto keys_done;
2874 if (!smartlist_len(certs)) {
2875 write_http_status_line(conn, 404, "Not found");
2876 goto keys_done;
2878 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2879 if (c->cache_info.published_on < if_modified_since)
2880 SMARTLIST_DEL_CURRENT(certs, c));
2881 if (!smartlist_len(certs)) {
2882 write_http_status_line(conn, 304, "Not modified");
2883 goto keys_done;
2885 len = 0;
2886 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2887 len += c->cache_info.signed_descriptor_len);
2889 if (global_write_bucket_low(TO_CONN(conn), compressed?len/2:len, 2)) {
2890 write_http_status_line(conn, 503, "Directory busy, try again later.");
2891 goto keys_done;
2894 write_http_response_header(conn, compressed?-1:len, compressed, 60*60);
2895 if (compressed) {
2896 conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
2897 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2898 connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
2899 c->cache_info.signed_descriptor_len,
2900 conn, 0));
2901 connection_write_to_buf_zlib("", 0, conn, 1);
2902 } else {
2903 SMARTLIST_FOREACH(certs, authority_cert_t *, c,
2904 connection_write_to_buf(c->cache_info.signed_descriptor_body,
2905 c->cache_info.signed_descriptor_len,
2906 TO_CONN(conn)));
2908 keys_done:
2909 smartlist_free(certs);
2910 goto done;
2913 if (options->HidServDirectoryV2 &&
2914 !strcmpstart(url,"/tor/rendezvous2/")) {
2915 /* Handle v2 rendezvous descriptor fetch request. */
2916 const char *descp;
2917 const char *query = url + strlen("/tor/rendezvous2/");
2918 if (strlen(query) == REND_DESC_ID_V2_LEN_BASE32) {
2919 log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'",
2920 safe_str(query));
2921 switch (rend_cache_lookup_v2_desc_as_dir(query, &descp)) {
2922 case 1: /* valid */
2923 write_http_response_header(conn, strlen(descp), 0, 0);
2924 connection_write_to_buf(descp, strlen(descp), TO_CONN(conn));
2925 break;
2926 case 0: /* well-formed but not present */
2927 write_http_status_line(conn, 404, "Not found");
2928 break;
2929 case -1: /* not well-formed */
2930 write_http_status_line(conn, 400, "Bad request");
2931 break;
2933 } else { /* not well-formed */
2934 write_http_status_line(conn, 400, "Bad request");
2936 goto done;
2939 if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) {
2940 /* rendezvous descriptor fetch */
2941 const char *descp;
2942 size_t desc_len;
2943 const char *query = url+strlen("/tor/rendezvous/");
2945 log_info(LD_REND, "Handling rendezvous descriptor get");
2946 switch (rend_cache_lookup_desc(query, 0, &descp, &desc_len)) {
2947 case 1: /* valid */
2948 write_http_response_header_impl(conn, desc_len,
2949 "application/octet-stream",
2950 NULL, NULL, 0);
2951 note_request("/tor/rendezvous?/", desc_len);
2952 /* need to send descp separately, because it may include NULs */
2953 connection_write_to_buf(descp, desc_len, TO_CONN(conn));
2954 break;
2955 case 0: /* well-formed but not present */
2956 write_http_status_line(conn, 404, "Not found");
2957 break;
2958 case -1: /* not well-formed */
2959 write_http_status_line(conn, 400, "Bad request");
2960 break;
2962 goto done;
2965 if (options->BridgeAuthoritativeDir &&
2966 options->BridgePassword &&
2967 connection_dir_is_encrypted(conn) &&
2968 !strcmp(url,"/tor/networkstatus-bridges")) {
2969 char *status;
2970 char *secret = alloc_http_authenticator(options->BridgePassword);
2972 header = http_get_header(headers, "Authorization: Basic ");
2974 /* now make sure the password is there and right */
2975 if (!header || strcmp(header, secret)) {
2976 write_http_status_line(conn, 404, "Not found");
2977 tor_free(secret);
2978 tor_free(header);
2979 goto done;
2981 tor_free(secret);
2982 tor_free(header);
2984 /* all happy now. send an answer. */
2985 status = networkstatus_getinfo_by_purpose("bridge", time(NULL));
2986 dlen = strlen(status);
2987 write_http_response_header(conn, dlen, 0, 0);
2988 connection_write_to_buf(status, dlen, TO_CONN(conn));
2989 tor_free(status);
2990 goto done;
2993 if (!strcmpstart(url,"/tor/bytes.txt")) {
2994 char *bytes = directory_dump_request_log();
2995 size_t len = strlen(bytes);
2996 write_http_response_header(conn, len, 0, 0);
2997 connection_write_to_buf(bytes, len, TO_CONN(conn));
2998 tor_free(bytes);
2999 goto done;
3002 if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
3003 rewritten to /tor/robots.txt */
3004 char robots[] = "User-agent: *\r\nDisallow: /\r\n";
3005 size_t len = strlen(robots);
3006 write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
3007 connection_write_to_buf(robots, len, TO_CONN(conn));
3008 goto done;
3011 if (!strcmp(url,"/tor/dbg-stability.txt")) {
3012 const char *stability;
3013 size_t len;
3014 if (! authdir_mode_tests_reachability(options) ||
3015 ! (stability = rep_hist_get_router_stability_doc(time(NULL)))) {
3016 write_http_status_line(conn, 404, "Not found.");
3017 goto done;
3020 len = strlen(stability);
3021 write_http_response_header(conn, len, 0, 0);
3022 connection_write_to_buf(stability, len, TO_CONN(conn));
3023 goto done;
3026 #if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
3027 #define ADD_MALLINFO_LINE(x) do { \
3028 tor_snprintf(tmp, sizeof(tmp), "%s %d\n", #x, mi.x); \
3029 smartlist_add(lines, tor_strdup(tmp)); \
3030 }while(0);
3032 if (!strcmp(url,"/tor/mallinfo.txt") &&
3033 (tor_addr_eq_ipv4h(&conn->_base.addr, 0x7f000001ul))) {
3034 char *result;
3035 size_t len;
3036 struct mallinfo mi;
3037 smartlist_t *lines;
3038 char tmp[256];
3040 memset(&mi, 0, sizeof(mi));
3041 mi = mallinfo();
3042 lines = smartlist_create();
3044 ADD_MALLINFO_LINE(arena)
3045 ADD_MALLINFO_LINE(ordblks)
3046 ADD_MALLINFO_LINE(smblks)
3047 ADD_MALLINFO_LINE(hblks)
3048 ADD_MALLINFO_LINE(hblkhd)
3049 ADD_MALLINFO_LINE(usmblks)
3050 ADD_MALLINFO_LINE(fsmblks)
3051 ADD_MALLINFO_LINE(uordblks)
3052 ADD_MALLINFO_LINE(fordblks)
3053 ADD_MALLINFO_LINE(keepcost)
3055 result = smartlist_join_strings(lines, "", 0, NULL);
3056 SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
3057 smartlist_free(lines);
3059 len = strlen(result);
3060 write_http_response_header(conn, len, 0, 0);
3061 connection_write_to_buf(result, len, TO_CONN(conn));
3062 tor_free(result);
3063 goto done;
3065 #endif
3067 /* we didn't recognize the url */
3068 write_http_status_line(conn, 404, "Not found");
3070 done:
3071 tor_free(url_mem);
3072 return 0;
3075 /** Helper function: called when a dirserver gets a complete HTTP POST
3076 * request. Look for an uploaded server descriptor or rendezvous
3077 * service descriptor. On finding one, process it and write a
3078 * response into conn-\>outbuf. If the request is unrecognized, send a
3079 * 400. Always return 0. */
3080 static int
3081 directory_handle_command_post(dir_connection_t *conn, const char *headers,
3082 const char *body, size_t body_len)
3084 char *url = NULL;
3085 or_options_t *options = get_options();
3087 log_debug(LD_DIRSERV,"Received POST command.");
3089 conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
3091 if (parse_http_url(headers, &url) < 0) {
3092 write_http_status_line(conn, 400, "Bad request");
3093 return 0;
3095 log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
3097 /* Handle v2 rendezvous service publish request. */
3098 if (options->HidServDirectoryV2 &&
3099 !strcmpstart(url,"/tor/rendezvous2/publish")) {
3100 switch (rend_cache_store_v2_desc_as_dir(body)) {
3101 case -2:
3102 log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
3103 "since we're not currently a hidden service directory.",
3104 (int)body_len, conn->_base.address);
3105 write_http_status_line(conn, 503, "Currently not acting as v2 "
3106 "hidden service directory");
3107 break;
3108 case -1:
3109 log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
3110 (int)body_len, conn->_base.address);
3111 write_http_status_line(conn, 400,
3112 "Invalid v2 service descriptor rejected");
3113 break;
3114 default:
3115 write_http_status_line(conn, 200, "Service descriptor (v2) stored");
3116 log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
3118 goto done;
3121 if (!authdir_mode(options)) {
3122 /* we just provide cached directories; we don't want to
3123 * receive anything. */
3124 write_http_status_line(conn, 400, "Nonauthoritative directory does not "
3125 "accept posted server descriptors");
3126 goto done;
3129 if (authdir_mode_handles_descs(options, -1) &&
3130 !strcmp(url,"/tor/")) { /* server descriptor post */
3131 const char *msg = "[None]";
3132 uint8_t purpose = authdir_mode_bridge(options) ?
3133 ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
3134 was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
3135 conn->_base.address, &msg);
3136 tor_assert(msg);
3137 if (WRA_WAS_ADDED(r))
3138 dirserv_get_directory(); /* rebuild and write to disk */
3140 if (r == ROUTER_ADDED_NOTIFY_GENERATOR) {
3141 /* Accepted with a message. */
3142 log_info(LD_DIRSERV,
3143 "Problematic router descriptor or extra-info from %s "
3144 "(\"%s\").",
3145 conn->_base.address, msg);
3146 write_http_status_line(conn, 400, msg);
3147 } else if (r == ROUTER_ADDED_SUCCESSFULLY) {
3148 write_http_status_line(conn, 200, msg);
3149 } else if (WRA_WAS_OUTDATED(r)) {
3150 write_http_response_header_impl(conn, -1, NULL, NULL,
3151 "X-Descriptor-Not-New: Yes\r\n", -1);
3152 } else {
3153 log_info(LD_DIRSERV,
3154 "Rejected router descriptor or extra-info from %s "
3155 "(\"%s\").",
3156 conn->_base.address, msg);
3157 write_http_status_line(conn, 400, msg);
3159 goto done;
3162 if (options->HSAuthoritativeDir &&
3163 !strcmpstart(url,"/tor/rendezvous/publish")) {
3164 /* rendezvous descriptor post */
3165 log_info(LD_REND, "Handling rendezvous descriptor post.");
3166 if (rend_cache_store(body, body_len, 1) < 0) {
3167 log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
3168 "Rejected rend descriptor (length %d) from %s.",
3169 (int)body_len, conn->_base.address);
3170 write_http_status_line(conn, 400,
3171 "Invalid v0 service descriptor rejected");
3172 } else {
3173 write_http_status_line(conn, 200, "Service descriptor (v0) stored");
3175 goto done;
3178 if (authdir_mode_v3(options) &&
3179 !strcmp(url,"/tor/post/vote")) { /* v3 networkstatus vote */
3180 const char *msg = "OK";
3181 int status;
3182 if (dirvote_add_vote(body, &msg, &status)) {
3183 write_http_status_line(conn, status, "Vote stored");
3184 } else {
3185 tor_assert(msg);
3186 write_http_status_line(conn, status, msg);
3188 goto done;
3191 if (authdir_mode_v3(options) &&
3192 !strcmp(url,"/tor/post/consensus-signature")) { /* sigs on consensus. */
3193 const char *msg = NULL;
3194 if (dirvote_add_signatures(body, conn->_base.address, &msg)>=0) {
3195 write_http_status_line(conn, 200, msg?msg:"Signatures stored");
3196 } else {
3197 log_warn(LD_DIR, "Unable to store signatures posted by %s: %s",
3198 conn->_base.address, msg?msg:"???");
3199 write_http_status_line(conn, 400, msg?msg:"Unable to store signatures");
3201 goto done;
3204 /* we didn't recognize the url */
3205 write_http_status_line(conn, 404, "Not found");
3207 done:
3208 tor_free(url);
3209 return 0;
3212 /** Called when a dirserver receives data on a directory connection;
3213 * looks for an HTTP request. If the request is complete, remove it
3214 * from the inbuf, try to process it; otherwise, leave it on the
3215 * buffer. Return a 0 on success, or -1 on error.
3217 static int
3218 directory_handle_command(dir_connection_t *conn)
3220 char *headers=NULL, *body=NULL;
3221 size_t body_len=0;
3222 int r;
3224 tor_assert(conn);
3225 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3227 switch (fetch_from_buf_http(conn->_base.inbuf,
3228 &headers, MAX_HEADERS_SIZE,
3229 &body, &body_len, MAX_DIR_UL_SIZE, 0)) {
3230 case -1: /* overflow */
3231 log_warn(LD_DIRSERV,
3232 "Request too large from address '%s' to DirPort. Closing.",
3233 safe_str(conn->_base.address));
3234 return -1;
3235 case 0:
3236 log_debug(LD_DIRSERV,"command not all here yet.");
3237 return 0;
3238 /* case 1, fall through */
3241 http_set_address_origin(headers, TO_CONN(conn));
3242 //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
3244 if (!strncasecmp(headers,"GET",3))
3245 r = directory_handle_command_get(conn, headers, body, body_len);
3246 else if (!strncasecmp(headers,"POST",4))
3247 r = directory_handle_command_post(conn, headers, body, body_len);
3248 else {
3249 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
3250 "Got headers %s with unknown command. Closing.",
3251 escaped(headers));
3252 r = -1;
3255 tor_free(headers); tor_free(body);
3256 return r;
3259 /** Write handler for directory connections; called when all data has
3260 * been flushed. Close the connection or wait for a response as
3261 * appropriate.
3264 connection_dir_finished_flushing(dir_connection_t *conn)
3266 tor_assert(conn);
3267 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3269 /* Note that we have finished writing the directory response. For direct
3270 * connections this means we're done, for tunneled connections its only
3271 * an intermediate step. */
3272 if (TO_CONN(conn)->dirreq_id)
3273 geoip_change_dirreq_state(TO_CONN(conn)->dirreq_id, DIRREQ_TUNNELED,
3274 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3275 else
3276 geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
3277 DIRREQ_DIRECT,
3278 DIRREQ_FLUSHING_DIR_CONN_FINISHED);
3279 switch (conn->_base.state) {
3280 case DIR_CONN_STATE_CLIENT_SENDING:
3281 log_debug(LD_DIR,"client finished sending command.");
3282 conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
3283 connection_stop_writing(TO_CONN(conn));
3284 return 0;
3285 case DIR_CONN_STATE_SERVER_WRITING:
3286 log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
3287 connection_mark_for_close(TO_CONN(conn));
3288 return 0;
3289 default:
3290 log_warn(LD_BUG,"called in unexpected state %d.",
3291 conn->_base.state);
3292 tor_fragile_assert();
3293 return -1;
3295 return 0;
3298 /** Connected handler for directory connections: begin sending data to the
3299 * server */
3301 connection_dir_finished_connecting(dir_connection_t *conn)
3303 tor_assert(conn);
3304 tor_assert(conn->_base.type == CONN_TYPE_DIR);
3305 tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
3307 log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
3308 conn->_base.address,conn->_base.port);
3310 conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
3311 return 0;
3314 /** Called when one or more networkstatus fetches have failed (with uppercase
3315 * fingerprints listed in <b>failed</b>). Mark those fingerprints as having
3316 * failed once, unless they failed with status code 503. */
3317 static void
3318 dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
3320 if (status_code == 503)
3321 return;
3322 SMARTLIST_FOREACH(failed, const char *, fp,
3324 char digest[DIGEST_LEN];
3325 trusted_dir_server_t *dir;
3326 if (base16_decode(digest, DIGEST_LEN, fp, strlen(fp))<0) {
3327 log_warn(LD_BUG, "Called with bad fingerprint in list: %s",
3328 escaped(fp));
3329 continue;
3331 dir = router_get_trusteddirserver_by_digest(digest);
3333 if (dir)
3334 download_status_failed(&dir->v2_ns_dl_status, status_code);
3338 /** Schedule for when servers should download things in general. */
3339 static const int server_dl_schedule[] = {
3340 0, 0, 0, 60, 60, 60*2, 60*5, 60*15, INT_MAX
3342 /** Schedule for when clients should download things in general. */
3343 static const int client_dl_schedule[] = {
3344 0, 0, 60, 60*5, 60*10, INT_MAX
3346 /** Schedule for when servers should download consensuses. */
3347 static const int server_consensus_dl_schedule[] = {
3348 0, 0, 60, 60*5, 60*10, 60*30, 60*30, 60*30, 60*30, 60*30, 60*60, 60*60*2
3350 /** Schedule for when clients should download consensuses. */
3351 static const int client_consensus_dl_schedule[] = {
3352 0, 0, 60, 60*5, 60*10, 60*30, 60*60, 60*60, 60*60, 60*60*3, 60*60*6, 60*60*12
3354 /** Schedule for when clients should download bridge descriptors. */
3355 static const int bridge_dl_schedule[] = {
3356 60*60, 15*60, 15*60, 60*60
3359 /** Decide which download schedule we want to use, and then return a
3360 * pointer to it along with a pointer to its length. Helper function for
3361 * download_status_increment_failure() and download_status_reset(). */
3362 static void
3363 find_dl_schedule_and_len(download_status_t *dls, int server,
3364 const int **schedule, size_t *schedule_len)
3366 switch (dls->schedule) {
3367 case DL_SCHED_GENERIC:
3368 if (server) {
3369 *schedule = server_dl_schedule;
3370 *schedule_len = sizeof(server_dl_schedule)/sizeof(int);
3371 } else {
3372 *schedule = client_dl_schedule;
3373 *schedule_len = sizeof(client_dl_schedule)/sizeof(int);
3375 break;
3376 case DL_SCHED_CONSENSUS:
3377 if (server) {
3378 *schedule = server_consensus_dl_schedule;
3379 *schedule_len = sizeof(server_consensus_dl_schedule)/sizeof(int);
3380 } else {
3381 *schedule = client_consensus_dl_schedule;
3382 *schedule_len = sizeof(client_consensus_dl_schedule)/sizeof(int);
3384 break;
3385 case DL_SCHED_BRIDGE:
3386 *schedule = bridge_dl_schedule;
3387 *schedule_len = sizeof(bridge_dl_schedule)/sizeof(int);
3388 break;
3389 default:
3390 tor_assert(0);
3394 /** Called when an attempt to download <b>dls</b> has failed with HTTP status
3395 * <b>status_code</b>. Increment the failure count (if the code indicates a
3396 * real failure) and set <b>dls</b>-\>next_attempt_at to an appropriate time
3397 * in the future. */
3398 time_t
3399 download_status_increment_failure(download_status_t *dls, int status_code,
3400 const char *item, int server, time_t now)
3402 const int *schedule;
3403 size_t schedule_len;
3404 int increment;
3405 tor_assert(dls);
3406 if (status_code != 503 || server) {
3407 if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1)
3408 ++dls->n_download_failures;
3411 find_dl_schedule_and_len(dls, server, &schedule, &schedule_len);
3413 if (dls->n_download_failures < schedule_len)
3414 increment = schedule[dls->n_download_failures];
3415 else if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
3416 increment = INT_MAX;
3417 else
3418 increment = schedule[schedule_len-1];
3420 if (increment < INT_MAX)
3421 dls->next_attempt_at = now+increment;
3422 else
3423 dls->next_attempt_at = TIME_MAX;
3425 if (item) {
3426 if (increment == 0)
3427 log_debug(LD_DIR, "%s failed %d time(s); I'll try again immediately.",
3428 item, (int)dls->n_download_failures);
3429 else if (dls->next_attempt_at < TIME_MAX)
3430 log_debug(LD_DIR, "%s failed %d time(s); I'll try again in %d seconds.",
3431 item, (int)dls->n_download_failures,
3432 (int)(dls->next_attempt_at-now));
3433 else
3434 log_debug(LD_DIR, "%s failed %d time(s); Giving up for a while.",
3435 item, (int)dls->n_download_failures);
3437 return dls->next_attempt_at;
3440 /** Reset <b>dls</b> so that it will be considered downloadable
3441 * immediately, and/or to show that we don't need it anymore.
3443 * (We find the zeroth element of the download schedule, and set
3444 * next_attempt_at to be the appropriate offset from 'now'. In most
3445 * cases this means setting it to 'now', so the item will be immediately
3446 * downloadable; in the case of bridge descriptors, the zeroth element
3447 * is an hour from now.) */
3448 void
3449 download_status_reset(download_status_t *dls)
3451 const int *schedule;
3452 size_t schedule_len;
3454 find_dl_schedule_and_len(dls, get_options()->DirPort,
3455 &schedule, &schedule_len);
3457 dls->n_download_failures = 0;
3458 dls->next_attempt_at = time(NULL) + schedule[0];
3461 /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
3462 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
3463 * either as descriptor digests or as identity digests based on
3464 * <b>was_descriptor_digests</b>).
3466 static void
3467 dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
3468 int router_purpose,
3469 int was_extrainfo, int was_descriptor_digests)
3471 char digest[DIGEST_LEN];
3472 time_t now = time(NULL);
3473 int server = directory_fetches_from_authorities(get_options());
3474 if (!was_descriptor_digests) {
3475 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
3476 tor_assert(!was_extrainfo); /* not supported yet */
3477 SMARTLIST_FOREACH(failed, const char *, cp,
3479 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
3480 log_warn(LD_BUG, "Malformed fingerprint in list: %s",
3481 escaped(cp));
3482 continue;
3484 retry_bridge_descriptor_fetch_directly(digest);
3487 return; /* FFFF should implement for other-than-router-purpose someday */
3489 SMARTLIST_FOREACH(failed, const char *, cp,
3491 download_status_t *dls = NULL;
3492 if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) {
3493 log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp));
3494 continue;
3496 if (was_extrainfo) {
3497 signed_descriptor_t *sd =
3498 router_get_by_extrainfo_digest(digest);
3499 if (sd)
3500 dls = &sd->ei_dl_status;
3501 } else {
3502 dls = router_get_dl_status_by_descriptor_digest(digest);
3504 if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
3505 continue;
3506 download_status_increment_failure(dls, status_code, cp, server, now);
3509 /* No need to relaunch descriptor downloads here: we already do it
3510 * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
3513 /** Helper. Compare two fp_pair_t objects, and return -1, 0, or 1 as
3514 * appropriate. */
3515 static int
3516 _compare_pairs(const void **a, const void **b)
3518 const fp_pair_t *fp1 = *a, *fp2 = *b;
3519 int r;
3520 if ((r = memcmp(fp1->first, fp2->first, DIGEST_LEN)))
3521 return r;
3522 else
3523 return memcmp(fp1->second, fp2->second, DIGEST_LEN);
3526 /** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
3527 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
3528 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
3529 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
3531 dir_split_resource_into_fingerprint_pairs(const char *res,
3532 smartlist_t *pairs_out)
3534 smartlist_t *pairs_tmp = smartlist_create();
3535 smartlist_t *pairs_result = smartlist_create();
3537 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
3538 if (smartlist_len(pairs_tmp)) {
3539 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
3540 size_t last_len = strlen(last);
3541 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3542 last[last_len-2] = '\0';
3545 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
3546 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
3547 log_info(LD_DIR,
3548 "Skipping digest pair %s with non-standard length.", escaped(cp));
3549 } else if (cp[HEX_DIGEST_LEN] != '-') {
3550 log_info(LD_DIR,
3551 "Skipping digest pair %s with missing dash.", escaped(cp));
3552 } else {
3553 fp_pair_t pair;
3554 if (base16_decode(pair.first, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0 ||
3555 base16_decode(pair.second,
3556 DIGEST_LEN, cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN)<0) {
3557 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
3558 } else {
3559 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
3562 tor_free(cp);
3563 } SMARTLIST_FOREACH_END(cp);
3564 smartlist_free(pairs_tmp);
3566 /* Uniq-and-sort */
3567 smartlist_sort(pairs_result, _compare_pairs);
3568 smartlist_uniq(pairs_result, _compare_pairs, _tor_free);
3570 smartlist_add_all(pairs_out, pairs_result);
3571 smartlist_free(pairs_result);
3572 return 0;
3575 /** Given a directory <b>resource</b> request, containing zero
3576 * or more strings separated by plus signs, followed optionally by ".z", store
3577 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
3578 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
3580 * If (flags & DSR_HEX), then delete all elements that aren't hex digests, and
3581 * decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as
3582 * a separator, delete all the elements that aren't base64-encoded digests,
3583 * and decode the rest. If (flags & DSR_DIGEST256), these digests should be
3584 * 256 bits long; else they should be 160.
3586 * If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates.
3589 dir_split_resource_into_fingerprints(const char *resource,
3590 smartlist_t *fp_out, int *compressed_out,
3591 int flags)
3593 const int decode_hex = flags & DSR_HEX;
3594 const int decode_base64 = flags & DSR_BASE64;
3595 const int digests_are_256 = flags & DSR_DIGEST256;
3596 const int sort_uniq = flags & DSR_SORT_UNIQ;
3598 const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
3599 const int hex_digest_len = digests_are_256 ?
3600 HEX_DIGEST256_LEN : HEX_DIGEST_LEN;
3601 const int base64_digest_len = digests_are_256 ?
3602 BASE64_DIGEST256_LEN : BASE64_DIGEST_LEN;
3603 smartlist_t *fp_tmp = smartlist_create();
3605 tor_assert(!(decode_hex && decode_base64));
3606 tor_assert(fp_out);
3608 smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
3609 if (compressed_out)
3610 *compressed_out = 0;
3611 if (smartlist_len(fp_tmp)) {
3612 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
3613 size_t last_len = strlen(last);
3614 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
3615 last[last_len-2] = '\0';
3616 if (compressed_out)
3617 *compressed_out = 1;
3620 if (decode_hex || decode_base64) {
3621 const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
3622 int i;
3623 char *cp, *d = NULL;
3624 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
3625 cp = smartlist_get(fp_tmp, i);
3626 if (strlen(cp) != encoded_len) {
3627 log_info(LD_DIR,
3628 "Skipping digest %s with non-standard length.", escaped(cp));
3629 smartlist_del_keeporder(fp_tmp, i--);
3630 goto again;
3632 d = tor_malloc_zero(digest_len);
3633 if (decode_hex ?
3634 (base16_decode(d, digest_len, cp, hex_digest_len)<0) :
3635 (base64_decode(d, digest_len, cp, base64_digest_len)<0)) {
3636 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
3637 smartlist_del_keeporder(fp_tmp, i--);
3638 goto again;
3640 smartlist_set(fp_tmp, i, d);
3641 d = NULL;
3642 again:
3643 tor_free(cp);
3644 tor_free(d);
3647 if (sort_uniq) {
3648 if (decode_hex || decode_base64) {
3649 if (digests_are_256) {
3650 smartlist_sort_digests256(fp_tmp);
3651 smartlist_uniq_digests256(fp_tmp);
3652 } else {
3653 smartlist_sort_digests(fp_tmp);
3654 smartlist_uniq_digests(fp_tmp);
3656 } else {
3657 smartlist_sort_strings(fp_tmp);
3658 smartlist_uniq_strings(fp_tmp);
3661 smartlist_add_all(fp_out, fp_tmp);
3662 smartlist_free(fp_tmp);
3663 return 0;