Forward port changelog
[tor.git] / src / or / dirserv.c
blob610cbf5e3722d7eb6d99c72095b98280206686bd
1 /* Copyright 2001-2004 Roger Dingledine.
2 * Copyright 2004 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.
12 **/
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 {
33 char *nickname;
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)
47 int i;
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);
57 return;
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.
69 int
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");
75 return -1;
77 add_fingerprint_to_dir(nickname, fp);
78 return 0;
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. */
87 int
88 dirserv_parse_fingerprint_file(const char *fname)
90 char *cf;
91 char *nickname, *fingerprint;
92 smartlist_t *fingerprint_list_new;
93 int i, result;
94 fingerprint_entry_t *ent;
95 struct config_line_t *front=NULL, *list;
97 cf = read_file_to_str(fname, 0);
98 if (!cf) {
99 log_fn(LOG_WARN, "Cannot open fingerprint file %s", fname);
100 return -1;
102 result = config_get_lines(cf, &front);
103 tor_free(cf);
104 if (result < 0) {
105 log_fn(LOG_WARN, "Error reading from fingerprint file");
106 return -1;
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);
115 continue;
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);
121 continue;
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. */
126 log(LOG_NOTICE,
127 "Authorizing a nickname '%s' would break many clients; skipping.",
128 DEFAULT_CLIENT_NICKNAME);
129 continue;
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();
152 return 0;
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)
162 int i, found=0;
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)) {
174 found = 1;
175 break;
179 if (!found) { /* No such server known */
180 log_fn(LOG_INFO,"no fingerprint found for '%s'",router->nickname);
181 return 0;
183 if (crypto_pk_get_fingerprint(router->identity_pkey, fp, 0)) {
184 log_fn(LOG_WARN,"error computing fingerprint");
185 return -1;
187 if (0==strcasecmp(ent->fingerprint, fp)) {
188 log_fn(LOG_DEBUG,"good fingerprint for '%s'",router->nickname);
189 return 1; /* Right fingerprint. */
190 } else {
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)
203 return NULL;
204 tor_assert(digest);
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; } );
210 return NULL;
213 #if 0
214 /** Return true iff any router named <b>nickname</b> with <b>digest</b>
215 * is in the verified fingerprint list. */
216 static int
217 router_nickname_is_approved(const char *nickname, const char *digest)
219 const char *n;
221 n = dirserv_get_nickname_by_digest(digest);
222 if (n && !strcasecmp(n,nickname))
223 return 1;
224 else
225 return 0;
227 #endif
229 /** Clear the current fingerprint list. */
230 void
231 dirserv_free_fingerprint_list()
233 int i;
234 fingerprint_entry_t *ent;
235 if (!fingerprint_list)
236 return;
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);
242 tor_free(ent);
244 smartlist_free(fingerprint_list);
245 fingerprint_list = NULL;
249 * Descriptor list
252 /** A directory server's view of a server descriptor. Contains both
253 * parsed and unparsed versions. */
254 typedef struct descriptor_entry_t {
255 char *nickname;
256 time_t published;
257 size_t desc_len;
258 char *descriptor;
259 int verified;
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);
272 tor_free(desc);
275 /** Release all storage that the dirserv is holding for server
276 * descriptors. */
277 void
278 dirserv_free_descriptors()
280 if (!descriptor_list)
281 return;
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. */
289 static int
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);
298 return -1;
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 */
305 return 0;
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
312 * to NULL.
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;
324 int i, r, found=-1;
325 char *start, *end;
326 char *desc_tmp = NULL;
327 const char *cp;
328 size_t desc_len;
329 time_t now;
330 int verified=1; /* whether we knew its fingerprint already */
331 tor_assert(msg);
332 *msg = NULL;
333 if (!descriptor_list)
334 descriptor_list = smartlist_create();
336 start = strstr(*desc, "router ");
337 if (!start) {
338 log_fn(LOG_WARN, "no 'router' line found. This is not a descriptor.");
339 return -2;
341 if ((end = strstr(start+6, "\nrouter "))) {
342 ++end; /* Include NL. */
343 } else if ((end = strstr(start+6, "\ndirectory-signature"))) {
344 ++end;
345 } else {
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);
353 tor_free(desc_tmp);
354 if (!ri) {
355 log(LOG_WARN, "Couldn't parse descriptor");
356 *msg = "Rejected: Couldn't parse server descriptor.";
357 return -1;
359 /* Okay. Now check whether the fingerprint is recognized. */
360 r = dirserv_router_fingerprint_is_known(ri);
361 if (r==-1) {
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.";
364 routerinfo_free(ri);
365 *desc = end;
366 return -1;
368 if (r==0) {
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);
374 } else {
375 log_fn(LOG_INFO, "Fingerprint line: %s %s", ri->nickname, fp);
377 verified = 0;
379 /* Is there too much clock skew? */
380 now = time(NULL);
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.";
384 routerinfo_free(ri);
385 *desc = end;
386 return -1;
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.";
391 routerinfo_free(ri);
392 *desc = end;
393 return -1;
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.";
398 routerinfo_free(ri);
399 *desc = end;
400 return -1;
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)) {
407 found = i;
408 break;
411 if (found >= 0) {
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. */
418 routerinfo_free(ri);
419 *desc = end;
420 return verified;
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);
427 } else {
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);
438 ent->router = ri;
439 ent->verified = verified;
440 smartlist_add(descriptor_list, ent);
442 *desc = end;
443 directory_set_dirty();
445 return verified;
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.)
452 static void
453 directory_remove_unrecognized(void)
455 int i;
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",
464 ent->nickname);
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
473 * generated one.
475 void
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
487 * <b>dir</b>.
490 dirserv_load_from_directory_string(const char *dir)
492 const char *cp = dir, *m;
493 while (1) {
494 cp = strstr(cp, "\nrouter ");
495 if (!cp) break;
496 ++cp;
497 if (dirserv_add_descriptor(&cp,&m) < -1) {
498 /* only fail if parsing failed; keep going if simply rejected */
499 return -1;
501 --cp; /*Back up to newline.*/
503 return 0;
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.
512 static char *
513 list_single_server_status(descriptor_entry_t *desc, int is_live,
514 int rr_format)
516 char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
517 char *cp;
519 tor_assert(desc);
520 tor_assert(desc->router);
522 cp = buf;
523 if (!is_live) {
524 *cp++ = '!';
526 if (desc->verified) {
527 strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
528 cp += strlen(cp);
529 if (!rr_format)
530 *cp++ = '=';
532 if (!desc->verified || !rr_format) {
533 *cp++ = '$';
534 base16_encode(cp, HEX_DIGEST_LEN+1, desc->router->identity_digest,
535 DIGEST_LEN);
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.
544 static int
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,
561 int is_live;
562 connection_t *conn;
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);
585 return 0;
588 /** Remove any descriptors from the directory that are more than <b>age</b>
589 * seconds old.
591 void
592 dirserv_remove_old_servers(int age)
594 int i;
595 time_t cutoff;
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
615 * failure.
618 dirserv_dump_directory_to_string(char **dir_out,
619 crypto_pk_env_t *private_key)
621 char *cp;
622 char *running_routers, *router_status;
623 char *identity_pkey; /* Identity key, DER64-encoded. */
624 char *recommended_versions;
625 char digest[20];
626 char signature[128];
627 char published[33];
628 time_t published_on;
629 char *buf = NULL;
630 size_t buf_len;
631 int i;
633 tor_assert(dir_out);
634 *dir_out = NULL;
636 if (!descriptor_list)
637 descriptor_list = smartlist_create();
639 if (list_server_status(&running_routers, &router_status))
640 return -1;
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.
646 #if 1
647 if (crypto_pk_DER64_encode_public_key(private_key, &identity_pkey)<0) {
648 log_fn(LOG_WARN,"write identity_pkey to string failed!");
649 return -1;
651 #else
653 int l;
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!");
656 return -1;
659 #endif
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
686 overruns.*/
688 tor_snprintf(buf, buf_len,
689 "signed-directory\n"
690 "published %s\n"
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,
696 identity_pkey);
698 tor_free(recommended_versions);
699 tor_free(running_routers);
700 tor_free(router_status);
701 tor_free(identity_pkey);
702 i = strlen(buf);
703 cp = buf+i;
705 SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t *, d,
706 if (strlcat(buf, d->descriptor, buf_len) >= buf_len)
707 goto truncated);
709 /* These multiple strlcat calls are inefficient, but dwarfed by the RSA
710 signature.
712 if (strlcat(buf, "directory-signature ", buf_len) >= buf_len)
713 goto truncated;
714 if (strlcat(buf, get_options()->Nickname, buf_len) >= buf_len)
715 goto truncated;
716 if (strlcat(buf, "\n", buf_len) >= buf_len)
717 goto truncated;
719 if (router_get_dir_hash(buf,digest)) {
720 log_fn(LOG_WARN,"couldn't compute digest");
721 tor_free(buf);
722 return -1;
724 if (crypto_pk_private_sign(private_key, signature, digest, 20) < 0) {
725 log_fn(LOG_WARN,"couldn't sign digest");
726 tor_free(buf);
727 return -1;
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)
732 goto truncated;
734 i = strlen(buf);
735 cp = buf+i;
736 if (base64_encode(cp, buf_len-i, signature, 128) < 0) {
737 log_fn(LOG_WARN,"couldn't base64-encode signature");
738 tor_free(buf);
739 return -1;
742 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
743 goto truncated;
745 *dir_out = buf;
746 return 0;
747 truncated:
748 log_fn(LOG_WARN,"tried to exceed string length.");
749 tor_free(buf);
750 return -1;
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 {
760 char *dir;
761 char *dir_z;
762 size_t dir_len;
763 size_t dir_z_len;
764 time_t published;
765 } 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)
777 time_t now;
778 cached_dir_t *d;
779 now = time(NULL);
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.");
788 tor_free(d->dir);
789 d->dir = tor_strdup(directory);
790 d->dir_len = strlen(directory);
791 tor_free(d->dir_z);
792 if (tor_gzip_compress(&(d->dir_z), &(d->dir_z_len), d->dir, d->dir_len,
793 ZLIB_METHOD)) {
794 log_fn(LOG_WARN,"Error compressing cached directory");
796 d->published = when;
797 if (!is_running_routers) {
798 char filename[512];
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;
815 if (*directory) {
816 return compress ? d->dir_z_len : d->dir_len;
817 } else {
818 /* no directory yet retrieved */
819 return 0;
822 if (the_directory_is_dirty &&
823 the_directory_is_dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
824 if (dirserv_regenerate_directory())
825 return 0;
826 } else {
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);
844 return -1;
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,
850 the_directory);
851 tor_free(the_directory_z);
852 if (tor_gzip_compress(&the_directory_z, &the_directory_z_len,
853 the_directory, the_directory_len,
854 ZLIB_METHOD)) {
855 log_fn(LOG_WARN, "Error gzipping directory.");
856 return -1;
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.");
867 tor_cleanup();
868 exit(0);
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);
877 return 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)
888 char *s=NULL, *cp;
889 char *router_status=NULL;
890 char digest[DIGEST_LEN];
891 char signature[PK_BYTES];
892 int i;
893 char published[33];
894 size_t len;
895 time_t published_on;
896 char *identity_pkey; /* Identity key, DER64-encoded. */
898 if (list_server_status(NULL, &router_status)) {
899 goto err;
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.
905 #if 1
906 if (crypto_pk_DER64_encode_public_key(private_key, &identity_pkey)<0) {
907 log_fn(LOG_WARN,"write identity_pkey to string failed!");
908 goto err;
910 #else
912 int l;
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!");
915 goto err;
918 #endif
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"
925 "published %s\n"
926 "router-status %s\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");
935 goto err;
937 if (crypto_pk_private_sign(private_key, signature, digest, 20) < 0) {
938 log_fn(LOG_WARN,"couldn't sign digest");
939 goto err;
942 i = strlen(s);
943 cp = s+i;
944 if (base64_encode(cp, len-i, signature, 128) < 0) {
945 log_fn(LOG_WARN,"couldn't base64-encode signature");
946 goto err;
948 if (strlcat(s, "-----END SIGNATURE-----\n", len) >= len) {
949 goto err;
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,
958 ZLIB_METHOD)) {
959 log_fn(LOG_WARN, "Error gzipping runningrouters");
960 return -1;
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); */
968 return 0;
969 err:
970 tor_free(s);
971 tor_free(router_status);
972 return -1;
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;
983 if (*rr) {
984 return compress ? d->dir_z_len : d->dir_len;
985 } else {
986 /* no directory yet retrieved */
987 return 0;
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?");
994 return 0;
997 *rr = compress ? the_runningrouters_z : the_runningrouters;
998 return compress ? the_runningrouters_z_len : the_runningrouters_len;