Reformat inconsistent function declarations.
[tor.git] / src / or / dirserv.c
blob1dce850a34c442fdcc475a4ab05714e3ac94cec4
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)
55 addr_policy_t *n;
56 if (authdir_reject_policy) {
57 addr_policy_free(authdir_reject_policy);
58 authdir_reject_policy = NULL;
60 config_parse_addr_policy(get_options()->AuthDirReject,
61 &authdir_reject_policy, ADDR_POLICY_ACCEPT);
62 /* ports aren't used. */
63 for (n=authdir_reject_policy; n; n = n->next) {
64 n->prt_min = 1;
65 n->prt_max = 65535;
68 if (authdir_invalid_policy) {
69 addr_policy_free(authdir_invalid_policy);
70 authdir_invalid_policy = NULL;
72 config_parse_addr_policy(get_options()->AuthDirInvalid,
73 &authdir_invalid_policy, ADDR_POLICY_ACCEPT);
74 /* ports aren't used. */
75 for (n=authdir_invalid_policy; n; n = n->next) {
76 n->prt_min = 1;
77 n->prt_max = 65535;
81 typedef struct fingerprint_entry_t {
82 char *nickname;
83 char *fingerprint; /**< Stored as HEX_DIGEST_LEN characters, followed by a NUL */
84 } fingerprint_entry_t;
86 /** List of nickname-\>identity fingerprint mappings for all the routers
87 * that we recognize. Used to prevent Sybil attacks. */
88 /* Should be static; exposed for testing */
89 smartlist_t *fingerprint_list = NULL;
91 /** Add the fingerprint <b>fp</b> for the nickname <b>nickname</b> to
92 * the smartlist of fingerprint_entry_t's <b>list</b>. Return 0 if it's
93 * new, or 1 if we replaced the old value.
95 int /* Should be static; exposed for testing */
96 add_fingerprint_to_dir(const char *nickname, const char *fp, smartlist_t *list)
98 int i;
99 fingerprint_entry_t *ent;
100 char *fingerprint;
101 tor_assert(nickname);
102 tor_assert(fp);
103 tor_assert(list);
105 fingerprint = tor_strdup(fp);
106 tor_strstrip(fingerprint, " ");
108 for (i = 0; i < smartlist_len(list); ++i) {
109 ent = smartlist_get(list, i);
110 if (!strcasecmp(ent->nickname,nickname)) {
111 tor_free(ent->fingerprint);
112 ent->fingerprint = fingerprint;
113 return 1;
116 ent = tor_malloc(sizeof(fingerprint_entry_t));
117 ent->nickname = tor_strdup(nickname);
118 ent->fingerprint = fingerprint;
119 smartlist_add(list, ent);
120 return 0;
123 /** Add the nickname and fingerprint for this OR to the
124 * global list of recognized identity key fingerprints. */
126 dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk)
128 char fp[FINGERPRINT_LEN+1];
129 if (crypto_pk_get_fingerprint(pk, fp, 0)<0) {
130 log_fn(LOG_ERR, "Error computing fingerprint");
131 return -1;
133 if (!fingerprint_list)
134 fingerprint_list = smartlist_create();
135 add_fingerprint_to_dir(nickname, fp, fingerprint_list);
136 return 0;
139 /** Parse the nickname-\>fingerprint mappings stored in the file named
140 * <b>fname</b>. The file format is line-based, with each non-blank
141 * holding one nickname, some space, and a fingerprint for that
142 * nickname. On success, replace the current fingerprint list with
143 * the contents of <b>fname</b> and return 0. On failure, leave the
144 * current fingerprint list untouched, and return -1. */
146 dirserv_parse_fingerprint_file(const char *fname)
148 char *cf;
149 char *nickname, *fingerprint;
150 smartlist_t *fingerprint_list_new;
151 int result;
152 config_line_t *front=NULL, *list;
154 cf = read_file_to_str(fname, 0);
155 if (!cf) {
156 log_fn(LOG_WARN, "Cannot open fingerprint file %s", fname);
157 return -1;
159 result = config_get_lines(cf, &front);
160 tor_free(cf);
161 if (result < 0) {
162 log_fn(LOG_WARN, "Error reading from fingerprint file");
163 return -1;
166 fingerprint_list_new = smartlist_create();
168 for (list=front; list; list=list->next) {
169 nickname = list->key; fingerprint = list->value;
170 if (strlen(nickname) > MAX_NICKNAME_LEN) {
171 log(LOG_NOTICE, "Nickname '%s' too long in fingerprint file. Skipping.", nickname);
172 continue;
174 if (!is_legal_nickname(nickname) &&
175 strcasecmp(nickname, "!reject") &&
176 strcasecmp(nickname, "!invalid")) {
177 log(LOG_NOTICE, "Invalid nickname '%s' in fingerprint file. Skipping.", nickname);
178 continue;
180 if (strlen(fingerprint) != FINGERPRINT_LEN ||
181 !crypto_pk_check_fingerprint_syntax(fingerprint)) {
182 log_fn(LOG_NOTICE, "Invalid fingerprint (nickname '%s', fingerprint %s). Skipping.",
183 nickname, fingerprint);
184 continue;
186 if (0==strcasecmp(nickname, DEFAULT_CLIENT_NICKNAME)) {
187 /* If you approved an OR called "client", then clients who use
188 * the default nickname could all be rejected. That's no good. */
189 log(LOG_NOTICE,
190 "Authorizing a nickname '%s' would break many clients; skipping.",
191 DEFAULT_CLIENT_NICKNAME);
192 continue;
194 if (add_fingerprint_to_dir(nickname, fingerprint, fingerprint_list_new) != 0)
195 log(LOG_NOTICE, "Duplicate nickname '%s'.", nickname);
198 config_free_lines(front);
199 dirserv_free_fingerprint_list();
200 fingerprint_list = fingerprint_list_new;
201 /* Delete any routers whose fingerprints we no longer recognize */
202 directory_remove_invalid();
203 return 0;
206 /** Check whether <b>router</b> has a nickname/identity key combination that
207 * we recognize from the fingerprint list, or an IP we automatically act on
208 * according to our configuration. Return the appropriate router status.
210 * If the status is 'FP_REJECT' and <b>msg</b> is provided, set
211 * *<b>msg</b> to an explanation of why.
213 static router_status_t
214 dirserv_router_get_status(const routerinfo_t *router, const char **msg)
216 fingerprint_entry_t *nn_ent = NULL, *fp_ent = NULL;
217 char fp[FINGERPRINT_LEN+1];
219 if (!fingerprint_list)
220 fingerprint_list = smartlist_create();
222 if (crypto_pk_get_fingerprint(router->identity_pkey, fp, 0)) {
223 log_fn(LOG_WARN,"Error computing fingerprint");
224 return -1;
227 log_fn(LOG_DEBUG, "%d fingerprints known.", smartlist_len(fingerprint_list));
228 SMARTLIST_FOREACH(fingerprint_list, fingerprint_entry_t *, ent,
230 if (!strcasecmp(fp,ent->fingerprint))
231 fp_ent = ent;
232 if (!strcasecmp(router->nickname,ent->nickname))
233 nn_ent = ent;
236 if (fp_ent) {
237 if (!strcasecmp(fp_ent->nickname, "!reject")) {
238 if (msg)
239 *msg = "Fingerprint is marked rejected";
240 return FP_REJECT;
241 } else if (!strcasecmp(fp_ent->nickname, "!invalid")) {
242 if (msg)
243 *msg = "Fingerprint is marged invalid";
244 return FP_INVALID;
248 if (!nn_ent) { /* No such server known with that nickname */
249 addr_policy_result_t rej = router_compare_addr_to_addr_policy(
250 router->addr, router->or_port, authdir_reject_policy);
251 addr_policy_result_t inv = router_compare_addr_to_addr_policy(
252 router->addr, router->or_port, authdir_invalid_policy);
254 if (rej == ADDR_POLICY_PROBABLY_ACCEPTED || rej == ADDR_POLICY_ACCEPTED) {
255 log_fn(LOG_INFO, "Rejecting '%s' because of address %s",
256 router->nickname, router->address);
257 if (msg)
258 *msg = "Authdir is rejecting routers in this range.";
259 return FP_REJECT;
261 if (inv == ADDR_POLICY_PROBABLY_ACCEPTED || inv == ADDR_POLICY_ACCEPTED) {
262 log_fn(LOG_INFO, "Not marking '%s' valid because of address %s",
263 router->nickname, router->address);
264 return FP_INVALID;
266 if (tor_version_as_new_as(router->platform,"0.1.0.2-rc"))
267 return FP_VALID;
268 else
269 return FP_INVALID;
270 log_fn(LOG_INFO,"No fingerprint found for '%s'",router->nickname);
271 return 0;
273 if (0==strcasecmp(nn_ent->fingerprint, fp)) {
274 log_fn(LOG_DEBUG,"Good fingerprint for '%s'",router->nickname);
275 return FP_NAMED; /* Right fingerprint. */
276 } else {
277 log_fn(LOG_WARN,"Mismatched fingerprint for '%s': expected '%s' got '%s'. ContactInfo '%s', platform '%s'.)",
278 router->nickname, nn_ent->fingerprint, fp,
279 router->contact_info ? router->contact_info : "",
280 router->platform ? router->platform : "");
281 if (msg)
282 *msg = "Rejected: There is already a verified server with this nickname and a different fingerprint.";
283 return FP_REJECT; /* Wrong fingerprint. */
287 /** If we are an authoritative dirserver, and the list of approved
288 * servers contains one whose identity key digest is <b>digest</b>,
289 * return that router's nickname. Otherwise return NULL. */
290 const char *
291 dirserv_get_nickname_by_digest(const char *digest)
293 char hexdigest[HEX_DIGEST_LEN+1];
294 if (!fingerprint_list)
295 return NULL;
296 tor_assert(digest);
298 base16_encode(hexdigest, HEX_DIGEST_LEN+1, digest, DIGEST_LEN);
299 SMARTLIST_FOREACH(fingerprint_list, fingerprint_entry_t*, ent,
300 { if (!strcasecmp(hexdigest, ent->fingerprint))
301 return ent->nickname; } );
302 return NULL;
305 /** Clear the current fingerprint list. */
306 void
307 dirserv_free_fingerprint_list(void)
309 int i;
310 fingerprint_entry_t *ent;
311 if (!fingerprint_list)
312 return;
314 for (i = 0; i < smartlist_len(fingerprint_list); ++i) {
315 ent = smartlist_get(fingerprint_list, i);
316 tor_free(ent->nickname);
317 tor_free(ent->fingerprint);
318 tor_free(ent);
320 smartlist_free(fingerprint_list);
321 fingerprint_list = NULL;
325 * Descriptor list
328 static smartlist_t *
329 get_descriptor_list(void)
331 routerlist_t *routerlist;
332 router_get_routerlist(&routerlist);
333 if (!routerlist)
334 return NULL;
335 return routerlist->routers;
338 /** Return -1 if <b>ri</b> has a private or otherwise bad address,
339 * unless we're configured to not care. Return 0 if all ok. */
340 static int
341 dirserv_router_has_valid_address(routerinfo_t *ri)
343 struct in_addr iaddr;
344 if (get_options()->DirAllowPrivateAddresses)
345 return 0; /* whatever it is, we're fine with it */
346 if (!tor_inet_aton(ri->address, &iaddr)) {
347 log_fn(LOG_INFO,"Router '%s' published non-IP address '%s'. Refusing.",
348 ri->nickname, ri->address);
349 return -1;
351 if (is_internal_IP(ntohl(iaddr.s_addr))) {
352 log_fn(LOG_INFO,"Router '%s' published internal IP address '%s'. Refusing.",
353 ri->nickname, ri->address);
354 return -1; /* it's a private IP, we should reject it */
356 return 0;
359 /** Check whether we, as a directory server, want to accept <b>ri</b>. If so,
360 * return 0, and set its is_valid,named,running fields. Otherwise, return -1.
362 * If the router is rejected, set *<b>msg</b> to an explanation of why.
365 authdir_wants_to_reject_router(routerinfo_t *ri,
366 const char **msg)
368 /* Okay. Now check whether the fingerprint is recognized. */
369 router_status_t status = dirserv_router_get_status(ri, msg);
370 time_t now;
371 tor_assert(msg);
372 if (status == FP_REJECT)
373 return -1; /* msg is already set. */
375 /* Is there too much clock skew? */
376 now = time(NULL);
377 if (ri->published_on > now+ROUTER_ALLOW_SKEW) {
378 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').",
379 ri->nickname, (int)((ri->published_on-now)/60),
380 ri->contact_info ? ri->contact_info : "",
381 ri->platform ? ri->platform : "");
382 *msg = "Rejected: Your clock is set too far in the future, or your timezone is not correct.";
383 return -1;
385 if (ri->published_on < now-ROUTER_MAX_AGE) {
386 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').",
387 ri->nickname, (int)((now-ri->published_on)/60),
388 ri->contact_info ? ri->contact_info : "",
389 ri->platform ? ri->platform : "");
390 *msg = "Rejected: Server is expired, or your clock is too far in the past, or your timezone is not correct.";
391 return -1;
393 if (dirserv_router_has_valid_address(ri) < 0) {
394 log_fn(LOG_NOTICE, "Router with nickname '%s' has invalid address '%s'. Not adding (ContactInfo '%s', platform '%s').",
395 ri->nickname, ri->address,
396 ri->contact_info ? ri->contact_info : "",
397 ri->platform ? ri->platform : "");
398 *msg = "Rejected: Address is not an IP, or IP is a private address.";
399 return -1;
401 /* Okay, looks like we're willing to accept this one. */
402 switch (status) {
403 case FP_NAMED:
404 ri->is_named = ri->is_verified = 1;
405 break;
406 case FP_VALID:
407 ri->is_named = 0;
408 ri->is_verified = 1;
409 break;
410 case FP_INVALID:
411 ri->is_named = ri->is_verified = 0;
412 break;
413 default:
414 tor_assert(0);
417 return 0;
420 /** Parse the server descriptor at <b>desc</b> and maybe insert it into
421 * the list of server descriptors. Set *<b>msg</b> to a message that
422 * should be passed back to the origin of this descriptor.
424 * Return 2 if descriptor is well-formed and accepted;
425 * 1 if well-formed and accepted but origin should hear *msg;
426 * 0 if well-formed but redundant with one we already have;
427 * -1 if it looks vaguely like a router descriptor but rejected;
428 * -2 if we can't find a router descriptor in <b>desc</b>.
431 dirserv_add_descriptor(const char *desc, const char **msg)
433 int r;
434 routerinfo_t *ri = NULL;
435 tor_assert(msg);
436 *msg = NULL;
438 /* Check: is the descriptor syntactically valid? */
439 ri = router_parse_entry_from_string(desc, NULL);
440 if (!ri) {
441 log(LOG_WARN, "Couldn't parse descriptor");
442 *msg = "Rejected: Couldn't parse server descriptor.";
443 return -2;
445 if ((r = router_add_to_routerlist(ri, msg, 0))<0) {
446 return r == -1 ? 0 : -1;
447 } else {
448 smartlist_t *changed = smartlist_create();
449 smartlist_add(changed, ri);
450 control_event_descriptors_changed(changed);
451 smartlist_free(changed);
452 if (!*msg) {
453 *msg = ri->is_verified ? "Verified server descriptor accepted" :
454 "Unverified server descriptor accepted";
456 return r == 0 ? 2 : 1;
460 /** Remove all descriptors whose nicknames or fingerprints no longer
461 * are allowed by our fingerprint list. (Descriptors that used to be
462 * good can become bad when we reload the fingerprint list.)
464 static void
465 directory_remove_invalid(void)
467 int i;
468 int changed = 0;
469 smartlist_t *descriptor_list = get_descriptor_list();
471 if (!descriptor_list)
472 return;
474 for (i = 0; i < smartlist_len(descriptor_list); ++i) {
475 const char *msg;
476 routerinfo_t *ent = smartlist_get(descriptor_list, i);
477 router_status_t r = dirserv_router_get_status(ent, &msg);
478 switch (r) {
479 case FP_REJECT:
480 log(LOG_INFO, "Router '%s' is now rejected: %s",
481 ent->nickname, msg?msg:"");
482 routerinfo_free(ent);
483 smartlist_del(descriptor_list, i--);
484 changed = 1;
485 break;
486 case FP_NAMED:
487 if (!ent->is_verified || !ent->is_named) {
488 log(LOG_INFO, "Router '%s' is now verified and named.", ent->nickname);
489 ent->is_verified = ent->is_named = 1;
490 changed = 1;
492 break;
493 case FP_VALID:
494 if (!ent->is_verified || ent->is_named) {
495 log(LOG_INFO, "Router '%s' is now verified.", ent->nickname);
496 ent->is_verified = 1;
497 ent->is_named = 0;
498 changed = 1;
500 break;
501 case FP_INVALID:
502 if (ent->is_verified || ent->is_named) {
503 log(LOG_INFO, "Router '%s' is no longer verified.", ent->nickname);
504 ent->is_verified = ent->is_named = 0;
505 changed = 1;
507 break;
510 if (changed)
511 directory_set_dirty();
514 /** Write a list of unregistered descriptors into a newly allocated
515 * string and return it. Used by dirserv operators to keep track of
516 * fast nodes that haven't registered.
518 char *
519 dirserver_getinfo_unregistered(const char *question)
521 int i;
522 router_status_t r;
523 smartlist_t *answerlist;
524 char buf[1024];
525 char *answer;
526 routerinfo_t *ent;
527 int min_bw = atoi(question);
528 smartlist_t *descriptor_list = get_descriptor_list();
530 if (!descriptor_list)
531 return tor_strdup("");
533 answerlist = smartlist_create();
534 for (i = 0; i < smartlist_len(descriptor_list); ++i) {
535 ent = smartlist_get(descriptor_list, i);
536 r = dirserv_router_get_status(ent, NULL);
537 if (ent->bandwidthcapacity >= (size_t)min_bw &&
538 ent->bandwidthrate >= (size_t)min_bw &&
539 r != FP_NAMED) {
540 /* then log this one */
541 tor_snprintf(buf, sizeof(buf),
542 "%s: BW %d on '%s'.",
543 ent->nickname, ent->bandwidthcapacity,
544 ent->platform ? ent->platform : "");
545 smartlist_add(answerlist, tor_strdup(buf));
548 answer = smartlist_join_strings(answerlist, "\r\n", 0, NULL);
549 SMARTLIST_FOREACH(answerlist, char *, cp, tor_free(cp));
550 smartlist_free(answerlist);
551 return answer;
554 /** Mark the directory as <b>dirty</b> -- when we're next asked for a
555 * directory, we will rebuild it instead of reusing the most recently
556 * generated one.
558 void
559 directory_set_dirty(void)
561 time_t now = time(NULL);
563 if (!the_directory_is_dirty)
564 the_directory_is_dirty = now;
565 if (!runningrouters_is_dirty)
566 runningrouters_is_dirty = now;
567 if (!the_v2_networkstatus_is_dirty)
568 the_v2_networkstatus_is_dirty = now;
572 * Allocate and return a description of the status of the server <b>desc</b>,
573 * for use in a router-status line. The server is listed
574 * as running iff <b>is_live</b> is true.
576 static char *
577 list_single_server_status(routerinfo_t *desc, int is_live)
579 char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
580 char *cp;
582 tor_assert(desc);
584 cp = buf;
585 if (!is_live) {
586 *cp++ = '!';
588 if (desc->is_verified) {
589 strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
590 cp += strlen(cp);
591 *cp++ = '=';
593 *cp++ = '$';
594 base16_encode(cp, HEX_DIGEST_LEN+1, desc->identity_digest,
595 DIGEST_LEN);
596 return tor_strdup(buf);
599 #define REACHABLE_TIMEOUT (60*60) /* an hour */
600 /* Make sure this is 3 times the value of get_dir_fetch_period() */
602 /** Treat a router as alive if
603 * - It's me, and I'm not hibernating.
604 * or - we're connected to it and we've found it reachable recently. */
605 static int
606 dirserv_thinks_router_is_reachable(routerinfo_t *router, time_t now)
608 connection_t *conn;
609 if (router_is_me(router) && !we_are_hibernating())
610 return 1;
611 conn = connection_get_by_identity_digest(router->identity_digest,
612 CONN_TYPE_OR);
613 if (conn && conn->state == OR_CONN_STATE_OPEN)
614 return get_options()->AssumeReachable ||
615 now < router->last_reachable + REACHABLE_TIMEOUT;
616 return 0;
619 /** Return 1 if we're confident that there's a problem with
620 * <b>router</b>'s reachability and its operator should be notified.
623 dirserv_thinks_router_is_blatantly_unreachable(routerinfo_t *router, time_t now)
625 connection_t *conn;
626 if (router->is_hibernating)
627 return 0;
628 conn = connection_get_by_identity_digest(router->identity_digest,
629 CONN_TYPE_OR);
630 if (conn && conn->state == OR_CONN_STATE_OPEN &&
631 now >= router->last_reachable + 2*REACHABLE_TIMEOUT &&
632 router->testing_since &&
633 now >= router->testing_since + 2*REACHABLE_TIMEOUT)
634 return 1;
635 return 0;
638 /** Based on the routerinfo_ts in <b>routers</b>, allocate the
639 * contents of a router-status line, and store it in
640 * *<b>router_status_out</b>. Return 0 on success, -1 on failure.
643 list_server_status(smartlist_t *routers, char **router_status_out)
645 /* List of entries in a router-status style: An optional !, then an optional
646 * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
647 smartlist_t *rs_entries;
648 time_t now = time(NULL);
649 int authdir_mode = get_options()->AuthoritativeDir;
650 tor_assert(router_status_out);
652 rs_entries = smartlist_create();
654 SMARTLIST_FOREACH(routers, routerinfo_t *, ri,
656 if (authdir_mode) {
657 /* Update router status in routerinfo_t. */
658 ri->is_running = dirserv_thinks_router_is_reachable(ri, now);
660 smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running));
663 *router_status_out = smartlist_join_strings(rs_entries, " ", 0, NULL);
665 SMARTLIST_FOREACH(rs_entries, char *, cp, tor_free(cp));
666 smartlist_free(rs_entries);
668 return 0;
671 /** Helper: Given pointers to two strings describing tor versions, return -1
672 * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
673 * Used to sort a list of versions. */
674 static int
675 _compare_tor_version_str_ptr(const void **_a, const void **_b)
677 const char *a = *_a, *b = *_b;
678 int ca, cb;
679 tor_version_t va, vb;
680 ca = tor_version_parse(a, &va);
681 cb = tor_version_parse(b, &vb);
682 /* If they both parse, compare them. */
683 if (!ca && !cb)
684 return tor_version_compare(&va,&vb);
685 /* If one parses, it comes first. */
686 if (!ca && cb)
687 return -1;
688 if (ca && !cb)
689 return 1;
690 /* If neither parses, compare strings. Also, the directory server admin needs
691 ** to be smacked upside the head. But Tor is tolerant and gentle. */
692 return strcmp(a,b);
695 /* Given a (possibly empty) list of config_line_t, each line of which contains
696 * a list of comma-separated version numbers surrounded by optional space,
697 * allocate and return a new string containing the version numbers, in order,
698 * separated by commas. Used to generate Recommended(Client|Server)?Versions
700 static char *
701 format_versions_list(config_line_t *ln)
703 smartlist_t *versions;
704 char *result;
705 versions = smartlist_create();
706 for ( ; ln; ln = ln->next) {
707 smartlist_split_string(versions, ln->value, ",",
708 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
710 smartlist_sort(versions, _compare_tor_version_str_ptr);
711 result = smartlist_join_strings(versions,",",0,NULL);
712 SMARTLIST_FOREACH(versions,char *,s,tor_free(s));
713 smartlist_free(versions);
714 return result;
717 /** Generate a new directory and write it into a newly allocated string.
718 * Point *<b>dir_out</b> to the allocated string. Sign the
719 * directory with <b>private_key</b>. Return 0 on success, -1 on
720 * failure.
723 dirserv_dump_directory_to_string(char **dir_out,
724 crypto_pk_env_t *private_key)
726 char *router_status;
727 char *identity_pkey; /* Identity key, DER64-encoded. */
728 char *recommended_versions;
729 char digest[DIGEST_LEN];
730 char published[ISO_TIME_LEN+1];
731 time_t published_on;
732 char *buf = NULL;
733 size_t buf_len;
734 size_t identity_pkey_len;
735 smartlist_t *descriptor_list = get_descriptor_list();
737 tor_assert(dir_out);
738 *dir_out = NULL;
740 if (!descriptor_list)
741 return -1;
743 if (list_server_status(descriptor_list, &router_status))
744 return -1;
746 if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,
747 &identity_pkey_len)<0) {
748 log_fn(LOG_WARN,"write identity_pkey to string failed!");
749 return -1;
752 recommended_versions = format_versions_list(get_options()->RecommendedVersions);
754 published_on = time(NULL);
755 format_iso_time(published, published_on);
757 buf_len = 2048+strlen(recommended_versions)+
758 strlen(router_status);
759 SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
760 buf_len += ri->signed_descriptor_len);
761 buf = tor_malloc(buf_len);
762 /* We'll be comparing against buf_len throughout the rest of the
763 function, though strictly speaking we shouldn't be able to exceed
764 it. This is C, after all, so we may as well check for buffer
765 overruns.*/
767 tor_snprintf(buf, buf_len,
768 "signed-directory\n"
769 "published %s\n"
770 "recommended-software %s\n"
771 "router-status %s\n"
772 "dir-signing-key\n%s\n",
773 published, recommended_versions, router_status,
774 identity_pkey);
776 tor_free(recommended_versions);
777 tor_free(router_status);
778 tor_free(identity_pkey);
780 SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
781 if (strlcat(buf, ri->signed_descriptor, buf_len) >= buf_len)
782 goto truncated);
784 /* These multiple strlcat calls are inefficient, but dwarfed by the RSA
785 signature.
787 if (strlcat(buf, "directory-signature ", buf_len) >= buf_len)
788 goto truncated;
789 if (strlcat(buf, get_options()->Nickname, buf_len) >= buf_len)
790 goto truncated;
791 if (strlcat(buf, "\n", buf_len) >= buf_len)
792 goto truncated;
794 if (router_get_dir_hash(buf,digest)) {
795 log_fn(LOG_WARN,"couldn't compute digest");
796 tor_free(buf);
797 return -1;
799 if (router_append_dirobj_signature(buf,buf_len,digest,private_key)<0) {
800 tor_free(buf);
801 return -1;
804 *dir_out = buf;
805 return 0;
806 truncated:
807 log_fn(LOG_WARN,"tried to exceed string length.");
808 tor_free(buf);
809 return -1;
812 /** Most recently generated encoded signed directory. (auth dirservers only.)*/
813 static cached_dir_t the_directory = { NULL, NULL, 0, 0, 0 };
815 /* Used only by non-auth dirservers: The directory and runningrouters we'll
816 * serve when requested. */
817 static cached_dir_t cached_directory = { NULL, NULL, 0, 0, 0 };
818 static cached_dir_t cached_runningrouters = { NULL, NULL, 0, 0, 0 };
820 /* Used for other dirservers' v2 network statuses. Map from hexdigest to
821 * cached_dir_t. */
822 static strmap_t *cached_v2_networkstatus = NULL;
824 /** Possibly replace the contents of <b>d</b> with the value of
825 * <b>directory</b> published on <b>when</b>, unless <b>when</b> is older than
826 * the last value, or too far in the future.
828 * Does not copy <b>directory</b>; free it if it isn't used.
830 static void
831 set_cached_dir(cached_dir_t *d, char *directory, time_t when)
833 time_t now = time(NULL);
834 if (when<=d->published) {
835 log_fn(LOG_INFO, "Ignoring old directory; not caching.");
836 tor_free(directory);
837 } else if (when>=now+ROUTER_MAX_AGE) {
838 log_fn(LOG_INFO, "Ignoring future directory; not caching.");
839 tor_free(directory);
840 } else {
841 /* if (when>d->published && when<now+ROUTER_MAX_AGE) */
842 log_fn(LOG_DEBUG, "Caching directory.");
843 tor_free(d->dir);
844 d->dir = directory;
845 d->dir_len = strlen(directory);
846 tor_free(d->dir_z);
847 if (tor_gzip_compress(&(d->dir_z), &(d->dir_z_len), d->dir, d->dir_len,
848 ZLIB_METHOD)) {
849 log_fn(LOG_WARN,"Error compressing cached directory");
851 d->published = when;
855 /** Remove all storage held in <b>d</b>, but do not free <b>d</b> itself. */
856 static void
857 clear_cached_dir(cached_dir_t *d)
859 tor_free(d->dir);
860 tor_free(d->dir_z);
861 memset(d, 0, sizeof(cached_dir_t));
864 /** Free all storage held by the cached_dir_t in <b>d</b>. */
865 static void
866 free_cached_dir(void *_d)
868 cached_dir_t *d = (cached_dir_t *)_d;
869 clear_cached_dir(d);
870 tor_free(d);
873 /** If we have no cached directory, or it is older than <b>when</b>, then
874 * replace it with <b>directory</b>, published at <b>when</b>.
876 void
877 dirserv_set_cached_directory(const char *directory, time_t published,
878 int is_running_routers)
880 cached_dir_t *d;
881 d = is_running_routers ? &cached_runningrouters : &cached_directory;
882 set_cached_dir(d, tor_strdup(directory), published);
885 /** We've just received a v2 network-status for an authoritative directory
886 * with fingerprint <b>fp</b> (hex digest, no spaces), published at
887 * <b>published</b>. Store it so we can serve it to others. If
888 * <b>directory</b> is NULL, remove the entry with the given fingerprint from
889 * the cache.
891 void
892 dirserv_set_cached_networkstatus_v2(const char *directory, const char *fp,
893 time_t published)
895 cached_dir_t *d;
896 if (!cached_v2_networkstatus)
897 cached_v2_networkstatus = strmap_new();
899 tor_assert(strlen(fp) == HEX_DIGEST_LEN);
901 if (!(d = strmap_get(cached_v2_networkstatus, fp))) {
902 if (!directory)
903 return;
904 d = tor_malloc_zero(sizeof(cached_dir_t));
905 strmap_set(cached_v2_networkstatus, fp, d);
908 tor_assert(d);
909 if (directory) {
910 set_cached_dir(d, tor_strdup(directory), published);
911 } else {
912 free_cached_dir(d);
913 strmap_remove(cached_v2_networkstatus, fp);
917 /** Helper: If we're an authority for the right directory version (the
918 * directory version is determined by <b>is_v1_object</b>), try to regenerate
919 * auth_src as appropriate and return it, falling back to cache_src on
920 * failure. If we're a cache, return cach_src.
922 static cached_dir_t *
923 dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
924 cached_dir_t *auth_src,
925 time_t dirty, int (*regenerate)(void),
926 const char *name,
927 int is_v1_object)
929 int authority = get_options()->AuthoritativeDir &&
930 (!is_v1_object || get_options()->V1AuthoritativeDir);
932 if (!authority) {
933 return cache_src;
934 } else {
935 /* We're authoritative. */
936 if (regenerate != NULL) {
937 if (dirty && dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
938 if (regenerate()) {
939 log_fn(LOG_ERR, "Couldn't generate %s?", name);
940 exit(1);
942 } else {
943 log_fn(LOG_INFO, "The %s is still clean; reusing.", name);
946 return auth_src ? auth_src : cache_src;
950 /** Helper: If we're authoritative and <b>auth_src</b> is set, use
951 * <b>auth_src</b>, otherwise use <b>cache_src</b>. If we're using
952 * <b>auth_src</b> and it's been <b>dirty</b> for at least
953 * DIR_REGEN_SLACK_TIME seconds, call <b>regenerate</b>() to make a fresh one.
954 * Yields the compressed version of the directory object if <b>compress</b> is
955 * set; otherwise return the uncompressed version. (In either case, sets
956 * *<b>out</b> and returns the size of the buffer in *<b>out</b>.)
958 * Use <b>is_v1_object</b> to help determine whether we're authoritative for
959 * this kind of object.
961 static size_t
962 dirserv_get_obj(const char **out, int compress,
963 cached_dir_t *cache_src,
964 cached_dir_t *auth_src,
965 time_t dirty, int (*regenerate)(void),
966 const char *name,
967 int is_v1_object)
969 cached_dir_t *d = dirserv_pick_cached_dir_obj(
970 cache_src, auth_src,
971 dirty, regenerate, name, is_v1_object);
973 if (!d)
974 return 0;
975 *out = compress ? d->dir_z : d->dir;
976 if (*out) {
977 return compress ? d->dir_z_len : d->dir_len;
978 } else {
979 /* not yet available. */
980 return 0;
984 /** Set *<b>directory</b> to the most recently generated encoded signed
985 * directory, generating a new one as necessary. If not an authoritative
986 * directory may return 0 if no directory is yet cached.*/
987 size_t
988 dirserv_get_directory(const char **directory, int compress)
990 return dirserv_get_obj(directory, compress,
991 &cached_directory, &the_directory,
992 the_directory_is_dirty,
993 dirserv_regenerate_directory,
994 "server directory", 1);
998 * Generate a fresh directory (authdirservers only.)
1000 static int
1001 dirserv_regenerate_directory(void)
1003 char *new_directory=NULL;
1005 if (dirserv_dump_directory_to_string(&new_directory,
1006 get_identity_key())) {
1007 log(LOG_WARN, "Error creating directory.");
1008 tor_free(new_directory);
1009 return -1;
1011 set_cached_dir(&the_directory, new_directory, time(NULL));
1012 log_fn(LOG_INFO,"New directory (size %d):\n%s",(int)the_directory.dir_len,
1013 the_directory.dir);
1015 the_directory_is_dirty = 0;
1017 /* Save the directory to disk so we re-load it quickly on startup.
1019 dirserv_set_cached_directory(the_directory.dir, time(NULL), 0);
1021 return 0;
1024 /** For authoritative directories: the current (v1) network status */
1025 static cached_dir_t the_runningrouters = { NULL, NULL, 0, 0, 0 };
1027 /** Replace the current running-routers list with a newly generated one. */
1028 static int
1029 generate_runningrouters(void)
1031 char *s=NULL;
1032 char *router_status=NULL;
1033 char digest[DIGEST_LEN];
1034 char published[ISO_TIME_LEN+1];
1035 size_t len;
1036 crypto_pk_env_t *private_key = get_identity_key();
1037 char *identity_pkey; /* Identity key, DER64-encoded. */
1038 size_t identity_pkey_len;
1039 smartlist_t *descriptor_list = get_descriptor_list();
1041 if (list_server_status(descriptor_list, &router_status)) {
1042 goto err;
1044 if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,
1045 &identity_pkey_len)<0) {
1046 log_fn(LOG_WARN,"write identity_pkey to string failed!");
1047 goto err;
1049 format_iso_time(published, time(NULL));
1051 len = 2048+strlen(router_status);
1052 s = tor_malloc_zero(len);
1053 tor_snprintf(s, len,
1054 "network-status\n"
1055 "published %s\n"
1056 "router-status %s\n"
1057 "dir-signing-key\n%s"
1058 "directory-signature %s\n",
1059 published, router_status, identity_pkey, get_options()->Nickname);
1060 tor_free(router_status);
1061 tor_free(identity_pkey);
1062 if (router_get_runningrouters_hash(s,digest)) {
1063 log_fn(LOG_WARN,"couldn't compute digest");
1064 goto err;
1066 if (router_append_dirobj_signature(s, len, digest, private_key)<0)
1067 goto err;
1069 set_cached_dir(&the_runningrouters, s, time(NULL));
1070 runningrouters_is_dirty = 0;
1072 return 0;
1073 err:
1074 tor_free(s);
1075 tor_free(router_status);
1076 return -1;
1079 /** Set *<b>rr</b> to the most recently generated encoded signed
1080 * running-routers list, generating a new one as necessary. Return the
1081 * size of the directory on success, and 0 on failure. */
1082 size_t
1083 dirserv_get_runningrouters(const char **rr, int compress)
1085 return dirserv_get_obj(rr, compress,
1086 &cached_runningrouters, &the_runningrouters,
1087 runningrouters_is_dirty,
1088 generate_runningrouters,
1089 "v1 network status list", 1);
1092 /** Return true iff <b>ri</b> is "useful as an exit node", meaning
1093 * it allows exit to at least one /8 address space for at least
1094 * one of ports 80, 443, and 6667. */
1095 static int
1096 router_is_general_exit(routerinfo_t *ri)
1098 static const int ports[] = { 80, 443, 6667 };
1099 int n_allowed = 0;
1100 int i;
1101 for (i = 0; i < 3; ++i) {
1102 struct addr_policy_t *policy = ri->exit_policy;
1103 for ( ; policy; policy = policy->next) {
1104 if (policy->prt_min > ports[i] || policy->prt_max < ports[i])
1105 continue; /* Doesn't cover our port. */
1106 if ((policy->msk & 0x00fffffful) != 0)
1107 continue; /* Narrower than a /8. */
1108 if ((policy->addr & 0xff000000ul) == 0x7f000000ul)
1109 continue; /* 127.x */
1110 /* We have a match that is at least a /8. */
1111 if (policy->policy_type == ADDR_POLICY_ACCEPT)
1112 ++n_allowed;
1113 break;
1116 return n_allowed > 0;
1119 /** For authoritative directories: the current (v2) network status */
1120 static cached_dir_t the_v2_networkstatus = { NULL, NULL, 0, 0, 0 };
1122 /** For authoritative directories only: replace the contents of
1123 * <b>the_v2_networkstatus</b> with a newly generated network status
1124 * object. */
1125 static int
1126 generate_v2_networkstatus(void)
1128 #define LONGEST_STATUS_FLAG_NAME_LEN 7
1129 #define N_STATUS_FLAGS 6
1130 #define RS_ENTRY_LEN \
1131 ( /* first line */ \
1132 MAX_NICKNAME_LEN+BASE64_DIGEST_LEN*2+ISO_TIME_LEN+INET_NTOA_BUF_LEN+ \
1133 5*2 /* ports */ + 10 /* punctuation */ + \
1134 /* second line */ \
1135 (LONGEST_STATUS_FLAG_NAME_LEN+1)*N_STATUS_FLAGS + 2)
1137 int r = -1;
1138 size_t len, identity_pkey_len;
1139 char *status = NULL, *client_versions = NULL, *server_versions = NULL,
1140 *identity_pkey = NULL, *hostname = NULL;
1141 char *outp, *endp;
1142 or_options_t *options = get_options();
1143 char fingerprint[FINGERPRINT_LEN+1];
1144 char ipaddr[INET_NTOA_BUF_LEN+1];
1145 char published[ISO_TIME_LEN];
1146 char digest[DIGEST_LEN];
1147 struct in_addr in;
1148 uint32_t addr;
1149 crypto_pk_env_t *private_key = get_identity_key();
1150 smartlist_t *descriptor_list = get_descriptor_list();
1151 time_t now = time(NULL);
1152 int naming = options->NamingAuthoritativeDir;
1153 int versioning = options->VersioningAuthoritativeDir;
1154 const char *contact;
1156 if (!descriptor_list) {
1157 log_fn(LOG_WARN, "Couldn't get router list.");
1158 goto done;
1161 if (resolve_my_address(options, &addr, &hostname)<0) {
1162 log_fn(LOG_WARN, "Couldn't resolve my hostname");
1163 goto done;
1165 in.s_addr = htonl(addr);
1166 tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
1168 format_iso_time(published, time(NULL));
1170 client_versions = format_versions_list(options->RecommendedClientVersions);
1171 server_versions = format_versions_list(options->RecommendedServerVersions);
1173 if (crypto_pk_write_public_key_to_string(private_key, &identity_pkey,
1174 &identity_pkey_len)<0) {
1175 log_fn(LOG_WARN,"Writing public key to string failed.");
1176 goto done;
1179 if (crypto_pk_get_fingerprint(private_key, fingerprint, 0)<0) {
1180 log_fn(LOG_ERR, "Error computing fingerprint");
1181 goto done;
1184 contact = get_options()->ContactInfo;
1185 if (!contact)
1186 contact = "(none)";
1188 len = 2048+strlen(client_versions)+strlen(server_versions)+identity_pkey_len*2;
1189 len += (RS_ENTRY_LEN)*smartlist_len(descriptor_list) ;
1191 status = tor_malloc(len);
1192 tor_snprintf(status, len,
1193 "network-status-version 2\n"
1194 "dir-source %s %s %d\n"
1195 "fingerprint %s\n"
1196 "contact %s\n"
1197 "published %s\n"
1198 "dir-options%s%s\n"
1199 "client-versions %s\n"
1200 "server-versions %s\n"
1201 "dir-signing-key\n%s\n",
1202 hostname, ipaddr, (int)options->DirPort,
1203 fingerprint,
1204 contact,
1205 published,
1206 naming ? " Names" : "",
1207 versioning ? " Versions" : "",
1208 client_versions,
1209 server_versions,
1210 identity_pkey);
1211 outp = status + strlen(status);
1212 endp = status + len;
1214 SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, {
1215 int f_exit = router_is_general_exit(ri);
1216 int f_stable = !router_is_unreliable(ri, 1, 0);
1217 int f_fast = !router_is_unreliable(ri, 0, 1);
1218 int f_running;
1219 int f_authority = router_digest_is_trusted_dir(ri->identity_digest);
1220 int f_named = naming && ri->is_named;
1221 int f_valid = ri->is_verified;
1222 char identity64[BASE64_DIGEST_LEN+1];
1223 char digest64[BASE64_DIGEST_LEN+1];
1224 if (options->AuthoritativeDir) {
1225 ri->is_running = dirserv_thinks_router_is_reachable(ri, now);
1227 f_running = ri->is_running;
1229 format_iso_time(published, ri->published_on);
1231 digest_to_base64(identity64, ri->identity_digest);
1232 digest_to_base64(digest64, ri->signed_descriptor_digest);
1234 in.s_addr = htonl(ri->addr);
1235 tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
1237 if (tor_snprintf(outp, endp-outp,
1238 "r %s %s %s %s %s %d %d\n"
1239 "s%s%s%s%s%s%s%s\n",
1240 ri->nickname,
1241 identity64,
1242 digest64,
1243 published,
1244 ipaddr,
1245 ri->or_port,
1246 ri->dir_port,
1247 f_authority?" Authority":"",
1248 f_exit?" Exit":"",
1249 f_fast?" Fast":"",
1250 f_named?" Named":"",
1251 f_stable?" Stable":"",
1252 f_running?" Running":"",
1253 f_valid?" Valid":"")<0) {
1254 log_fn(LOG_WARN, "Unable to print router status.");
1255 goto done;
1257 outp += strlen(outp);
1260 if (tor_snprintf(outp, endp-outp, "directory-signature %s\n",
1261 get_options()->Nickname)<0) {
1262 log_fn(LOG_WARN, "Unable to write signature line.");
1263 goto done;
1266 if (router_get_networkstatus_v2_hash(status, digest)<0) {
1267 log_fn(LOG_WARN, "Unable to hash network status");
1268 goto done;
1271 if (router_append_dirobj_signature(outp,endp-outp,digest,private_key)<0) {
1272 log_fn(LOG_WARN, "Unable to sign router status.");
1273 goto done;
1276 set_cached_dir(&the_v2_networkstatus, status, time(NULL));
1277 status = NULL; /* So it doesn't get double-freed. */
1278 the_v2_networkstatus_is_dirty = 0;
1279 router_set_networkstatus(the_v2_networkstatus.dir, time(NULL), NS_GENERATED,
1280 NULL);
1282 r = 0;
1283 done:
1284 tor_free(client_versions);
1285 tor_free(server_versions);
1286 tor_free(status);
1287 tor_free(hostname);
1288 tor_free(identity_pkey);
1289 return r;
1292 /** Look for a network status object as specified by <b>key</b>, which should
1293 * be either "authority" (to find a network status generated by us), a hex
1294 * identity digest (to find a network status generated by given directory), or
1295 * "all" (to return all the v2 network status objects we have, concatenated).
1296 * If <b>compress</b>, find the version compressed with zlib. Return 0 if
1297 * nothing was found; otherwise set *<b>directory</b> to the matching network
1298 * status and return its length.
1301 dirserv_get_networkstatus_v2(smartlist_t *result,
1302 const char *key)
1304 tor_assert(result);
1306 if (!cached_v2_networkstatus)
1307 cached_v2_networkstatus = strmap_new();
1309 if (!(strcmp(key,"authority"))) {
1310 if (get_options()->AuthoritativeDir) {
1311 cached_dir_t *d =
1312 dirserv_pick_cached_dir_obj(NULL,
1313 &the_v2_networkstatus,
1314 the_v2_networkstatus_is_dirty,
1315 generate_v2_networkstatus,
1316 "network status list", 0);
1317 log_fn(LOG_WARN, "Unable to generate an authoritative network stautus.");
1318 if (d)
1319 smartlist_add(result, d);
1321 } else if (!strcmp(key, "all")) {
1322 strmap_iter_t *iter = strmap_iter_init(cached_v2_networkstatus);
1323 while (!strmap_iter_done(iter)) {
1324 const char *fp;
1325 void *val;
1326 strmap_iter_get(iter, &fp, &val);
1327 smartlist_add(result, val);
1328 iter = strmap_iter_next(cached_v2_networkstatus, iter);
1330 if (smartlist_len(result) == 0)
1331 log_fn(LOG_WARN, "Client requested 'all' network status objects; we have none.");
1332 } else if (!strcmpstart(key, "fp/")) {
1333 smartlist_t *hexdigests = smartlist_create();
1334 dir_split_resource_into_fingerprints(key+3, hexdigests, NULL);
1335 SMARTLIST_FOREACH(hexdigests, char *, cp,
1337 cached_dir_t *cached;
1338 tor_strupper(cp);
1339 if (router_fingerprint_is_me(cp) &&
1340 get_options()->AuthoritativeDir &&
1341 the_v2_networkstatus_is_dirty &&
1342 the_v2_networkstatus_is_dirty + DIR_REGEN_SLACK_TIME < time(NULL))
1343 generate_v2_networkstatus();
1344 cached = strmap_get(cached_v2_networkstatus, cp);
1345 if (cached) {
1346 smartlist_add(result, cached);
1347 } else {
1348 log_fn(LOG_INFO, "Don't know about any network status with fingerprint '%s'", cp);
1350 tor_free(cp);
1352 smartlist_free(hexdigests);
1354 return 0;
1357 /** Add a routerinfo_t to <b>descs_out</b> for each router matching
1358 * <b>key</b>. The key should be either "/tor/server/authority" for our own
1359 * routerinfo; "/tor/server/all" for all the routerinfos we have,
1360 * concatenated; or "/tor/server/FP" where FP is a plus-separated sequence of
1361 * hex identity digests.
1363 void
1364 dirserv_get_routerdescs(smartlist_t *descs_out, const char *key)
1366 smartlist_t *complete_list = get_descriptor_list();
1367 if (!complete_list)
1368 return;
1370 if (!strcmp(key, "/tor/server/all")) {
1371 smartlist_add_all(descs_out, complete_list);
1372 } else if (!strcmp(key, "/tor/server/authority")) {
1373 routerinfo_t *ri = router_get_my_routerinfo();
1374 if (ri)
1375 smartlist_add(descs_out, ri);
1376 } else if (!strcmpstart(key, "/tor/server/fp/")) {
1377 smartlist_t *hexdigests = smartlist_create();
1378 smartlist_t *digests = smartlist_create();
1379 key += strlen("/tor/server/fp/");
1380 dir_split_resource_into_fingerprints(key, hexdigests, NULL);
1381 SMARTLIST_FOREACH(hexdigests, char *, cp,
1383 char *d;
1384 if (strlen(cp) != HEX_DIGEST_LEN)
1385 continue;
1386 d = tor_malloc_zero(DIGEST_LEN);
1387 base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN);
1388 tor_free(cp);
1389 smartlist_add(digests, d);
1391 smartlist_free(hexdigests);
1392 SMARTLIST_FOREACH(digests, const char *, d,
1394 if (router_digest_is_me(d)) {
1395 smartlist_add(descs_out, router_get_my_routerinfo());
1396 } else {
1397 routerinfo_t *ri = router_get_by_digest(d);
1398 if (ri)
1399 smartlist_add(descs_out,ri);
1402 SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
1403 smartlist_free(digests);
1407 /** Called when a TLS handshake has completed successfully with a
1408 * router listening at <b>address</b>:<b>or_port</b>, and has yielded
1409 * a certificate with digest <b>digest_rcvd</b> and nickname
1410 * <b>nickname_rcvd</b>. When this happens, it's clear that any other
1411 * descriptors for that address/port combination must be unusable:
1412 * delete them if they are not verified.
1414 * Also, if as_advertised is 1, then inform the reachability checker
1415 * that we could get to this guy.
1417 void
1418 dirserv_orconn_tls_done(const char *address,
1419 uint16_t or_port,
1420 const char *digest_rcvd,
1421 const char *nickname_rcvd,
1422 int as_advertised)
1424 int i;
1425 smartlist_t *descriptor_list = get_descriptor_list();
1426 tor_assert(address);
1427 tor_assert(digest_rcvd);
1428 tor_assert(nickname_rcvd);
1430 if (!descriptor_list)
1431 return;
1433 // XXXXNM We should really have a better solution here than dropping
1434 // XXXXNM whole routers; otherwise, they come back way too easily.
1435 for (i = 0; i < smartlist_len(descriptor_list); ++i) {
1436 routerinfo_t *ri = smartlist_get(descriptor_list, i);
1437 int drop = 0;
1438 if (strcasecmp(address, ri->address) || or_port != ri->or_port)
1439 continue;
1440 if (!ri->is_verified) {
1441 /* We have a router at the same address! */
1442 if (strcasecmp(ri->nickname, nickname_rcvd)) {
1443 log_fn(LOG_NOTICE, "Dropping descriptor: nickname '%s' does not match nickname '%s' in cert from %s:%d",
1444 ri->nickname, nickname_rcvd, address, or_port);
1445 drop = 1;
1446 } else if (memcmp(ri->identity_digest, digest_rcvd, DIGEST_LEN)) {
1447 log_fn(LOG_NOTICE, "Dropping descriptor: identity key does not match key in cert from %s:%d",
1448 address, or_port);
1449 drop = 1;
1452 if (drop) {
1453 routerinfo_free(ri);
1454 smartlist_del(descriptor_list, i--);
1455 directory_set_dirty();
1456 } else { /* correct nickname and digest. mark this router reachable! */
1457 log_fn(LOG_INFO,"Found router %s to be reachable. Yay.", ri->nickname);
1458 ri->last_reachable = time(NULL);
1459 ri->num_unreachable_notifications = 0;
1464 /** Release all storage used by the directory server. */
1465 void
1466 dirserv_free_all(void)
1468 if (fingerprint_list) {
1469 SMARTLIST_FOREACH(fingerprint_list, fingerprint_entry_t*, fp,
1470 { tor_free(fp->nickname);
1471 tor_free(fp->fingerprint);
1472 tor_free(fp); });
1473 smartlist_free(fingerprint_list);
1474 fingerprint_list = NULL;
1476 if (authdir_reject_policy)
1477 addr_policy_free(authdir_reject_policy);
1478 if (authdir_invalid_policy)
1479 addr_policy_free(authdir_invalid_policy);
1480 clear_cached_dir(&the_directory);
1481 clear_cached_dir(&the_runningrouters);
1482 clear_cached_dir(&cached_directory);
1483 clear_cached_dir(&cached_runningrouters);
1484 if (cached_v2_networkstatus) {
1485 strmap_free(cached_v2_networkstatus, free_cached_dir);
1486 cached_v2_networkstatus = NULL;