Add a bunch more warnings to out warning suite; resolve them; pack structs a little...
[tor.git] / src / or / dirserv.c
bloba20b09315a850ae73f8f6d0390a903e3c0d54183
1 /* Copyright 2001-2004 Roger Dingledine.
2 * Copyright 2004-2005 Roger Dingledine, Nick Mathewson. */
3 /* See LICENSE for licensing information */
4 /* $Id$ */
5 const char dirserv_c_id[] = "$Id$";
7 #include "or.h"
9 /**
10 * \file dirserv.c
11 * \brief Directory server core implementation. Manages directory
12 * contents and generates directories.
13 **/
15 /** How far in the future do we allow a router to get? (seconds) */
16 #define ROUTER_ALLOW_SKEW (60*60*12) /* 12 hours */
17 /** How many seconds do we wait before regenerating the directory? */
18 #define DIR_REGEN_SLACK_TIME 30
20 extern long stats_n_seconds_working;
22 typedef enum {
23 FP_NAMED, /**< Listed in fingerprint file. */
24 FP_VALID, /**< Unlisted but believed valid. */
25 FP_INVALID, /**< Believed invalid. */
26 FP_REJECT, /**< We will not publish this router. */
27 } router_status_t;
29 /** Do we need to regenerate the directory when someone asks for it? */
30 static int the_directory_is_dirty = 1;
31 static int runningrouters_is_dirty = 1;
32 static int the_v2_networkstatus_is_dirty = 1;
34 static void directory_remove_invalid(void);
35 static int dirserv_regenerate_directory(void);
36 static char *format_versions_list(config_line_t *ln);
37 /* Should be static; exposed for testing */
38 int add_fingerprint_to_dir(const char *nickname, const char *fp, smartlist_t *list);
39 static int router_is_general_exit(routerinfo_t *ri);
40 static router_status_t dirserv_router_get_status(const routerinfo_t *router,
41 const char **msg);
42 static int dirserv_thinks_router_is_reachable(routerinfo_t *router,
43 time_t now);
45 /************** Fingerprint handling code ************/
47 static addr_policy_t *authdir_reject_policy = NULL;
48 static addr_policy_t *authdir_invalid_policy = NULL;
50 /** Parse authdir policy strings from the configuration.
52 void
53 parse_authdir_policy(void) {
54 addr_policy_t *n;
55 if (authdir_reject_policy) {
56 addr_policy_free(authdir_reject_policy);
57 authdir_reject_policy = NULL;
59 config_parse_addr_policy(get_options()->AuthDirReject,
60 &authdir_reject_policy, ADDR_POLICY_ACCEPT);
61 /* ports aren't used. */
62 for (n=authdir_reject_policy; n; n = n->next) {
63 n->prt_min = 1;
64 n->prt_max = 65535;
67 if (authdir_invalid_policy) {
68 addr_policy_free(authdir_invalid_policy);
69 authdir_invalid_policy = NULL;
71 config_parse_addr_policy(get_options()->AuthDirInvalid,
72 &authdir_invalid_policy, ADDR_POLICY_ACCEPT);
73 /* ports aren't used. */
74 for (n=authdir_invalid_policy; n; n = n->next) {
75 n->prt_min = 1;
76 n->prt_max = 65535;
80 typedef struct fingerprint_entry_t {
81 char *nickname;
82 char *fingerprint; /**< Stored as HEX_DIGEST_LEN characters, followed by a NUL */
83 } fingerprint_entry_t;
85 /** List of nickname-\>identity fingerprint mappings for all the routers
86 * that we recognize. Used to prevent Sybil attacks. */
87 /* Should be static; exposed for testing */
88 smartlist_t *fingerprint_list = NULL;
90 /** Add the fingerprint <b>fp</b> for the nickname <b>nickname</b> to
91 * the smartlist of fingerprint_entry_t's <b>list</b>. Return 0 if it's
92 * new, or 1 if we replaced the old value.
94 int /* Should be static; exposed for testing */
95 add_fingerprint_to_dir(const char *nickname, const char *fp, smartlist_t *list)
97 int i;
98 fingerprint_entry_t *ent;
99 char *fingerprint;
100 tor_assert(nickname);
101 tor_assert(fp);
102 tor_assert(list);
104 fingerprint = tor_strdup(fp);
105 tor_strstrip(fingerprint, " ");
107 for (i = 0; i < smartlist_len(list); ++i) {
108 ent = smartlist_get(list, i);
109 if (!strcasecmp(ent->nickname,nickname)) {
110 tor_free(ent->fingerprint);
111 ent->fingerprint = fingerprint;
112 return 1;
115 ent = tor_malloc(sizeof(fingerprint_entry_t));
116 ent->nickname = tor_strdup(nickname);
117 ent->fingerprint = fingerprint;
118 smartlist_add(list, ent);
119 return 0;
122 /** Add the nickname and fingerprint for this OR to the
123 * global list of recognized identity key fingerprints. */
125 dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk)
127 char fp[FINGERPRINT_LEN+1];
128 if (crypto_pk_get_fingerprint(pk, fp, 0)<0) {
129 log_fn(LOG_ERR, "Error computing fingerprint");
130 return -1;
132 if (!fingerprint_list)
133 fingerprint_list = smartlist_create();
134 add_fingerprint_to_dir(nickname, fp, fingerprint_list);
135 return 0;
138 /** Parse the nickname-\>fingerprint mappings stored in the file named
139 * <b>fname</b>. The file format is line-based, with each non-blank
140 * holding one nickname, some space, and a fingerprint for that
141 * nickname. On success, replace the current fingerprint list with
142 * the contents of <b>fname</b> and return 0. On failure, leave the
143 * current fingerprint list untouched, and return -1. */
145 dirserv_parse_fingerprint_file(const char *fname)
147 char *cf;
148 char *nickname, *fingerprint;
149 smartlist_t *fingerprint_list_new;
150 int result;
151 config_line_t *front=NULL, *list;
153 cf = read_file_to_str(fname, 0);
154 if (!cf) {
155 log_fn(LOG_WARN, "Cannot open fingerprint file %s", fname);
156 return -1;
158 result = config_get_lines(cf, &front);
159 tor_free(cf);
160 if (result < 0) {
161 log_fn(LOG_WARN, "Error reading from fingerprint file");
162 return -1;
165 fingerprint_list_new = smartlist_create();
167 for (list=front; list; list=list->next) {
168 nickname = list->key; fingerprint = list->value;
169 if (strlen(nickname) > MAX_NICKNAME_LEN) {
170 log(LOG_NOTICE, "Nickname '%s' too long in fingerprint file. Skipping.", nickname);
171 continue;
173 if (!is_legal_nickname(nickname) &&
174 strcasecmp(nickname, "!reject") &&
175 strcasecmp(nickname, "!invalid")) {
176 log(LOG_NOTICE, "Invalid nickname '%s' in fingerprint file. Skipping.", nickname);
177 continue;
179 if (strlen(fingerprint) != FINGERPRINT_LEN ||
180 !crypto_pk_check_fingerprint_syntax(fingerprint)) {
181 log_fn(LOG_NOTICE, "Invalid fingerprint (nickname '%s', fingerprint %s). Skipping.",
182 nickname, fingerprint);
183 continue;
185 if (0==strcasecmp(nickname, DEFAULT_CLIENT_NICKNAME)) {
186 /* If you approved an OR called "client", then clients who use
187 * the default nickname could all be rejected. That's no good. */
188 log(LOG_NOTICE,
189 "Authorizing a nickname '%s' would break many clients; skipping.",
190 DEFAULT_CLIENT_NICKNAME);
191 continue;
193 if (add_fingerprint_to_dir(nickname, fingerprint, fingerprint_list_new) != 0)
194 log(LOG_NOTICE, "Duplicate nickname '%s'.", nickname);
197 config_free_lines(front);
198 dirserv_free_fingerprint_list();
199 fingerprint_list = fingerprint_list_new;
200 /* Delete any routers whose fingerprints we no longer recognize */
201 directory_remove_invalid();
202 return 0;
205 /** Check whether <b>router</b> has a nickname/identity key combination that
206 * we recognize from the fingerprint list, or an IP we automatically act on
207 * according to our configuration. Return the appropriate router status.
209 * If the status is 'FP_REJECT' and <b>msg</b> is provided, set
210 * *<b>msg</b> to an explanation of why.
212 static router_status_t
213 dirserv_router_get_status(const routerinfo_t *router, const char **msg)
215 fingerprint_entry_t *nn_ent = NULL, *fp_ent = NULL;
216 char fp[FINGERPRINT_LEN+1];
218 if (!fingerprint_list)
219 fingerprint_list = smartlist_create();
221 if (crypto_pk_get_fingerprint(router->identity_pkey, fp, 0)) {
222 log_fn(LOG_WARN,"Error computing fingerprint");
223 return -1;
226 log_fn(LOG_DEBUG, "%d fingerprints known.", smartlist_len(fingerprint_list));
227 SMARTLIST_FOREACH(fingerprint_list, fingerprint_entry_t *, ent,
229 if (!strcasecmp(fp,ent->fingerprint))
230 fp_ent = ent;
231 if (!strcasecmp(router->nickname,ent->nickname))
232 nn_ent = ent;
235 if (fp_ent) {
236 if (!strcasecmp(fp_ent->nickname, "!reject")) {
237 if (msg)
238 *msg = "Fingerprint is marked rejected";
239 return FP_REJECT;
240 } else if (!strcasecmp(fp_ent->nickname, "!invalid")) {
241 if (msg)
242 *msg = "Fingerprint is marged invalid";
243 return FP_INVALID;
247 if (!nn_ent) { /* No such server known with that nickname */
248 addr_policy_result_t rej = router_compare_addr_to_addr_policy(
249 router->addr, router->or_port, authdir_reject_policy);
250 addr_policy_result_t inv = router_compare_addr_to_addr_policy(
251 router->addr, router->or_port, authdir_invalid_policy);
253 if (rej == ADDR_POLICY_PROBABLY_ACCEPTED || rej == ADDR_POLICY_ACCEPTED) {
254 log_fn(LOG_INFO, "Rejecting '%s' because of address %s",
255 router->nickname, router->address);
256 if (msg)
257 *msg = "Authdir is rejecting routers in this range.";
258 return FP_REJECT;
260 if (inv == ADDR_POLICY_PROBABLY_ACCEPTED || inv == ADDR_POLICY_ACCEPTED) {
261 log_fn(LOG_INFO, "Not marking '%s' valid because of address %s",
262 router->nickname, router->address);
263 return FP_INVALID;
265 if (tor_version_as_new_as(router->platform,"0.1.0.2-rc"))
266 return FP_VALID;
267 else
268 return FP_INVALID;
269 log_fn(LOG_INFO,"No fingerprint found for '%s'",router->nickname);
270 return 0;
272 if (0==strcasecmp(nn_ent->fingerprint, fp)) {
273 log_fn(LOG_DEBUG,"Good fingerprint for '%s'",router->nickname);
274 return FP_NAMED; /* Right fingerprint. */
275 } else {
276 log_fn(LOG_WARN,"Mismatched fingerprint for '%s': expected '%s' got '%s'. ContactInfo '%s', platform '%s'.)",
277 router->nickname, nn_ent->fingerprint, fp,
278 router->contact_info ? router->contact_info : "",
279 router->platform ? router->platform : "");
280 if (msg)
281 *msg = "Rejected: There is already a verified server with this nickname and a different fingerprint.";
282 return FP_REJECT; /* Wrong fingerprint. */
286 /** If we are an authoritative dirserver, and the list of approved
287 * servers contains one whose identity key digest is <b>digest</b>,
288 * return that router's nickname. Otherwise return NULL. */
289 const char *
290 dirserv_get_nickname_by_digest(const char *digest)
292 char hexdigest[HEX_DIGEST_LEN+1];
293 if (!fingerprint_list)
294 return NULL;
295 tor_assert(digest);
297 base16_encode(hexdigest, HEX_DIGEST_LEN+1, digest, DIGEST_LEN);
298 SMARTLIST_FOREACH(fingerprint_list, fingerprint_entry_t*, ent,
299 { if (!strcasecmp(hexdigest, ent->fingerprint))
300 return ent->nickname; } );
301 return NULL;
304 /** Clear the current fingerprint list. */
305 void
306 dirserv_free_fingerprint_list(void)
308 int i;
309 fingerprint_entry_t *ent;
310 if (!fingerprint_list)
311 return;
313 for (i = 0; i < smartlist_len(fingerprint_list); ++i) {
314 ent = smartlist_get(fingerprint_list, i);
315 tor_free(ent->nickname);
316 tor_free(ent->fingerprint);
317 tor_free(ent);
319 smartlist_free(fingerprint_list);
320 fingerprint_list = NULL;
324 * Descriptor list
327 static smartlist_t *
328 get_descriptor_list(void)
330 routerlist_t *routerlist;
331 router_get_routerlist(&routerlist);
332 if (!routerlist)
333 return NULL;
334 return routerlist->routers;
337 /** Return -1 if <b>ri</b> has a private or otherwise bad address,
338 * unless we're configured to not care. Return 0 if all ok. */
339 static int
340 dirserv_router_has_valid_address(routerinfo_t *ri)
342 struct in_addr iaddr;
343 if (get_options()->DirAllowPrivateAddresses)
344 return 0; /* whatever it is, we're fine with it */
345 if (!tor_inet_aton(ri->address, &iaddr)) {
346 log_fn(LOG_INFO,"Router '%s' published non-IP address '%s'. Refusing.",
347 ri->nickname, ri->address);
348 return -1;
350 if (is_internal_IP(ntohl(iaddr.s_addr))) {
351 log_fn(LOG_INFO,"Router '%s' published internal IP address '%s'. Refusing.",
352 ri->nickname, ri->address);
353 return -1; /* it's a private IP, we should reject it */
355 return 0;
358 /** Check whether we, as a directory server, want to accept <b>ri</b>. If so,
359 * return 0, and set its is_valid,named,running fields. Otherwise, return -1.
361 * If the router is rejected, set *<b>msg</b> to an explanation of why.
364 authdir_wants_to_reject_router(routerinfo_t *ri,
365 const char **msg)
367 /* Okay. Now check whether the fingerprint is recognized. */
368 router_status_t status = dirserv_router_get_status(ri, msg);
369 time_t now;
370 tor_assert(msg);
371 if (status == FP_REJECT)
372 return -1; /* msg is already set. */
374 /* Is there too much clock skew? */
375 now = time(NULL);
376 if (ri->published_on > now+ROUTER_ALLOW_SKEW) {
377 log_fn(LOG_NOTICE, "Publication time for nickname '%s' is too far (%d minutes) in the future; possible clock skew. Not adding (ContactInfo '%s', platform '%s').",
378 ri->nickname, (int)((ri->published_on-now)/60),
379 ri->contact_info ? ri->contact_info : "",
380 ri->platform ? ri->platform : "");
381 *msg = "Rejected: Your clock is set too far in the future, or your timezone is not correct.";
382 return -1;
384 if (ri->published_on < now-ROUTER_MAX_AGE) {
385 log_fn(LOG_NOTICE, "Publication time for router with nickname '%s' is too far (%d minutes) in the past. Not adding (ContactInfo '%s', platform '%s').",
386 ri->nickname, (int)((now-ri->published_on)/60),
387 ri->contact_info ? ri->contact_info : "",
388 ri->platform ? ri->platform : "");
389 *msg = "Rejected: Server is expired, or your clock is too far in the past, or your timezone is not correct.";
390 return -1;
392 if (dirserv_router_has_valid_address(ri) < 0) {
393 log_fn(LOG_NOTICE, "Router with nickname '%s' has invalid address '%s'. Not adding (ContactInfo '%s', platform '%s').",
394 ri->nickname, ri->address,
395 ri->contact_info ? ri->contact_info : "",
396 ri->platform ? ri->platform : "");
397 *msg = "Rejected: Address is not an IP, or IP is a private address.";
398 return -1;
400 /* Okay, looks like we're willing to accept this one. */
401 switch (status) {
402 case FP_NAMED:
403 ri->is_named = ri->is_verified = 1;
404 break;
405 case FP_VALID:
406 ri->is_named = 0;
407 ri->is_verified = 1;
408 break;
409 case FP_INVALID:
410 ri->is_named = ri->is_verified = 0;
411 break;
412 default:
413 tor_assert(0);
416 return 0;
419 /** Parse the server descriptor at <b>desc</b> and maybe insert it into
420 * the list of server descriptors. Set *<b>msg</b> to a message that
421 * should be passed back to the origin of this descriptor.
423 * Return 2 if descriptor is well-formed and accepted;
424 * 1 if well-formed and accepted but origin should hear *msg;
425 * 0 if well-formed but redundant with one we already have;
426 * -1 if it looks vaguely like a router descriptor but rejected;
427 * -2 if we can't find a router descriptor in <b>desc</b>.
430 dirserv_add_descriptor(const char *desc, const char **msg)
432 int r;
433 routerinfo_t *ri = NULL;
434 tor_assert(msg);
435 *msg = NULL;
437 /* Check: is the descriptor syntactically valid? */
438 ri = router_parse_entry_from_string(desc, NULL);
439 if (!ri) {
440 log(LOG_WARN, "Couldn't parse descriptor");
441 *msg = "Rejected: Couldn't parse server descriptor.";
442 return -2;
444 if ((r = router_add_to_routerlist(ri, msg, 0))<0) {
445 return r == -1 ? 0 : -1;
446 } else {
447 smartlist_t *changed = smartlist_create();
448 smartlist_add(changed, ri);
449 control_event_descriptors_changed(changed);
450 smartlist_free(changed);
451 if (!*msg) {
452 *msg = ri->is_verified ? "Verified server descriptor accepted" :
453 "Unverified server descriptor accepted";
455 return r == 0 ? 2 : 1;
459 /** Remove all descriptors whose nicknames or fingerprints no longer
460 * are allowed by our fingerprint list. (Descriptors that used to be
461 * good can become bad when we reload the fingerprint list.)
463 static void
464 directory_remove_invalid(void)
466 int i;
467 int changed = 0;
468 smartlist_t *descriptor_list = get_descriptor_list();
470 if (!descriptor_list)
471 return;
473 for (i = 0; i < smartlist_len(descriptor_list); ++i) {
474 const char *msg;
475 routerinfo_t *ent = smartlist_get(descriptor_list, i);
476 router_status_t r = dirserv_router_get_status(ent, &msg);
477 switch (r) {
478 case FP_REJECT:
479 log(LOG_INFO, "Router '%s' is now rejected: %s",
480 ent->nickname, msg?msg:"");
481 routerinfo_free(ent);
482 smartlist_del(descriptor_list, i--);
483 changed = 1;
484 break;
485 case FP_NAMED:
486 if (!ent->is_verified || !ent->is_named) {
487 log(LOG_INFO, "Router '%s' is now verified and named.", ent->nickname);
488 ent->is_verified = ent->is_named = 1;
489 changed = 1;
491 break;
492 case FP_VALID:
493 if (!ent->is_verified || ent->is_named) {
494 log(LOG_INFO, "Router '%s' is now verified.", ent->nickname);
495 ent->is_verified = 1;
496 ent->is_named = 0;
497 changed = 1;
499 break;
500 case FP_INVALID:
501 if (ent->is_verified || ent->is_named) {
502 log(LOG_INFO, "Router '%s' is no longer verified.", ent->nickname);
503 ent->is_verified = ent->is_named = 0;
504 changed = 1;
506 break;
509 if (changed)
510 directory_set_dirty();
513 /** Write a list of unregistered descriptors into a newly allocated
514 * string and return it. Used by dirserv operators to keep track of
515 * fast nodes that haven't registered.
517 char *
518 dirserver_getinfo_unregistered(const char *question)
520 int i;
521 router_status_t r;
522 smartlist_t *answerlist;
523 char buf[1024];
524 char *answer;
525 routerinfo_t *ent;
526 int min_bw = atoi(question);
527 smartlist_t *descriptor_list = get_descriptor_list();
529 if (!descriptor_list)
530 return tor_strdup("");
532 answerlist = smartlist_create();
533 for (i = 0; i < smartlist_len(descriptor_list); ++i) {
534 ent = smartlist_get(descriptor_list, i);
535 r = dirserv_router_get_status(ent, NULL);
536 if (ent->bandwidthcapacity >= (size_t)min_bw &&
537 ent->bandwidthrate >= (size_t)min_bw &&
538 r != FP_NAMED) {
539 /* then log this one */
540 tor_snprintf(buf, sizeof(buf),
541 "%s: BW %d on '%s'.",
542 ent->nickname, ent->bandwidthcapacity,
543 ent->platform ? ent->platform : "");
544 smartlist_add(answerlist, tor_strdup(buf));
547 answer = smartlist_join_strings(answerlist, "\r\n", 0, NULL);
548 SMARTLIST_FOREACH(answerlist, char *, cp, tor_free(cp));
549 smartlist_free(answerlist);
550 return answer;
553 /** Mark the directory as <b>dirty</b> -- when we're next asked for a
554 * directory, we will rebuild it instead of reusing the most recently
555 * generated one.
557 void
558 directory_set_dirty(void)
560 time_t now = time(NULL);
562 if (!the_directory_is_dirty)
563 the_directory_is_dirty = now;
564 if (!runningrouters_is_dirty)
565 runningrouters_is_dirty = now;
566 if (!the_v2_networkstatus_is_dirty)
567 the_v2_networkstatus_is_dirty = now;
571 * Allocate and return a description of the status of the server <b>desc</b>,
572 * for use in a router-status line. The server is listed
573 * as running iff <b>is_live</b> is true.
575 static char *
576 list_single_server_status(routerinfo_t *desc, int is_live)
578 char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
579 char *cp;
581 tor_assert(desc);
583 cp = buf;
584 if (!is_live) {
585 *cp++ = '!';
587 if (desc->is_verified) {
588 strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
589 cp += strlen(cp);
590 *cp++ = '=';
592 *cp++ = '$';
593 base16_encode(cp, HEX_DIGEST_LEN+1, desc->identity_digest,
594 DIGEST_LEN);
595 return tor_strdup(buf);
598 #define REACHABLE_TIMEOUT (60*60) /* an hour */
599 /* Make sure this is 3 times the value of get_dir_fetch_period() */
601 /** Treat a router as alive if
602 * - It's me, and I'm not hibernating.
603 * or - we're connected to it and we've found it reachable recently. */
604 static int
605 dirserv_thinks_router_is_reachable(routerinfo_t *router, time_t now)
607 connection_t *conn;
608 if (router_is_me(router) && !we_are_hibernating())
609 return 1;
610 conn = connection_get_by_identity_digest(router->identity_digest,
611 CONN_TYPE_OR);
612 if (conn && conn->state == OR_CONN_STATE_OPEN)
613 return get_options()->AssumeReachable ||
614 now < router->last_reachable + REACHABLE_TIMEOUT;
615 return 0;
618 /** Return 1 if we're confident that there's a problem with
619 * <b>router</b>'s reachability and its operator should be notified.
622 dirserv_thinks_router_is_blatantly_unreachable(routerinfo_t *router, time_t now)
624 connection_t *conn;
625 if (router->is_hibernating)
626 return 0;
627 conn = connection_get_by_identity_digest(router->identity_digest,
628 CONN_TYPE_OR);
629 if (conn && conn->state == OR_CONN_STATE_OPEN &&
630 now >= router->last_reachable + 2*REACHABLE_TIMEOUT &&
631 router->testing_since &&
632 now >= router->testing_since + 2*REACHABLE_TIMEOUT)
633 return 1;
634 return 0;
637 /** Based on the routerinfo_ts in <b>routers</b>, allocate the
638 * contents of a router-status line, and store it in
639 * *<b>router_status_out</b>. Return 0 on success, -1 on failure.
642 list_server_status(smartlist_t *routers, char **router_status_out)
644 /* List of entries in a router-status style: An optional !, then an optional
645 * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
646 smartlist_t *rs_entries;
647 time_t now = time(NULL);
648 int authdir_mode = get_options()->AuthoritativeDir;
649 tor_assert(router_status_out);
651 rs_entries = smartlist_create();
653 SMARTLIST_FOREACH(routers, routerinfo_t *, ri,
655 if (authdir_mode) {
656 /* Update router status in routerinfo_t. */
657 ri->is_running = dirserv_thinks_router_is_reachable(ri, now);
659 smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running));
662 *router_status_out = smartlist_join_strings(rs_entries, " ", 0, NULL);
664 SMARTLIST_FOREACH(rs_entries, char *, cp, tor_free(cp));
665 smartlist_free(rs_entries);
667 return 0;
670 /** Helper: Given pointers to two strings describing tor versions, return -1
671 * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
672 * Used to sort a list of versions. */
673 static int
674 _compare_tor_version_str_ptr(const void **_a, const void **_b)
676 const char *a = *_a, *b = *_b;
677 int ca, cb;
678 tor_version_t va, vb;
679 ca = tor_version_parse(a, &va);
680 cb = tor_version_parse(b, &vb);
681 /* If they both parse, compare them. */
682 if (!ca && !cb)
683 return tor_version_compare(&va,&vb);
684 /* If one parses, it comes first. */
685 if (!ca && cb)
686 return -1;
687 if (ca && !cb)
688 return 1;
689 /* If neither parses, compare strings. Also, the directory server admin needs
690 ** to be smacked upside the head. But Tor is tolerant and gentle. */
691 return strcmp(a,b);
694 /* Given a (possibly empty) list of config_line_t, each line of which contains
695 * a list of comma-separated version numbers surrounded by optional space,
696 * allocate and return a new string containing the version numbers, in order,
697 * separated by commas. Used to generate Recommended(Client|Server)?Versions
699 static char *
700 format_versions_list(config_line_t *ln)
702 smartlist_t *versions;
703 char *result;
704 versions = smartlist_create();
705 for ( ; ln; ln = ln->next) {
706 smartlist_split_string(versions, ln->value, ",",
707 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
709 smartlist_sort(versions, _compare_tor_version_str_ptr);
710 result = smartlist_join_strings(versions,",",0,NULL);
711 SMARTLIST_FOREACH(versions,char *,s,tor_free(s));
712 smartlist_free(versions);
713 return result;
716 /** Generate a new directory and write it into a newly allocated string.
717 * Point *<b>dir_out</b> to the allocated string. Sign the
718 * directory with <b>private_key</b>. Return 0 on success, -1 on
719 * failure.
722 dirserv_dump_directory_to_string(char **dir_out,
723 crypto_pk_env_t *private_key)
725 char *router_status;
726 char *identity_pkey; /* Identity key, DER64-encoded. */
727 char *recommended_versions;
728 char digest[DIGEST_LEN];
729 char published[ISO_TIME_LEN+1];
730 time_t published_on;
731 char *buf = NULL;
732 size_t buf_len;
733 size_t identity_pkey_len;
734 smartlist_t *descriptor_list = get_descriptor_list();
736 tor_assert(dir_out);
737 *dir_out = NULL;
739 if (!descriptor_list)
740 return -1;
742 if (list_server_status(descriptor_list, &router_status))
743 return -1;
745 if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,
746 &identity_pkey_len)<0) {
747 log_fn(LOG_WARN,"write identity_pkey to string failed!");
748 return -1;
751 recommended_versions = format_versions_list(get_options()->RecommendedVersions);
753 published_on = time(NULL);
754 format_iso_time(published, published_on);
756 buf_len = 2048+strlen(recommended_versions)+
757 strlen(router_status);
758 SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
759 buf_len += ri->signed_descriptor_len);
760 buf = tor_malloc(buf_len);
761 /* We'll be comparing against buf_len throughout the rest of the
762 function, though strictly speaking we shouldn't be able to exceed
763 it. This is C, after all, so we may as well check for buffer
764 overruns.*/
766 tor_snprintf(buf, buf_len,
767 "signed-directory\n"
768 "published %s\n"
769 "recommended-software %s\n"
770 "router-status %s\n"
771 "dir-signing-key\n%s\n",
772 published, recommended_versions, router_status,
773 identity_pkey);
775 tor_free(recommended_versions);
776 tor_free(router_status);
777 tor_free(identity_pkey);
779 SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
780 if (strlcat(buf, ri->signed_descriptor, buf_len) >= buf_len)
781 goto truncated);
783 /* These multiple strlcat calls are inefficient, but dwarfed by the RSA
784 signature.
786 if (strlcat(buf, "directory-signature ", buf_len) >= buf_len)
787 goto truncated;
788 if (strlcat(buf, get_options()->Nickname, buf_len) >= buf_len)
789 goto truncated;
790 if (strlcat(buf, "\n", buf_len) >= buf_len)
791 goto truncated;
793 if (router_get_dir_hash(buf,digest)) {
794 log_fn(LOG_WARN,"couldn't compute digest");
795 tor_free(buf);
796 return -1;
798 if (router_append_dirobj_signature(buf,buf_len,digest,private_key)<0) {
799 tor_free(buf);
800 return -1;
803 *dir_out = buf;
804 return 0;
805 truncated:
806 log_fn(LOG_WARN,"tried to exceed string length.");
807 tor_free(buf);
808 return -1;
811 /** Most recently generated encoded signed directory. (auth dirservers only.)*/
812 static cached_dir_t the_directory = { NULL, NULL, 0, 0, 0 };
814 /* Used only by non-auth dirservers: The directory and runningrouters we'll
815 * serve when requested. */
816 static cached_dir_t cached_directory = { NULL, NULL, 0, 0, 0 };
817 static cached_dir_t cached_runningrouters = { NULL, NULL, 0, 0, 0 };
819 /* Used for other dirservers' v2 network statuses. Map from hexdigest to
820 * cached_dir_t. */
821 static strmap_t *cached_v2_networkstatus = NULL;
823 /** Possibly replace the contents of <b>d</b> with the value of
824 * <b>directory</b> published on <b>when</b>, unless <b>when</b> is older than
825 * the last value, or too far in the future.
827 * Does not copy <b>directory</b>; free it if it isn't used.
829 static void
830 set_cached_dir(cached_dir_t *d, char *directory, time_t when)
832 time_t now = time(NULL);
833 if (when<=d->published) {
834 log_fn(LOG_INFO, "Ignoring old directory; not caching.");
835 tor_free(directory);
836 } else if (when>=now+ROUTER_MAX_AGE) {
837 log_fn(LOG_INFO, "Ignoring future directory; not caching.");
838 tor_free(directory);
839 } else {
840 /* if (when>d->published && when<now+ROUTER_MAX_AGE) */
841 log_fn(LOG_DEBUG, "Caching directory.");
842 tor_free(d->dir);
843 d->dir = directory;
844 d->dir_len = strlen(directory);
845 tor_free(d->dir_z);
846 if (tor_gzip_compress(&(d->dir_z), &(d->dir_z_len), d->dir, d->dir_len,
847 ZLIB_METHOD)) {
848 log_fn(LOG_WARN,"Error compressing cached directory");
850 d->published = when;
854 /** Remove all storage held in <b>d</b>, but do not free <b>d</b> itself. */
855 static void
856 clear_cached_dir(cached_dir_t *d)
858 tor_free(d->dir);
859 tor_free(d->dir_z);
860 memset(d, 0, sizeof(cached_dir_t));
863 /** Free all storage held by the cached_dir_t in <b>d</b>. */
864 static void
865 free_cached_dir(void *_d)
867 cached_dir_t *d = (cached_dir_t *)_d;
868 clear_cached_dir(d);
869 tor_free(d);
872 /** If we have no cached directory, or it is older than <b>when</b>, then
873 * replace it with <b>directory</b>, published at <b>when</b>.
875 void
876 dirserv_set_cached_directory(const char *directory, time_t published,
877 int is_running_routers)
879 cached_dir_t *d;
880 d = is_running_routers ? &cached_runningrouters : &cached_directory;
881 set_cached_dir(d, tor_strdup(directory), published);
884 /** We've just received a v2 network-status for an authoritative directory
885 * with fingerprint <b>fp</b> (hex digest, no spaces), published at
886 * <b>published</b>. Store it so we can serve it to others. If
887 * <b>directory</b> is NULL, remove the entry with the given fingerprint from
888 * the cache.
890 void
891 dirserv_set_cached_networkstatus_v2(const char *directory, const char *fp,
892 time_t published)
894 cached_dir_t *d;
895 if (!cached_v2_networkstatus)
896 cached_v2_networkstatus = strmap_new();
898 tor_assert(strlen(fp) == HEX_DIGEST_LEN);
900 if (!(d = strmap_get(cached_v2_networkstatus, fp))) {
901 if (!directory)
902 return;
903 d = tor_malloc_zero(sizeof(cached_dir_t));
904 strmap_set(cached_v2_networkstatus, fp, d);
907 tor_assert(d);
908 if (directory) {
909 set_cached_dir(d, tor_strdup(directory), published);
910 } else {
911 free_cached_dir(d);
912 strmap_remove(cached_v2_networkstatus, fp);
916 /** Helper: If we're an authority for the right directory version (the
917 * directory version is determined by <b>is_v1_object</b>), try to regenerate
918 * auth_src as appropriate and return it, falling back to cache_src on
919 * failure. If we're a cache, return cach_src.
921 static cached_dir_t *
922 dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
923 cached_dir_t *auth_src,
924 time_t dirty, int (*regenerate)(void),
925 const char *name,
926 int is_v1_object)
928 int authority = get_options()->AuthoritativeDir &&
929 (!is_v1_object || get_options()->V1AuthoritativeDir);
931 if (!authority) {
932 return cache_src;
933 } else {
934 /* We're authoritative. */
935 if (regenerate != NULL) {
936 if (dirty && dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
937 if (regenerate()) {
938 log_fn(LOG_ERR, "Couldn't generate %s?", name);
939 exit(1);
941 } else {
942 log_fn(LOG_INFO, "The %s is still clean; reusing.", name);
945 return auth_src ? auth_src : cache_src;
949 /** Helper: If we're authoritative and <b>auth_src</b> is set, use
950 * <b>auth_src</b>, otherwise use <b>cache_src</b>. If we're using
951 * <b>auth_src</b> and it's been <b>dirty</b> for at least
952 * DIR_REGEN_SLACK_TIME seconds, call <b>regenerate</b>() to make a fresh one.
953 * Yields the compressed version of the directory object if <b>compress</b> is
954 * set; otherwise return the uncompressed version. (In either case, sets
955 * *<b>out</b> and returns the size of the buffer in *<b>out</b>.)
957 * Use <b>is_v1_object</b> to help determine whether we're authoritative for
958 * this kind of object.
960 static size_t
961 dirserv_get_obj(const char **out, int compress,
962 cached_dir_t *cache_src,
963 cached_dir_t *auth_src,
964 time_t dirty, int (*regenerate)(void),
965 const char *name,
966 int is_v1_object)
968 cached_dir_t *d = dirserv_pick_cached_dir_obj(
969 cache_src, auth_src,
970 dirty, regenerate, name, is_v1_object);
972 if (!d)
973 return 0;
974 *out = compress ? d->dir_z : d->dir;
975 if (*out) {
976 return compress ? d->dir_z_len : d->dir_len;
977 } else {
978 /* not yet available. */
979 return 0;
983 /** Set *<b>directory</b> to the most recently generated encoded signed
984 * directory, generating a new one as necessary. If not an authoritative
985 * directory may return 0 if no directory is yet cached.*/
986 size_t
987 dirserv_get_directory(const char **directory, int compress)
989 return dirserv_get_obj(directory, compress,
990 &cached_directory, &the_directory,
991 the_directory_is_dirty,
992 dirserv_regenerate_directory,
993 "server directory", 1);
997 * Generate a fresh directory (authdirservers only.)
999 static int
1000 dirserv_regenerate_directory(void)
1002 char *new_directory=NULL;
1004 if (dirserv_dump_directory_to_string(&new_directory,
1005 get_identity_key())) {
1006 log(LOG_WARN, "Error creating directory.");
1007 tor_free(new_directory);
1008 return -1;
1010 set_cached_dir(&the_directory, new_directory, time(NULL));
1011 log_fn(LOG_INFO,"New directory (size %d):\n%s",(int)the_directory.dir_len,
1012 the_directory.dir);
1014 the_directory_is_dirty = 0;
1016 /* Save the directory to disk so we re-load it quickly on startup.
1018 dirserv_set_cached_directory(the_directory.dir, time(NULL), 0);
1020 return 0;
1023 /** For authoritative directories: the current (v1) network status */
1024 static cached_dir_t the_runningrouters = { NULL, NULL, 0, 0, 0 };
1026 /** Replace the current running-routers list with a newly generated one. */
1027 static int
1028 generate_runningrouters(void)
1030 char *s=NULL;
1031 char *router_status=NULL;
1032 char digest[DIGEST_LEN];
1033 char published[ISO_TIME_LEN+1];
1034 size_t len;
1035 crypto_pk_env_t *private_key = get_identity_key();
1036 char *identity_pkey; /* Identity key, DER64-encoded. */
1037 size_t identity_pkey_len;
1038 smartlist_t *descriptor_list = get_descriptor_list();
1040 if (list_server_status(descriptor_list, &router_status)) {
1041 goto err;
1043 if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,
1044 &identity_pkey_len)<0) {
1045 log_fn(LOG_WARN,"write identity_pkey to string failed!");
1046 goto err;
1048 format_iso_time(published, time(NULL));
1050 len = 2048+strlen(router_status);
1051 s = tor_malloc_zero(len);
1052 tor_snprintf(s, len,
1053 "network-status\n"
1054 "published %s\n"
1055 "router-status %s\n"
1056 "dir-signing-key\n%s"
1057 "directory-signature %s\n",
1058 published, router_status, identity_pkey, get_options()->Nickname);
1059 tor_free(router_status);
1060 tor_free(identity_pkey);
1061 if (router_get_runningrouters_hash(s,digest)) {
1062 log_fn(LOG_WARN,"couldn't compute digest");
1063 goto err;
1065 if (router_append_dirobj_signature(s, len, digest, private_key)<0)
1066 goto err;
1068 set_cached_dir(&the_runningrouters, s, time(NULL));
1069 runningrouters_is_dirty = 0;
1071 return 0;
1072 err:
1073 tor_free(s);
1074 tor_free(router_status);
1075 return -1;
1078 /** Set *<b>rr</b> to the most recently generated encoded signed
1079 * running-routers list, generating a new one as necessary. Return the
1080 * size of the directory on success, and 0 on failure. */
1081 size_t
1082 dirserv_get_runningrouters(const char **rr, int compress)
1084 return dirserv_get_obj(rr, compress,
1085 &cached_runningrouters, &the_runningrouters,
1086 runningrouters_is_dirty,
1087 generate_runningrouters,
1088 "v1 network status list", 1);
1091 /** Return true iff <b>ri</b> is "useful as an exit node", meaning
1092 * it allows exit to at least one /8 address space for at least
1093 * one of ports 80, 443, and 6667. */
1094 static int
1095 router_is_general_exit(routerinfo_t *ri)
1097 static const int ports[] = { 80, 443, 6667 };
1098 int n_allowed = 0;
1099 int i;
1100 for (i = 0; i < 3; ++i) {
1101 struct addr_policy_t *policy = ri->exit_policy;
1102 for ( ; policy; policy = policy->next) {
1103 if (policy->prt_min > ports[i] || policy->prt_max < ports[i])
1104 continue; /* Doesn't cover our port. */
1105 if ((policy->msk & 0x00fffffful) != 0)
1106 continue; /* Narrower than a /8. */
1107 if ((policy->addr & 0xff000000ul) == 0x7f000000ul)
1108 continue; /* 127.x */
1109 /* We have a match that is at least a /8. */
1110 if (policy->policy_type == ADDR_POLICY_ACCEPT)
1111 ++n_allowed;
1112 break;
1115 return n_allowed > 0;
1118 /** For authoritative directories: the current (v2) network status */
1119 static cached_dir_t the_v2_networkstatus = { NULL, NULL, 0, 0, 0 };
1121 /** For authoritative directories only: replace the contents of
1122 * <b>the_v2_networkstatus</b> with a newly generated network status
1123 * object. */
1124 static int
1125 generate_v2_networkstatus(void)
1127 #define LONGEST_STATUS_FLAG_NAME_LEN 7
1128 #define N_STATUS_FLAGS 6
1129 #define RS_ENTRY_LEN \
1130 ( /* first line */ \
1131 MAX_NICKNAME_LEN+BASE64_DIGEST_LEN*2+ISO_TIME_LEN+INET_NTOA_BUF_LEN+ \
1132 5*2 /* ports */ + 10 /* punctuation */ + \
1133 /* second line */ \
1134 (LONGEST_STATUS_FLAG_NAME_LEN+1)*N_STATUS_FLAGS + 2)
1136 int r = -1;
1137 size_t len, identity_pkey_len;
1138 char *status = NULL, *client_versions = NULL, *server_versions = NULL,
1139 *identity_pkey = NULL, *hostname = NULL;
1140 char *outp, *endp;
1141 or_options_t *options = get_options();
1142 char fingerprint[FINGERPRINT_LEN+1];
1143 char ipaddr[INET_NTOA_BUF_LEN+1];
1144 char published[ISO_TIME_LEN];
1145 char digest[DIGEST_LEN];
1146 struct in_addr in;
1147 uint32_t addr;
1148 crypto_pk_env_t *private_key = get_identity_key();
1149 smartlist_t *descriptor_list = get_descriptor_list();
1150 time_t now = time(NULL);
1151 int naming = options->NamingAuthoritativeDir;
1152 int versioning = options->VersioningAuthoritativeDir;
1153 const char *contact;
1155 if (!descriptor_list) {
1156 log_fn(LOG_WARN, "Couldn't get router list.");
1157 goto done;
1160 if (resolve_my_address(options, &addr, &hostname)<0) {
1161 log_fn(LOG_WARN, "Couldn't resolve my hostname");
1162 goto done;
1164 in.s_addr = htonl(addr);
1165 tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
1167 format_iso_time(published, time(NULL));
1169 client_versions = format_versions_list(options->RecommendedClientVersions);
1170 server_versions = format_versions_list(options->RecommendedServerVersions);
1172 if (crypto_pk_write_public_key_to_string(private_key, &identity_pkey,
1173 &identity_pkey_len)<0) {
1174 log_fn(LOG_WARN,"Writing public key to string failed.");
1175 goto done;
1178 if (crypto_pk_get_fingerprint(private_key, fingerprint, 0)<0) {
1179 log_fn(LOG_ERR, "Error computing fingerprint");
1180 goto done;
1183 contact = get_options()->ContactInfo;
1184 if (!contact)
1185 contact = "(none)";
1187 len = 2048+strlen(client_versions)+strlen(server_versions)+identity_pkey_len*2;
1188 len += (RS_ENTRY_LEN)*smartlist_len(descriptor_list) ;
1190 status = tor_malloc(len);
1191 tor_snprintf(status, len,
1192 "network-status-version 2\n"
1193 "dir-source %s %s %d\n"
1194 "fingerprint %s\n"
1195 "contact %s\n"
1196 "published %s\n"
1197 "dir-options%s%s\n"
1198 "client-versions %s\n"
1199 "server-versions %s\n"
1200 "dir-signing-key\n%s\n",
1201 hostname, ipaddr, (int)options->DirPort,
1202 fingerprint,
1203 contact,
1204 published,
1205 naming ? " Names" : "",
1206 versioning ? " Versions" : "",
1207 client_versions,
1208 server_versions,
1209 identity_pkey);
1210 outp = status + strlen(status);
1211 endp = status + len;
1213 SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, {
1214 int f_exit = router_is_general_exit(ri);
1215 int f_stable = !router_is_unreliable(ri, 1, 0);
1216 int f_fast = !router_is_unreliable(ri, 0, 1);
1217 int f_running;
1218 int f_authority = router_digest_is_trusted_dir(ri->identity_digest);
1219 int f_named = naming && ri->is_named;
1220 int f_valid = ri->is_verified;
1221 char identity64[BASE64_DIGEST_LEN+1];
1222 char digest64[BASE64_DIGEST_LEN+1];
1223 if (options->AuthoritativeDir) {
1224 ri->is_running = dirserv_thinks_router_is_reachable(ri, now);
1226 f_running = ri->is_running;
1228 format_iso_time(published, ri->published_on);
1230 digest_to_base64(identity64, ri->identity_digest);
1231 digest_to_base64(digest64, ri->signed_descriptor_digest);
1233 in.s_addr = htonl(ri->addr);
1234 tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
1236 if (tor_snprintf(outp, endp-outp,
1237 "r %s %s %s %s %s %d %d\n"
1238 "s%s%s%s%s%s%s%s\n",
1239 ri->nickname,
1240 identity64,
1241 digest64,
1242 published,
1243 ipaddr,
1244 ri->or_port,
1245 ri->dir_port,
1246 f_authority?" Authority":"",
1247 f_exit?" Exit":"",
1248 f_fast?" Fast":"",
1249 f_named?" Named":"",
1250 f_stable?" Stable":"",
1251 f_running?" Running":"",
1252 f_valid?" Valid":"")<0) {
1253 log_fn(LOG_WARN, "Unable to print router status.");
1254 goto done;
1256 outp += strlen(outp);
1259 if (tor_snprintf(outp, endp-outp, "directory-signature %s\n",
1260 get_options()->Nickname)<0) {
1261 log_fn(LOG_WARN, "Unable to write signature line.");
1262 goto done;
1265 if (router_get_networkstatus_v2_hash(status, digest)<0) {
1266 log_fn(LOG_WARN, "Unable to hash network status");
1267 goto done;
1270 if (router_append_dirobj_signature(outp,endp-outp,digest,private_key)<0) {
1271 log_fn(LOG_WARN, "Unable to sign router status.");
1272 goto done;
1275 set_cached_dir(&the_v2_networkstatus, status, time(NULL));
1276 status = NULL; /* So it doesn't get double-freed. */
1277 the_v2_networkstatus_is_dirty = 0;
1278 router_set_networkstatus(the_v2_networkstatus.dir, time(NULL), NS_GENERATED,
1279 NULL);
1281 r = 0;
1282 done:
1283 tor_free(client_versions);
1284 tor_free(server_versions);
1285 tor_free(status);
1286 tor_free(hostname);
1287 tor_free(identity_pkey);
1288 return r;
1291 /** Look for a network status object as specified by <b>key</b>, which should
1292 * be either "authority" (to find a network status generated by us), a hex
1293 * identity digest (to find a network status generated by given directory), or
1294 * "all" (to return all the v2 network status objects we have, concatenated).
1295 * If <b>compress</b>, find the version compressed with zlib. Return 0 if
1296 * nothing was found; otherwise set *<b>directory</b> to the matching network
1297 * status and return its length.
1300 dirserv_get_networkstatus_v2(smartlist_t *result,
1301 const char *key)
1303 tor_assert(result);
1305 if (!cached_v2_networkstatus)
1306 cached_v2_networkstatus = strmap_new();
1308 if (!(strcmp(key,"authority"))) {
1309 if (get_options()->AuthoritativeDir) {
1310 cached_dir_t *d =
1311 dirserv_pick_cached_dir_obj(NULL,
1312 &the_v2_networkstatus,
1313 the_v2_networkstatus_is_dirty,
1314 generate_v2_networkstatus,
1315 "network status list", 0);
1316 log_fn(LOG_WARN, "Unable to generate an authoritative network stautus.");
1317 if (d)
1318 smartlist_add(result, d);
1320 } else if (!strcmp(key, "all")) {
1321 strmap_iter_t *iter = strmap_iter_init(cached_v2_networkstatus);
1322 while (!strmap_iter_done(iter)) {
1323 const char *fp;
1324 void *val;
1325 strmap_iter_get(iter, &fp, &val);
1326 smartlist_add(result, val);
1327 iter = strmap_iter_next(cached_v2_networkstatus, iter);
1329 if (smartlist_len(result) == 0)
1330 log_fn(LOG_WARN, "Client requested 'all' network status objects; we have none.");
1331 } else if (!strcmpstart(key, "fp/")) {
1332 smartlist_t *hexdigests = smartlist_create();
1333 dir_split_resource_into_fingerprints(key+3, hexdigests, NULL);
1334 SMARTLIST_FOREACH(hexdigests, char *, cp,
1336 cached_dir_t *cached;
1337 tor_strupper(cp);
1338 if (router_fingerprint_is_me(cp) &&
1339 get_options()->AuthoritativeDir &&
1340 the_v2_networkstatus_is_dirty &&
1341 the_v2_networkstatus_is_dirty + DIR_REGEN_SLACK_TIME < time(NULL))
1342 generate_v2_networkstatus();
1343 cached = strmap_get(cached_v2_networkstatus, cp);
1344 if (cached) {
1345 smartlist_add(result, cached);
1346 } else {
1347 log_fn(LOG_INFO, "Don't know about any network status with fingerprint '%s'", cp);
1349 tor_free(cp);
1351 smartlist_free(hexdigests);
1353 return 0;
1356 /** Add a routerinfo_t to <b>descs_out</b> for each router matching
1357 * <b>key</b>. The key should be either "/tor/server/authority" for our own
1358 * routerinfo; "/tor/server/all" for all the routerinfos we have,
1359 * concatenated; or "/tor/server/FP" where FP is a plus-separated sequence of
1360 * hex identity digests.
1362 void
1363 dirserv_get_routerdescs(smartlist_t *descs_out, const char *key)
1365 smartlist_t *complete_list = get_descriptor_list();
1366 if (!complete_list)
1367 return;
1369 if (!strcmp(key, "/tor/server/all")) {
1370 smartlist_add_all(descs_out, complete_list);
1371 } else if (!strcmp(key, "/tor/server/authority")) {
1372 routerinfo_t *ri = router_get_my_routerinfo();
1373 if (ri)
1374 smartlist_add(descs_out, ri);
1375 } else if (!strcmpstart(key, "/tor/server/fp/")) {
1376 smartlist_t *hexdigests = smartlist_create();
1377 smartlist_t *digests = smartlist_create();
1378 key += strlen("/tor/server/fp/");
1379 dir_split_resource_into_fingerprints(key, hexdigests, NULL);
1380 SMARTLIST_FOREACH(hexdigests, char *, cp,
1382 char *d;
1383 if (strlen(cp) != HEX_DIGEST_LEN)
1384 continue;
1385 d = tor_malloc_zero(DIGEST_LEN);
1386 base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN);
1387 tor_free(cp);
1388 smartlist_add(digests, d);
1390 smartlist_free(hexdigests);
1391 SMARTLIST_FOREACH(digests, const char *, d,
1393 if (router_digest_is_me(d)) {
1394 smartlist_add(descs_out, router_get_my_routerinfo());
1395 } else {
1396 routerinfo_t *ri = router_get_by_digest(d);
1397 if (ri)
1398 smartlist_add(descs_out,ri);
1401 SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
1402 smartlist_free(digests);
1406 /** Called when a TLS handshake has completed successfully with a
1407 * router listening at <b>address</b>:<b>or_port</b>, and has yielded
1408 * a certificate with digest <b>digest_rcvd</b> and nickname
1409 * <b>nickname_rcvd</b>. When this happens, it's clear that any other
1410 * descriptors for that address/port combination must be unusable:
1411 * delete them if they are not verified.
1413 * Also, if as_advertised is 1, then inform the reachability checker
1414 * that we could get to this guy.
1416 void
1417 dirserv_orconn_tls_done(const char *address,
1418 uint16_t or_port,
1419 const char *digest_rcvd,
1420 const char *nickname_rcvd,
1421 int as_advertised)
1423 int i;
1424 smartlist_t *descriptor_list = get_descriptor_list();
1425 tor_assert(address);
1426 tor_assert(digest_rcvd);
1427 tor_assert(nickname_rcvd);
1429 if (!descriptor_list)
1430 return;
1432 // XXXXNM We should really have a better solution here than dropping
1433 // XXXXNM whole routers; otherwise, they come back way too easily.
1434 for (i = 0; i < smartlist_len(descriptor_list); ++i) {
1435 routerinfo_t *ri = smartlist_get(descriptor_list, i);
1436 int drop = 0;
1437 if (strcasecmp(address, ri->address) || or_port != ri->or_port)
1438 continue;
1439 if (!ri->is_verified) {
1440 /* We have a router at the same address! */
1441 if (strcasecmp(ri->nickname, nickname_rcvd)) {
1442 log_fn(LOG_NOTICE, "Dropping descriptor: nickname '%s' does not match nickname '%s' in cert from %s:%d",
1443 ri->nickname, nickname_rcvd, address, or_port);
1444 drop = 1;
1445 } else if (memcmp(ri->identity_digest, digest_rcvd, DIGEST_LEN)) {
1446 log_fn(LOG_NOTICE, "Dropping descriptor: identity key does not match key in cert from %s:%d",
1447 address, or_port);
1448 drop = 1;
1451 if (drop) {
1452 routerinfo_free(ri);
1453 smartlist_del(descriptor_list, i--);
1454 directory_set_dirty();
1455 } else { /* correct nickname and digest. mark this router reachable! */
1456 log_fn(LOG_INFO,"Found router %s to be reachable. Yay.", ri->nickname);
1457 ri->last_reachable = time(NULL);
1458 ri->num_unreachable_notifications = 0;
1463 /** Release all storage used by the directory server. */
1464 void
1465 dirserv_free_all(void)
1467 if (fingerprint_list) {
1468 SMARTLIST_FOREACH(fingerprint_list, fingerprint_entry_t*, fp,
1469 { tor_free(fp->nickname);
1470 tor_free(fp->fingerprint);
1471 tor_free(fp); });
1472 smartlist_free(fingerprint_list);
1473 fingerprint_list = NULL;
1475 if (authdir_reject_policy)
1476 addr_policy_free(authdir_reject_policy);
1477 if (authdir_invalid_policy)
1478 addr_policy_free(authdir_invalid_policy);
1479 clear_cached_dir(&the_directory);
1480 clear_cached_dir(&the_runningrouters);
1481 clear_cached_dir(&cached_directory);
1482 clear_cached_dir(&cached_runningrouters);
1483 if (cached_v2_networkstatus) {
1484 strmap_free(cached_v2_networkstatus, free_cached_dir);
1485 cached_v2_networkstatus = NULL;