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;
316 * -1 if not well-formed or other parsing error.
319 dirserv_add_descriptor(const char **desc
, const char **msg
)
321 descriptor_entry_t
*ent
= NULL
;
322 routerinfo_t
*ri
= NULL
;
325 char *desc_tmp
= NULL
;
329 int verified
=1; /* whether we knew its fingerprint already */
332 if (!descriptor_list
)
333 descriptor_list
= smartlist_create();
335 start
= strstr(*desc
, "router ");
337 log_fn(LOG_WARN
, "no 'router' line found. This is not a descriptor.");
340 if ((end
= strstr(start
+6, "\nrouter "))) {
341 ++end
; /* Include NL. */
342 } else if ((end
= strstr(start
+6, "\ndirectory-signature"))) {
345 end
= start
+strlen(start
);
347 desc_len
= end
-start
;
348 cp
= desc_tmp
= tor_strndup(start
, desc_len
);
350 /* Check: is the descriptor syntactically valid? */
351 ri
= router_parse_entry_from_string(cp
, NULL
);
354 log(LOG_WARN
, "Couldn't parse descriptor");
355 *msg
= "Rejected: Couldn't parse server descriptor.";
358 /* Okay. Now check whether the fingerprint is recognized. */
359 r
= dirserv_router_fingerprint_is_known(ri
);
361 log_fn(LOG_WARN
, "Known nickname '%s', wrong fingerprint. Not adding.", ri
->nickname
);
362 *msg
= "Rejected: There is already a verified server with this nickname and a different fingerprint.";
368 char fp
[FINGERPRINT_LEN
+1];
369 log_fn(LOG_INFO
, "Unknown nickname '%s' (%s:%d). Will try to add.",
370 ri
->nickname
, ri
->address
, ri
->or_port
);
371 if (crypto_pk_get_fingerprint(ri
->identity_pkey
, fp
, 1) < 0) {
372 log_fn(LOG_WARN
, "Error computing fingerprint for '%s'", ri
->nickname
);
374 log_fn(LOG_INFO
, "Fingerprint line: %s %s", ri
->nickname
, fp
);
378 /* Is there too much clock skew? */
380 if (ri
->published_on
> now
+ROUTER_ALLOW_SKEW
) {
381 log_fn(LOG_NOTICE
, "Publication time for nickname '%s' is too far in the future; possible clock skew. Not adding.", ri
->nickname
);
382 *msg
= "Rejected: Your clock is set too far in the future, or your timezone is not correct.";
387 if (ri
->published_on
< now
-ROUTER_MAX_AGE
) {
388 log_fn(LOG_NOTICE
, "Publication time for router with nickname '%s' is too far in the past. Not adding.", ri
->nickname
);
389 *msg
= "Rejected: Server is expired, or your clock is too far in the past, or your timezone is not correct.";
394 if (dirserv_router_has_valid_address(ri
) < 0) {
395 log_fn(LOG_NOTICE
, "Router with nickname '%s' has invalid address '%s'. Not adding.", ri
->nickname
, ri
->address
);
396 *msg
= "Rejected: Address is not an IP, or IP is a private address.";
402 /* Do we already have an entry for this router? */
403 for (i
= 0; i
< smartlist_len(descriptor_list
); ++i
) {
404 ent
= smartlist_get(descriptor_list
, i
);
405 if (!strcasecmp(ri
->nickname
, ent
->nickname
)) {
411 /* if so, decide whether to update it. */
412 if (ent
->published
>= ri
->published_on
) {
413 /* We already have a newer or equal-time descriptor */
414 log_fn(LOG_INFO
,"We already have a new enough desc for nickname '%s'. Not adding.",ri
->nickname
);
415 *msg
= "We already have a newer descriptor.";
416 /* This isn't really an error; return success. */
421 /* We don't have a newer one; we'll update this one. */
422 log_fn(LOG_INFO
,"Dirserv updating desc for nickname '%s'",ri
->nickname
);
423 *msg
= verified
?"Verified server updated":"Unverified server updated. (Have you sent us your key fingerprint?)";
424 free_descriptor_entry(ent
);
425 smartlist_del_keeporder(descriptor_list
, found
);
427 /* Add at the end. */
428 log_fn(LOG_INFO
,"Dirserv adding desc for nickname '%s'",ri
->nickname
);
429 *msg
= verified
?"Verified server added":"Unverified server added. (Have you sent us your key fingerprint?)";
432 ent
= tor_malloc(sizeof(descriptor_entry_t
));
433 ent
->nickname
= tor_strdup(ri
->nickname
);
434 ent
->published
= ri
->published_on
;
435 ent
->desc_len
= desc_len
;
436 ent
->descriptor
= tor_strndup(start
,desc_len
);
438 ent
->verified
= verified
;
439 smartlist_add(descriptor_list
, ent
);
442 directory_set_dirty();
447 /** Remove all descriptors whose nicknames or fingerprints we don't
448 * recognize. (Descriptors that used to be good can become
449 * unrecognized when we reload the fingerprint list.)
452 directory_remove_unrecognized(void)
455 descriptor_entry_t
*ent
;
456 if (!descriptor_list
)
457 descriptor_list
= smartlist_create();
459 for (i
= 0; i
< smartlist_len(descriptor_list
); ++i
) {
460 ent
= smartlist_get(descriptor_list
, i
);
461 if (dirserv_router_fingerprint_is_known(ent
->router
)<=0) {
462 log(LOG_INFO
, "Router '%s' is no longer recognized",
464 free_descriptor_entry(ent
);
465 smartlist_del(descriptor_list
, i
--);
470 /** Mark the directory as <b>dirty</b> -- when we're next asked for a
471 * directory, we will rebuild it instead of reusing the most recently
475 directory_set_dirty()
477 time_t now
= time(NULL
);
479 if (!the_directory_is_dirty
)
480 the_directory_is_dirty
= now
;
481 if (!runningrouters_is_dirty
)
482 runningrouters_is_dirty
= now
;
485 /** Load all descriptors from a directory stored in the string
489 dirserv_load_from_directory_string(const char *dir
)
491 const char *cp
= dir
, *m
;
493 cp
= strstr(cp
, "\nrouter ");
496 if (dirserv_add_descriptor(&cp
,&m
) < 0) {
499 --cp
; /*Back up to newline.*/
505 * Allocate and return a description of the status of the server <b>desc</b>,
506 * for use in a running-routers line (if <b>rr_format</b> is true), or in a
507 * router-status line (if <b>rr_format</b> is false. The server is listed
508 * as running iff <b>is_live</b> is true.
511 list_single_server_status(descriptor_entry_t
*desc
, int is_live
,
514 char buf
[MAX_NICKNAME_LEN
+HEX_DIGEST_LEN
+4]; /* !nickname=$hexdigest\0 */
518 tor_assert(desc
->router
);
524 if (desc
->verified
) {
525 strlcpy(cp
, desc
->nickname
, sizeof(buf
)-(cp
-buf
));
530 if (!desc
->verified
|| !rr_format
) {
532 base16_encode(cp
, HEX_DIGEST_LEN
+1, desc
->router
->identity_digest
,
535 return tor_strdup(buf
);
538 /** Allocate the contents of a running-routers line and a router-status line,
539 * and store them in *<b>running_routers_out</b> and *<b>router_status_out</b>
540 * respectively. Return 0 on success, -1 on failure.
543 list_server_status(char **running_routers_out
, char **router_status_out
)
545 /* List of entries in running-routers style: An optional !, then either
546 * a nickname or a dollar-prefixed hexdigest. */
547 smartlist_t
*rr_entries
;
548 /* List of entries in a router-status style: An optional !, then an optional
549 * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
550 smartlist_t
*rs_entries
;
552 tor_assert(running_routers_out
|| router_status_out
);
554 rr_entries
= smartlist_create();
555 rs_entries
= smartlist_create();
557 SMARTLIST_FOREACH(descriptor_list
, descriptor_entry_t
*, d
,
561 tor_assert(d
->router
);
562 conn
= connection_get_by_identity_digest(
563 d
->router
->identity_digest
, CONN_TYPE_OR
);
564 /* Treat a router as alive if
565 * - It's me, and I'm not hibernating.
566 * or - we're connected to it. */
567 is_live
= (router_is_me(d
->router
) && !we_are_hibernating()) ||
568 (conn
&& conn
->state
== OR_CONN_STATE_OPEN
);
569 smartlist_add(rr_entries
, list_single_server_status(d
, is_live
, 1));
570 smartlist_add(rs_entries
, list_single_server_status(d
, is_live
, 0));
573 if (running_routers_out
)
574 *running_routers_out
= smartlist_join_strings(rr_entries
, " ", 0,NULL
);
575 if (router_status_out
)
576 *router_status_out
= smartlist_join_strings(rs_entries
, " ", 0,NULL
);
578 SMARTLIST_FOREACH(rr_entries
, char *, cp
, tor_free(cp
));
579 SMARTLIST_FOREACH(rs_entries
, char *, cp
, tor_free(cp
));
580 smartlist_free(rr_entries
);
581 smartlist_free(rs_entries
);
586 /** Remove any descriptors from the directory that are more than <b>age</b>
590 dirserv_remove_old_servers(int age
)
594 descriptor_entry_t
*ent
;
595 if (!descriptor_list
)
596 descriptor_list
= smartlist_create();
598 cutoff
= time(NULL
) - age
;
599 for (i
= 0; i
< smartlist_len(descriptor_list
); ++i
) {
600 ent
= smartlist_get(descriptor_list
, i
);
601 if (ent
->published
<= cutoff
) {
602 /* descriptor_list[i] is too old. Remove it. */
603 free_descriptor_entry(ent
);
604 smartlist_del(descriptor_list
, i
--);
605 directory_set_dirty();
610 /** Generate a new directory and write it into a newly allocated string.
611 * Point *<b>dir_out</b> to the allocated string. Sign the
612 * directory with <b>private_key</b>. Return 0 on success, -1 on
616 dirserv_dump_directory_to_string(char **dir_out
,
617 crypto_pk_env_t
*private_key
)
620 char *running_routers
, *router_status
;
621 char *identity_pkey
; /* Identity key, DER64-encoded. */
622 char *recommended_versions
;
634 if (!descriptor_list
)
635 descriptor_list
= smartlist_create();
637 if (list_server_status(&running_routers
, &router_status
))
640 /* ASN.1-encode the public key. This is a temporary measure; once
641 * everyone is running 0.0.9pre3 or later, we can shift to using a
642 * PEM-encoded key instead.
645 if (crypto_pk_DER64_encode_public_key(private_key
, &identity_pkey
)<0) {
646 log_fn(LOG_WARN
,"write identity_pkey to string failed!");
652 if (crypto_pk_write_public_key_to_string(private_key
,&identity_pkey
,&l
)<0) {
653 log_fn(LOG_WARN
,"write identity_pkey to string failed!");
660 smartlist_t
*versions
;
661 struct config_line_t
*ln
;
662 versions
= smartlist_create();
663 for (ln
= get_options()->RecommendedVersions
; ln
; ln
= ln
->next
) {
664 smartlist_split_string(versions
, ln
->value
, ",",
665 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
667 recommended_versions
= smartlist_join_strings(versions
,",",0,NULL
);
668 SMARTLIST_FOREACH(versions
,char *,s
,tor_free(s
));
669 smartlist_free(versions
);
672 dirserv_remove_old_servers(ROUTER_MAX_AGE
);
673 published_on
= time(NULL
);
674 format_iso_time(published
, published_on
);
676 buf_len
= 2048+strlen(recommended_versions
)+strlen(running_routers
)+
677 strlen(router_status
);
678 SMARTLIST_FOREACH(descriptor_list
, descriptor_entry_t
*, d
,
679 buf_len
+= strlen(d
->descriptor
));
680 buf
= tor_malloc(buf_len
);
681 /* We'll be comparing against buf_len throughout the rest of the
682 function, though strictly speaking we shouldn't be able to exceed
683 it. This is C, after all, so we may as well check for buffer
686 tor_snprintf(buf
, buf_len
,
689 "recommended-software %s\n"
690 "running-routers %s\n"
691 "opt router-status %s\n"
692 "opt dir-signing-key %s\n\n",
693 published
, recommended_versions
, running_routers
, router_status
,
696 tor_free(running_routers
);
697 tor_free(router_status
);
698 tor_free(identity_pkey
);
702 SMARTLIST_FOREACH(descriptor_list
, descriptor_entry_t
*, d
,
703 if (strlcat(buf
, d
->descriptor
, buf_len
) >= buf_len
)
706 /* These multiple strlcat calls are inefficient, but dwarfed by the RSA
709 if (strlcat(buf
, "directory-signature ", buf_len
) >= buf_len
)
711 if (strlcat(buf
, get_options()->Nickname
, buf_len
) >= buf_len
)
713 if (strlcat(buf
, "\n", buf_len
) >= buf_len
)
716 if (router_get_dir_hash(buf
,digest
)) {
717 log_fn(LOG_WARN
,"couldn't compute digest");
721 if (crypto_pk_private_sign(private_key
, signature
, digest
, 20) < 0) {
722 log_fn(LOG_WARN
,"couldn't sign digest");
726 log(LOG_DEBUG
,"generated directory digest begins with %s",hex_str(digest
,4));
728 if (strlcat(cp
, "-----BEGIN SIGNATURE-----\n", buf_len
) >= buf_len
)
733 if (base64_encode(cp
, buf_len
-i
, signature
, 128) < 0) {
734 log_fn(LOG_WARN
,"couldn't base64-encode signature");
739 if (strlcat(buf
, "-----END SIGNATURE-----\n", buf_len
) >= buf_len
)
745 log_fn(LOG_WARN
,"tried to exceed string length.");
750 /** Most recently generated encoded signed directory. */
751 static char *the_directory
= NULL
;
752 static size_t the_directory_len
= 0;
753 static char *the_directory_z
= NULL
;
754 static size_t the_directory_z_len
= 0;
756 typedef struct cached_dir_t
{
764 /* used only by non-auth dirservers */
765 static cached_dir_t cached_directory
= { NULL
, NULL
, 0, 0, 0 };
766 static cached_dir_t cached_runningrouters
= { NULL
, NULL
, 0, 0, 0 };
768 /** If we have no cached directory, or it is older than <b>when</b>, then
769 * replace it with <b>directory</b>, published at <b>when</b>.
771 void dirserv_set_cached_directory(const char *directory
, time_t when
,
772 int is_running_routers
)
777 d
= is_running_routers
? &cached_runningrouters
: &cached_directory
;
778 if (when
<=d
->published
) {
779 log_fn(LOG_INFO
, "Ignoring old directory; not caching.");
780 } else if (when
>=now
+ROUTER_ALLOW_SKEW
) {
781 log_fn(LOG_INFO
, "Ignoring future directory; not caching.");
782 } else if (when
>d
->published
&&
783 when
<now
+ROUTER_ALLOW_SKEW
) {
784 log_fn(LOG_DEBUG
, "Caching directory.");
786 d
->dir
= tor_strdup(directory
);
787 d
->dir_len
= strlen(directory
);
789 if (tor_gzip_compress(&(d
->dir_z
), &(d
->dir_z_len
), d
->dir
, d
->dir_len
,
791 log_fn(LOG_WARN
,"Error compressing cached directory");
794 if (!is_running_routers
) {
796 tor_snprintf(filename
,sizeof(filename
),"%s/cached-directory", get_options()->DataDirectory
);
797 if (write_str_to_file(filename
,cached_directory
.dir
,0) < 0) {
798 log_fn(LOG_NOTICE
, "Couldn't write cached directory to disk. Ignoring.");
804 /** Set *<b>directory</b> to the most recently generated encoded signed
805 * directory, generating a new one as necessary. If not an authoritative
806 * directory may return 0 if no directory is yet cached.*/
807 size_t dirserv_get_directory(const char **directory
, int compress
)
809 if (!get_options()->AuthoritativeDir
) {
810 cached_dir_t
*d
= &cached_directory
;
811 *directory
= compress
? d
->dir_z
: d
->dir
;
813 return compress
? d
->dir_z_len
: d
->dir_len
;
815 /* no directory yet retrieved */
819 if (the_directory_is_dirty
&&
820 the_directory_is_dirty
+ DIR_REGEN_SLACK_TIME
< time(NULL
)) {
821 if (dirserv_regenerate_directory())
824 log(LOG_INFO
,"Directory still clean, reusing.");
826 *directory
= compress
? the_directory_z
: the_directory
;
827 return compress
? the_directory_z_len
: the_directory_len
;
831 * Generate a fresh directory (authdirservers only.)
833 static int dirserv_regenerate_directory(void)
835 char *new_directory
=NULL
;
837 if (dirserv_dump_directory_to_string(&new_directory
,
838 get_identity_key())) {
839 log(LOG_WARN
, "Error creating directory.");
840 tor_free(new_directory
);
843 tor_free(the_directory
);
844 the_directory
= new_directory
;
845 the_directory_len
= strlen(the_directory
);
846 log_fn(LOG_INFO
,"New directory (size %d):\n%s",(int)the_directory_len
,
848 tor_free(the_directory_z
);
849 if (tor_gzip_compress(&the_directory_z
, &the_directory_z_len
,
850 the_directory
, the_directory_len
,
852 log_fn(LOG_WARN
, "Error gzipping directory.");
856 /* Now read the directory we just made in order to update our own
857 * router lists. This does more signature checking than is strictly
858 * necessary, but safe is better than sorry. */
859 new_directory
= tor_strdup(the_directory
);
860 /* use a new copy of the dir, since get_dir_from_string scribbles on it */
861 if (router_load_routerlist_from_directory(new_directory
,
862 get_identity_key(), 1, 0)) {
863 log_fn(LOG_ERR
, "We just generated a directory we can't parse. Dying.");
867 tor_free(new_directory
);
868 the_directory_is_dirty
= 0;
870 /* Save the directory to disk so we re-load it quickly on startup.
872 dirserv_set_cached_directory(the_directory
, time(NULL
), 0);
877 static char *the_runningrouters
=NULL
;
878 static size_t the_runningrouters_len
=0;
879 static char *the_runningrouters_z
=NULL
;
880 static size_t the_runningrouters_z_len
=0;
882 /** Replace the current running-routers list with a newly generated one. */
883 static int generate_runningrouters(crypto_pk_env_t
*private_key
)
886 char *router_status
=NULL
;
887 char digest
[DIGEST_LEN
];
888 char signature
[PK_BYTES
];
893 char *identity_pkey
; /* Identity key, DER64-encoded. */
895 if (list_server_status(NULL
, &router_status
)) {
898 /* ASN.1-encode the public key. This is a temporary measure; once
899 * everyone is running 0.0.9pre3 or later, we can shift to using a
900 * PEM-encoded key instead.
903 if (crypto_pk_DER64_encode_public_key(private_key
, &identity_pkey
)<0) {
904 log_fn(LOG_WARN
,"write identity_pkey to string failed!");
910 if (crypto_pk_write_public_key_to_string(private_key
,&identity_pkey
,&l
)<0) {
911 log_fn(LOG_WARN
,"write identity_pkey to string failed!");
916 published_on
= time(NULL
);
917 format_iso_time(published
, published_on
);
919 len
= 2048+strlen(router_status
);
920 s
= tor_malloc_zero(len
);
921 tor_snprintf(s
, len
, "network-status\n"
924 "opt dir-signing-key %s\n"
925 "directory-signature %s\n"
926 "-----BEGIN SIGNATURE-----\n",
927 published
, router_status
, identity_pkey
, get_options()->Nickname
);
928 tor_free(router_status
);
929 tor_free(identity_pkey
);
930 if (router_get_runningrouters_hash(s
,digest
)) {
931 log_fn(LOG_WARN
,"couldn't compute digest");
934 if (crypto_pk_private_sign(private_key
, signature
, digest
, 20) < 0) {
935 log_fn(LOG_WARN
,"couldn't sign digest");
941 if (base64_encode(cp
, len
-i
, signature
, 128) < 0) {
942 log_fn(LOG_WARN
,"couldn't base64-encode signature");
945 if (strlcat(s
, "-----END SIGNATURE-----\n", len
) >= len
) {
949 tor_free(the_runningrouters
);
950 the_runningrouters
= s
;
951 the_runningrouters_len
= strlen(s
);
952 tor_free(the_runningrouters_z
);
953 if (tor_gzip_compress(&the_runningrouters_z
, &the_runningrouters_z_len
,
954 the_runningrouters
, the_runningrouters_len
,
956 log_fn(LOG_WARN
, "Error gzipping runningrouters");
959 runningrouters_is_dirty
= 0;
961 /* We don't cache running-routers to disk, so there's no point in
962 * authdirservers caching it. */
963 /* dirserv_set_cached_directory(the_runningrouters, time(NULL), 1); */
968 tor_free(router_status
);
972 /** Set *<b>rr</b> to the most recently generated encoded signed
973 * running-routers list, generating a new one as necessary. Return the
974 * size of the directory on success, and 0 on failure. */
975 size_t dirserv_get_runningrouters(const char **rr
, int compress
)
977 if (!get_options()->AuthoritativeDir
) {
978 cached_dir_t
*d
= &cached_runningrouters
;
979 *rr
= compress
? d
->dir_z
: d
->dir
;
981 return compress
? d
->dir_z_len
: d
->dir_len
;
983 /* no directory yet retrieved */
987 if (runningrouters_is_dirty
&&
988 runningrouters_is_dirty
+ DIR_REGEN_SLACK_TIME
< time(NULL
)) {
989 if (generate_runningrouters(get_identity_key())) {
990 log_fn(LOG_ERR
, "Couldn't generate running-routers list?");
994 *rr
= compress
? the_runningrouters_z
: the_runningrouters
;
995 return compress
? the_runningrouters_z_len
: the_runningrouters_len
;