1 /* Copyright 2001-2004 Roger Dingledine.
2 * Copyright 2004 Roger Dingledine, Nick Mathewson. */
3 /* See LICENSE for licensing information */
5 const char dirserv_c_id
[] = "$Id$";
11 * \brief Directory server core implementation.
14 /** How far in the future do we allow a router to get? (seconds) */
15 #define ROUTER_ALLOW_SKEW (30*60)
16 /** How many seconds do we wait before regenerating the directory? */
17 #define DIR_REGEN_SLACK_TIME 10
19 /** Do we need to regenerate the directory when someone asks for it? */
20 static int the_directory_is_dirty
= 1;
21 static int runningrouters_is_dirty
= 1;
23 static int list_server_status(char **running_routers_out
,
24 char **router_status_out
);
25 static void directory_remove_unrecognized(void);
26 static int dirserv_regenerate_directory(void);
27 /* Should be static; exposed for testing */
28 void add_fingerprint_to_dir(const char *nickname
, const char *fp
);
30 /************** Fingerprint handling code ************/
32 typedef struct fingerprint_entry_t
{
34 char *fingerprint
; /**< Stored as HEX_DIGEST_LEN characters, followed by a NUL */
35 } fingerprint_entry_t
;
37 /** List of nickname-\>identity fingerprint mappings for all the routers
38 * that we recognize. Used to prevent Sybil attacks. */
39 static smartlist_t
*fingerprint_list
= NULL
;
41 /** Add the fingerprint <b>fp</b> for the nickname <b>nickname</b> to
42 * the global list of recognized identity key fingerprints.
44 void /* Should be static; exposed for testing */
45 add_fingerprint_to_dir(const char *nickname
, const char *fp
)
48 fingerprint_entry_t
*ent
;
49 if (!fingerprint_list
)
50 fingerprint_list
= smartlist_create();
52 for (i
= 0; i
< smartlist_len(fingerprint_list
); ++i
) {
53 ent
= smartlist_get(fingerprint_list
, i
);
54 if (!strcasecmp(ent
->nickname
,nickname
)) {
55 tor_free(ent
->fingerprint
);
56 ent
->fingerprint
= tor_strdup(fp
);
60 ent
= tor_malloc(sizeof(fingerprint_entry_t
));
61 ent
->nickname
= tor_strdup(nickname
);
62 ent
->fingerprint
= tor_strdup(fp
);
63 tor_strstrip(ent
->fingerprint
, " ");
64 smartlist_add(fingerprint_list
, ent
);
67 /** Add the nickname and fingerprint for this OR to the recognized list.
70 dirserv_add_own_fingerprint(const char *nickname
, crypto_pk_env_t
*pk
)
72 char fp
[FINGERPRINT_LEN
+1];
73 if (crypto_pk_get_fingerprint(pk
, fp
, 0)<0) {
74 log_fn(LOG_ERR
, "Error computing fingerprint");
77 add_fingerprint_to_dir(nickname
, fp
);
81 /** Parse the nickname-\>fingerprint mappings stored in the file named
82 * <b>fname</b>. The file format is line-based, with each non-blank
83 * holding one nickname, some space, and a fingerprint for that
84 * nickname. On success, replace the current fingerprint list with
85 * the contents of <b>fname</b> and return 0. On failure, leave the
86 * current fingerprint list untouched, and return -1. */
88 dirserv_parse_fingerprint_file(const char *fname
)
91 char *nickname
, *fingerprint
;
92 smartlist_t
*fingerprint_list_new
;
94 fingerprint_entry_t
*ent
;
95 struct config_line_t
*front
=NULL
, *list
;
97 cf
= read_file_to_str(fname
, 0);
99 log_fn(LOG_WARN
, "Cannot open fingerprint file %s", fname
);
102 result
= config_get_lines(cf
, &front
);
105 log_fn(LOG_WARN
, "Error reading from fingerprint file");
109 fingerprint_list_new
= smartlist_create();
111 for (list
=front
; list
; list
=list
->next
) {
112 nickname
= list
->key
; fingerprint
= list
->value
;
113 if (strlen(nickname
) > MAX_NICKNAME_LEN
) {
114 log(LOG_NOTICE
, "Nickname '%s' too long in fingerprint file. Skipping.", nickname
);
117 if (strlen(fingerprint
) != FINGERPRINT_LEN
||
118 !crypto_pk_check_fingerprint_syntax(fingerprint
)) {
119 log_fn(LOG_NOTICE
, "Invalid fingerprint (nickname '%s', fingerprint %s). Skipping.",
120 nickname
, fingerprint
);
123 if (0==strcasecmp(nickname
, DEFAULT_CLIENT_NICKNAME
)) {
124 /* If you approved an OR called "client", then clients who use
125 * the default nickname could all be rejected. That's no good. */
127 "Authorizing a nickname '%s' would break many clients; skipping.",
128 DEFAULT_CLIENT_NICKNAME
);
131 for (i
= 0; i
< smartlist_len(fingerprint_list_new
); ++i
) {
132 ent
= smartlist_get(fingerprint_list_new
, i
);
133 if (0==strcasecmp(ent
->nickname
, nickname
)) {
134 log(LOG_NOTICE
, "Duplicate nickname '%s'. Skipping.",nickname
);
135 break; /* out of the for. the 'if' below means skip to the next line. */
138 if (i
== smartlist_len(fingerprint_list_new
)) { /* not a duplicate */
139 ent
= tor_malloc(sizeof(fingerprint_entry_t
));
140 ent
->nickname
= tor_strdup(nickname
);
141 ent
->fingerprint
= tor_strdup(fingerprint
);
142 tor_strstrip(ent
->fingerprint
, " ");
143 smartlist_add(fingerprint_list_new
, ent
);
147 config_free_lines(front
);
148 dirserv_free_fingerprint_list();
149 fingerprint_list
= fingerprint_list_new
;
150 /* Delete any routers whose fingerprints we no longer recognize */
151 directory_remove_unrecognized();
155 /** Check whether <b>router</b> has a nickname/identity key combination that
156 * we recognize from the fingerprint list. Return 1 if router's
157 * identity and nickname match, -1 if we recognize the nickname but
158 * the identity key is wrong, and 0 if the nickname is not known. */
160 dirserv_router_fingerprint_is_known(const routerinfo_t
*router
)
163 fingerprint_entry_t
*ent
=NULL
;
164 char fp
[FINGERPRINT_LEN
+1];
166 if (!fingerprint_list
)
167 fingerprint_list
= smartlist_create();
169 log_fn(LOG_DEBUG
, "%d fingerprints known.", smartlist_len(fingerprint_list
));
170 for (i
=0;i
<smartlist_len(fingerprint_list
);++i
) {
171 ent
= smartlist_get(fingerprint_list
, i
);
172 log_fn(LOG_DEBUG
,"%s vs %s", router
->nickname
, ent
->nickname
);
173 if (!strcasecmp(router
->nickname
,ent
->nickname
)) {
179 if (!found
) { /* No such server known */
180 log_fn(LOG_INFO
,"no fingerprint found for '%s'",router
->nickname
);
183 if (crypto_pk_get_fingerprint(router
->identity_pkey
, fp
, 0)) {
184 log_fn(LOG_WARN
,"error computing fingerprint");
187 if (0==strcasecmp(ent
->fingerprint
, fp
)) {
188 log_fn(LOG_DEBUG
,"good fingerprint for '%s'",router
->nickname
);
189 return 1; /* Right fingerprint. */
191 log_fn(LOG_WARN
,"mismatched fingerprint for '%s'",router
->nickname
);
192 return -1; /* Wrong fingerprint. */
196 /** If we are an authoritative dirserver, and the list of approved
197 * servers contains one whose identity key digest is <b>digest</b>,
198 * return that router's nickname. Otherwise return NULL. */
199 const char *dirserv_get_nickname_by_digest(const char *digest
)
201 char hexdigest
[HEX_DIGEST_LEN
+1];
202 if (!fingerprint_list
)
206 base16_encode(hexdigest
, HEX_DIGEST_LEN
+1, digest
, DIGEST_LEN
);
207 SMARTLIST_FOREACH(fingerprint_list
, fingerprint_entry_t
*, ent
,
208 { if (!strcasecmp(hexdigest
, ent
->fingerprint
))
209 return ent
->nickname
; } );
214 /** Return true iff any router named <b>nickname</b> with <b>digest</b>
215 * is in the verified fingerprint list. */
217 router_nickname_is_approved(const char *nickname
, const char *digest
)
221 n
= dirserv_get_nickname_by_digest(digest
);
222 if (n
&& !strcasecmp(n
,nickname
))
229 /** Clear the current fingerprint list. */
231 dirserv_free_fingerprint_list()
234 fingerprint_entry_t
*ent
;
235 if (!fingerprint_list
)
238 for (i
= 0; i
< smartlist_len(fingerprint_list
); ++i
) {
239 ent
= smartlist_get(fingerprint_list
, i
);
240 tor_free(ent
->nickname
);
241 tor_free(ent
->fingerprint
);
244 smartlist_free(fingerprint_list
);
245 fingerprint_list
= NULL
;
252 /** A directory server's view of a server descriptor. Contains both
253 * parsed and unparsed versions. */
254 typedef struct descriptor_entry_t
{
260 routerinfo_t
*router
;
261 } descriptor_entry_t
;
263 /** List of all server descriptors that this dirserv is holding. */
264 static smartlist_t
*descriptor_list
= NULL
;
266 /** Release the storage held by <b>desc</b> */
267 static void free_descriptor_entry(descriptor_entry_t
*desc
)
269 tor_free(desc
->descriptor
);
270 tor_free(desc
->nickname
);
271 routerinfo_free(desc
->router
);
275 /** Release all storage that the dirserv is holding for server
278 dirserv_free_descriptors()
280 if (!descriptor_list
)
282 SMARTLIST_FOREACH(descriptor_list
, descriptor_entry_t
*, d
,
283 free_descriptor_entry(d
));
284 smartlist_clear(descriptor_list
);
287 /** Return -1 if <b>ri</b> has a private or otherwise bad address,
288 * unless we're configured to not care. Return 0 if all ok. */
290 dirserv_router_has_valid_address(routerinfo_t
*ri
)
292 struct in_addr iaddr
;
293 if (get_options()->DirAllowPrivateAddresses
)
294 return 0; /* whatever it is, we're fine with it */
295 if (!tor_inet_aton(ri
->address
, &iaddr
)) {
296 log_fn(LOG_INFO
,"Router '%s' published non-IP address '%s'. Refusing.",
297 ri
->nickname
, ri
->address
);
300 if (is_internal_IP(ntohl(iaddr
.s_addr
))) {
301 log_fn(LOG_INFO
,"Router '%s' published internal IP address '%s'. Refusing.",
302 ri
->nickname
, ri
->address
);
303 return -1; /* it's a private IP, we should reject it */
308 /** Parse the server descriptor at *desc and maybe insert it into the
309 * list of server descriptors, and (if the descriptor is well-formed)
310 * advance *desc immediately past the descriptor's end. Set msg to a
311 * message that should be passed back to the origin of this descriptor, or
314 * Return 1 if descriptor is well-formed and accepted;
315 * 0 if well-formed and server is unapproved but accepted;
316 * -1 if well-formed but rejected;
317 * -2 if not well-formed.
320 dirserv_add_descriptor(const char **desc
, const char **msg
)
322 descriptor_entry_t
*ent
= NULL
;
323 routerinfo_t
*ri
= NULL
;
326 char *desc_tmp
= NULL
;
330 int verified
=1; /* whether we knew its fingerprint already */
333 if (!descriptor_list
)
334 descriptor_list
= smartlist_create();
336 start
= strstr(*desc
, "router ");
338 log_fn(LOG_WARN
, "no 'router' line found. This is not a descriptor.");
341 if ((end
= strstr(start
+6, "\nrouter "))) {
342 ++end
; /* Include NL. */
343 } else if ((end
= strstr(start
+6, "\ndirectory-signature"))) {
346 end
= start
+strlen(start
);
348 desc_len
= end
-start
;
349 cp
= desc_tmp
= tor_strndup(start
, desc_len
);
351 /* Check: is the descriptor syntactically valid? */
352 ri
= router_parse_entry_from_string(cp
, NULL
);
355 log(LOG_WARN
, "Couldn't parse descriptor");
356 *msg
= "Rejected: Couldn't parse server descriptor.";
359 /* Okay. Now check whether the fingerprint is recognized. */
360 r
= dirserv_router_fingerprint_is_known(ri
);
362 log_fn(LOG_WARN
, "Known nickname '%s', wrong fingerprint. Not adding.", ri
->nickname
);
363 *msg
= "Rejected: There is already a verified server with this nickname and a different fingerprint.";
369 char fp
[FINGERPRINT_LEN
+1];
370 log_fn(LOG_INFO
, "Unknown nickname '%s' (%s:%d). Will try to add.",
371 ri
->nickname
, ri
->address
, ri
->or_port
);
372 if (crypto_pk_get_fingerprint(ri
->identity_pkey
, fp
, 1) < 0) {
373 log_fn(LOG_WARN
, "Error computing fingerprint for '%s'", ri
->nickname
);
375 log_fn(LOG_INFO
, "Fingerprint line: %s %s", ri
->nickname
, fp
);
379 /* Is there too much clock skew? */
381 if (ri
->published_on
> now
+ROUTER_ALLOW_SKEW
) {
382 log_fn(LOG_NOTICE
, "Publication time for nickname '%s' is too far in the future; possible clock skew. Not adding.", ri
->nickname
);
383 *msg
= "Rejected: Your clock is set too far in the future, or your timezone is not correct.";
388 if (ri
->published_on
< now
-ROUTER_MAX_AGE
) {
389 log_fn(LOG_NOTICE
, "Publication time for router with nickname '%s' is too far in the past. Not adding.", ri
->nickname
);
390 *msg
= "Rejected: Server is expired, or your clock is too far in the past, or your timezone is not correct.";
395 if (dirserv_router_has_valid_address(ri
) < 0) {
396 log_fn(LOG_NOTICE
, "Router with nickname '%s' has invalid address '%s'. Not adding.", ri
->nickname
, ri
->address
);
397 *msg
= "Rejected: Address is not an IP, or IP is a private address.";
403 /* Do we already have an entry for this router? */
404 for (i
= 0; i
< smartlist_len(descriptor_list
); ++i
) {
405 ent
= smartlist_get(descriptor_list
, i
);
406 if (!strcasecmp(ri
->nickname
, ent
->nickname
)) {
412 /* if so, decide whether to update it. */
413 if (ent
->published
>= ri
->published_on
) {
414 /* We already have a newer or equal-time descriptor */
415 log_fn(LOG_INFO
,"We already have a new enough desc for nickname '%s'. Not adding.",ri
->nickname
);
416 *msg
= "We already have a newer descriptor.";
417 /* This isn't really an error; return success. */
422 /* We don't have a newer one; we'll update this one. */
423 log_fn(LOG_INFO
,"Dirserv updating desc for nickname '%s'",ri
->nickname
);
424 *msg
= verified
?"Verified server updated":"Unverified server updated. (Have you sent us your key fingerprint?)";
425 free_descriptor_entry(ent
);
426 smartlist_del_keeporder(descriptor_list
, found
);
428 /* Add at the end. */
429 log_fn(LOG_INFO
,"Dirserv adding desc for nickname '%s'",ri
->nickname
);
430 *msg
= verified
?"Verified server added":"Unverified server added. (Have you sent us your key fingerprint?)";
433 ent
= tor_malloc(sizeof(descriptor_entry_t
));
434 ent
->nickname
= tor_strdup(ri
->nickname
);
435 ent
->published
= ri
->published_on
;
436 ent
->desc_len
= desc_len
;
437 ent
->descriptor
= tor_strndup(start
,desc_len
);
439 ent
->verified
= verified
;
440 smartlist_add(descriptor_list
, ent
);
443 directory_set_dirty();
448 /** Remove all descriptors whose nicknames or fingerprints we don't
449 * recognize. (Descriptors that used to be good can become
450 * unrecognized when we reload the fingerprint list.)
453 directory_remove_unrecognized(void)
456 descriptor_entry_t
*ent
;
457 if (!descriptor_list
)
458 descriptor_list
= smartlist_create();
460 for (i
= 0; i
< smartlist_len(descriptor_list
); ++i
) {
461 ent
= smartlist_get(descriptor_list
, i
);
462 if (dirserv_router_fingerprint_is_known(ent
->router
)<=0) {
463 log(LOG_INFO
, "Router '%s' is no longer recognized",
465 free_descriptor_entry(ent
);
466 smartlist_del(descriptor_list
, i
--);
471 /** Mark the directory as <b>dirty</b> -- when we're next asked for a
472 * directory, we will rebuild it instead of reusing the most recently
476 directory_set_dirty()
478 time_t now
= time(NULL
);
480 if (!the_directory_is_dirty
)
481 the_directory_is_dirty
= now
;
482 if (!runningrouters_is_dirty
)
483 runningrouters_is_dirty
= now
;
486 /** Load all descriptors from a directory stored in the string
490 dirserv_load_from_directory_string(const char *dir
)
492 const char *cp
= dir
, *m
;
494 cp
= strstr(cp
, "\nrouter ");
497 if (dirserv_add_descriptor(&cp
,&m
) < -1) {
498 /* only fail if parsing failed; keep going if simply rejected */
501 --cp
; /*Back up to newline.*/
507 * Allocate and return a description of the status of the server <b>desc</b>,
508 * for use in a running-routers line (if <b>rr_format</b> is true), or in a
509 * router-status line (if <b>rr_format</b> is false. The server is listed
510 * as running iff <b>is_live</b> is true.
513 list_single_server_status(descriptor_entry_t
*desc
, int is_live
,
516 char buf
[MAX_NICKNAME_LEN
+HEX_DIGEST_LEN
+4]; /* !nickname=$hexdigest\0 */
520 tor_assert(desc
->router
);
526 if (desc
->verified
) {
527 strlcpy(cp
, desc
->nickname
, sizeof(buf
)-(cp
-buf
));
532 if (!desc
->verified
|| !rr_format
) {
534 base16_encode(cp
, HEX_DIGEST_LEN
+1, desc
->router
->identity_digest
,
537 return tor_strdup(buf
);
540 /** Allocate the contents of a running-routers line and a router-status line,
541 * and store them in *<b>running_routers_out</b> and *<b>router_status_out</b>
542 * respectively. Return 0 on success, -1 on failure.
545 list_server_status(char **running_routers_out
, char **router_status_out
)
547 /* List of entries in running-routers style: An optional !, then either
548 * a nickname or a dollar-prefixed hexdigest. */
549 smartlist_t
*rr_entries
;
550 /* List of entries in a router-status style: An optional !, then an optional
551 * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
552 smartlist_t
*rs_entries
;
554 tor_assert(running_routers_out
|| router_status_out
);
556 rr_entries
= smartlist_create();
557 rs_entries
= smartlist_create();
559 SMARTLIST_FOREACH(descriptor_list
, descriptor_entry_t
*, d
,
563 tor_assert(d
->router
);
564 conn
= connection_get_by_identity_digest(
565 d
->router
->identity_digest
, CONN_TYPE_OR
);
566 /* Treat a router as alive if
567 * - It's me, and I'm not hibernating.
568 * or - we're connected to it. */
569 is_live
= (router_is_me(d
->router
) && !we_are_hibernating()) ||
570 (conn
&& conn
->state
== OR_CONN_STATE_OPEN
);
571 smartlist_add(rr_entries
, list_single_server_status(d
, is_live
, 1));
572 smartlist_add(rs_entries
, list_single_server_status(d
, is_live
, 0));
575 if (running_routers_out
)
576 *running_routers_out
= smartlist_join_strings(rr_entries
, " ", 0,NULL
);
577 if (router_status_out
)
578 *router_status_out
= smartlist_join_strings(rs_entries
, " ", 0,NULL
);
580 SMARTLIST_FOREACH(rr_entries
, char *, cp
, tor_free(cp
));
581 SMARTLIST_FOREACH(rs_entries
, char *, cp
, tor_free(cp
));
582 smartlist_free(rr_entries
);
583 smartlist_free(rs_entries
);
588 /** Remove any descriptors from the directory that are more than <b>age</b>
592 dirserv_remove_old_servers(int age
)
596 descriptor_entry_t
*ent
;
597 if (!descriptor_list
)
598 descriptor_list
= smartlist_create();
600 cutoff
= time(NULL
) - age
;
601 for (i
= 0; i
< smartlist_len(descriptor_list
); ++i
) {
602 ent
= smartlist_get(descriptor_list
, i
);
603 if (ent
->published
<= cutoff
) {
604 /* descriptor_list[i] is too old. Remove it. */
605 free_descriptor_entry(ent
);
606 smartlist_del(descriptor_list
, i
--);
607 directory_set_dirty();
612 /** Generate a new directory and write it into a newly allocated string.
613 * Point *<b>dir_out</b> to the allocated string. Sign the
614 * directory with <b>private_key</b>. Return 0 on success, -1 on
618 dirserv_dump_directory_to_string(char **dir_out
,
619 crypto_pk_env_t
*private_key
)
622 char *running_routers
, *router_status
;
623 char *identity_pkey
; /* Identity key, DER64-encoded. */
624 char *recommended_versions
;
636 if (!descriptor_list
)
637 descriptor_list
= smartlist_create();
639 if (list_server_status(&running_routers
, &router_status
))
642 /* ASN.1-encode the public key. This is a temporary measure; once
643 * everyone is running 0.0.9pre3 or later, we can shift to using a
644 * PEM-encoded key instead.
647 if (crypto_pk_DER64_encode_public_key(private_key
, &identity_pkey
)<0) {
648 log_fn(LOG_WARN
,"write identity_pkey to string failed!");
654 if (crypto_pk_write_public_key_to_string(private_key
,&identity_pkey
,&l
)<0) {
655 log_fn(LOG_WARN
,"write identity_pkey to string failed!");
662 smartlist_t
*versions
;
663 struct config_line_t
*ln
;
664 versions
= smartlist_create();
665 for (ln
= get_options()->RecommendedVersions
; ln
; ln
= ln
->next
) {
666 smartlist_split_string(versions
, ln
->value
, ",",
667 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
669 recommended_versions
= smartlist_join_strings(versions
,",",0,NULL
);
670 SMARTLIST_FOREACH(versions
,char *,s
,tor_free(s
));
671 smartlist_free(versions
);
674 dirserv_remove_old_servers(ROUTER_MAX_AGE
);
675 published_on
= time(NULL
);
676 format_iso_time(published
, published_on
);
678 buf_len
= 2048+strlen(recommended_versions
)+strlen(running_routers
)+
679 strlen(router_status
);
680 SMARTLIST_FOREACH(descriptor_list
, descriptor_entry_t
*, d
,
681 buf_len
+= strlen(d
->descriptor
));
682 buf
= tor_malloc(buf_len
);
683 /* We'll be comparing against buf_len throughout the rest of the
684 function, though strictly speaking we shouldn't be able to exceed
685 it. This is C, after all, so we may as well check for buffer
688 tor_snprintf(buf
, buf_len
,
691 "recommended-software %s\n"
692 "running-routers %s\n"
693 "opt router-status %s\n"
694 "opt dir-signing-key %s\n\n",
695 published
, recommended_versions
, running_routers
, router_status
,
698 tor_free(recommended_versions
);
699 tor_free(running_routers
);
700 tor_free(router_status
);
701 tor_free(identity_pkey
);
705 SMARTLIST_FOREACH(descriptor_list
, descriptor_entry_t
*, d
,
706 if (strlcat(buf
, d
->descriptor
, buf_len
) >= buf_len
)
709 /* These multiple strlcat calls are inefficient, but dwarfed by the RSA
712 if (strlcat(buf
, "directory-signature ", buf_len
) >= buf_len
)
714 if (strlcat(buf
, get_options()->Nickname
, buf_len
) >= buf_len
)
716 if (strlcat(buf
, "\n", buf_len
) >= buf_len
)
719 if (router_get_dir_hash(buf
,digest
)) {
720 log_fn(LOG_WARN
,"couldn't compute digest");
724 if (crypto_pk_private_sign(private_key
, signature
, digest
, 20) < 0) {
725 log_fn(LOG_WARN
,"couldn't sign digest");
729 log(LOG_DEBUG
,"generated directory digest begins with %s",hex_str(digest
,4));
731 if (strlcat(cp
, "-----BEGIN SIGNATURE-----\n", buf_len
) >= buf_len
)
736 if (base64_encode(cp
, buf_len
-i
, signature
, 128) < 0) {
737 log_fn(LOG_WARN
,"couldn't base64-encode signature");
742 if (strlcat(buf
, "-----END SIGNATURE-----\n", buf_len
) >= buf_len
)
748 log_fn(LOG_WARN
,"tried to exceed string length.");
753 /** Most recently generated encoded signed directory. */
754 static char *the_directory
= NULL
;
755 static size_t the_directory_len
= 0;
756 static char *the_directory_z
= NULL
;
757 static size_t the_directory_z_len
= 0;
759 typedef struct cached_dir_t
{
767 /* used only by non-auth dirservers */
768 static cached_dir_t cached_directory
= { NULL
, NULL
, 0, 0, 0 };
769 static cached_dir_t cached_runningrouters
= { NULL
, NULL
, 0, 0, 0 };
771 /** If we have no cached directory, or it is older than <b>when</b>, then
772 * replace it with <b>directory</b>, published at <b>when</b>.
774 void dirserv_set_cached_directory(const char *directory
, time_t when
,
775 int is_running_routers
)
780 d
= is_running_routers
? &cached_runningrouters
: &cached_directory
;
781 if (when
<=d
->published
) {
782 log_fn(LOG_INFO
, "Ignoring old directory; not caching.");
783 } else if (when
>=now
+ROUTER_ALLOW_SKEW
) {
784 log_fn(LOG_INFO
, "Ignoring future directory; not caching.");
785 } else if (when
>d
->published
&&
786 when
<now
+ROUTER_ALLOW_SKEW
) {
787 log_fn(LOG_DEBUG
, "Caching directory.");
789 d
->dir
= tor_strdup(directory
);
790 d
->dir_len
= strlen(directory
);
792 if (tor_gzip_compress(&(d
->dir_z
), &(d
->dir_z_len
), d
->dir
, d
->dir_len
,
794 log_fn(LOG_WARN
,"Error compressing cached directory");
797 if (!is_running_routers
) {
799 tor_snprintf(filename
,sizeof(filename
),"%s/cached-directory", get_options()->DataDirectory
);
800 if (write_str_to_file(filename
,cached_directory
.dir
,0) < 0) {
801 log_fn(LOG_NOTICE
, "Couldn't write cached directory to disk. Ignoring.");
807 /** Set *<b>directory</b> to the most recently generated encoded signed
808 * directory, generating a new one as necessary. If not an authoritative
809 * directory may return 0 if no directory is yet cached.*/
810 size_t dirserv_get_directory(const char **directory
, int compress
)
812 if (!get_options()->AuthoritativeDir
) {
813 cached_dir_t
*d
= &cached_directory
;
814 *directory
= compress
? d
->dir_z
: d
->dir
;
816 return compress
? d
->dir_z_len
: d
->dir_len
;
818 /* no directory yet retrieved */
822 if (the_directory_is_dirty
&&
823 the_directory_is_dirty
+ DIR_REGEN_SLACK_TIME
< time(NULL
)) {
824 if (dirserv_regenerate_directory())
827 log(LOG_INFO
,"Directory still clean, reusing.");
829 *directory
= compress
? the_directory_z
: the_directory
;
830 return compress
? the_directory_z_len
: the_directory_len
;
834 * Generate a fresh directory (authdirservers only.)
836 static int dirserv_regenerate_directory(void)
838 char *new_directory
=NULL
;
840 if (dirserv_dump_directory_to_string(&new_directory
,
841 get_identity_key())) {
842 log(LOG_WARN
, "Error creating directory.");
843 tor_free(new_directory
);
846 tor_free(the_directory
);
847 the_directory
= new_directory
;
848 the_directory_len
= strlen(the_directory
);
849 log_fn(LOG_INFO
,"New directory (size %d):\n%s",(int)the_directory_len
,
851 tor_free(the_directory_z
);
852 if (tor_gzip_compress(&the_directory_z
, &the_directory_z_len
,
853 the_directory
, the_directory_len
,
855 log_fn(LOG_WARN
, "Error gzipping directory.");
859 /* Now read the directory we just made in order to update our own
860 * router lists. This does more signature checking than is strictly
861 * necessary, but safe is better than sorry. */
862 new_directory
= tor_strdup(the_directory
);
863 /* use a new copy of the dir, since get_dir_from_string scribbles on it */
864 if (router_load_routerlist_from_directory(new_directory
,
865 get_identity_key(), 1, 0)) {
866 log_fn(LOG_ERR
, "We just generated a directory we can't parse. Dying.");
870 tor_free(new_directory
);
871 the_directory_is_dirty
= 0;
873 /* Save the directory to disk so we re-load it quickly on startup.
875 dirserv_set_cached_directory(the_directory
, time(NULL
), 0);
880 static char *the_runningrouters
=NULL
;
881 static size_t the_runningrouters_len
=0;
882 static char *the_runningrouters_z
=NULL
;
883 static size_t the_runningrouters_z_len
=0;
885 /** Replace the current running-routers list with a newly generated one. */
886 static int generate_runningrouters(crypto_pk_env_t
*private_key
)
889 char *router_status
=NULL
;
890 char digest
[DIGEST_LEN
];
891 char signature
[PK_BYTES
];
896 char *identity_pkey
; /* Identity key, DER64-encoded. */
898 if (list_server_status(NULL
, &router_status
)) {
901 /* ASN.1-encode the public key. This is a temporary measure; once
902 * everyone is running 0.0.9pre3 or later, we can shift to using a
903 * PEM-encoded key instead.
906 if (crypto_pk_DER64_encode_public_key(private_key
, &identity_pkey
)<0) {
907 log_fn(LOG_WARN
,"write identity_pkey to string failed!");
913 if (crypto_pk_write_public_key_to_string(private_key
,&identity_pkey
,&l
)<0) {
914 log_fn(LOG_WARN
,"write identity_pkey to string failed!");
919 published_on
= time(NULL
);
920 format_iso_time(published
, published_on
);
922 len
= 2048+strlen(router_status
);
923 s
= tor_malloc_zero(len
);
924 tor_snprintf(s
, len
, "network-status\n"
927 "opt dir-signing-key %s\n"
928 "directory-signature %s\n"
929 "-----BEGIN SIGNATURE-----\n",
930 published
, router_status
, identity_pkey
, get_options()->Nickname
);
931 tor_free(router_status
);
932 tor_free(identity_pkey
);
933 if (router_get_runningrouters_hash(s
,digest
)) {
934 log_fn(LOG_WARN
,"couldn't compute digest");
937 if (crypto_pk_private_sign(private_key
, signature
, digest
, 20) < 0) {
938 log_fn(LOG_WARN
,"couldn't sign digest");
944 if (base64_encode(cp
, len
-i
, signature
, 128) < 0) {
945 log_fn(LOG_WARN
,"couldn't base64-encode signature");
948 if (strlcat(s
, "-----END SIGNATURE-----\n", len
) >= len
) {
952 tor_free(the_runningrouters
);
953 the_runningrouters
= s
;
954 the_runningrouters_len
= strlen(s
);
955 tor_free(the_runningrouters_z
);
956 if (tor_gzip_compress(&the_runningrouters_z
, &the_runningrouters_z_len
,
957 the_runningrouters
, the_runningrouters_len
,
959 log_fn(LOG_WARN
, "Error gzipping runningrouters");
962 runningrouters_is_dirty
= 0;
964 /* We don't cache running-routers to disk, so there's no point in
965 * authdirservers caching it. */
966 /* dirserv_set_cached_directory(the_runningrouters, time(NULL), 1); */
971 tor_free(router_status
);
975 /** Set *<b>rr</b> to the most recently generated encoded signed
976 * running-routers list, generating a new one as necessary. Return the
977 * size of the directory on success, and 0 on failure. */
978 size_t dirserv_get_runningrouters(const char **rr
, int compress
)
980 if (!get_options()->AuthoritativeDir
) {
981 cached_dir_t
*d
= &cached_runningrouters
;
982 *rr
= compress
? d
->dir_z
: d
->dir
;
984 return compress
? d
->dir_z_len
: d
->dir_len
;
986 /* no directory yet retrieved */
990 if (runningrouters_is_dirty
&&
991 runningrouters_is_dirty
+ DIR_REGEN_SLACK_TIME
< time(NULL
)) {
992 if (generate_runningrouters(get_identity_key())) {
993 log_fn(LOG_ERR
, "Couldn't generate running-routers list?");
997 *rr
= compress
? the_runningrouters_z
: the_runningrouters
;
998 return compress
? the_runningrouters_z_len
: the_runningrouters_len
;