dirserv.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. /* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #include "or.h"
  5. /**
  6. * \file dirserv.c
  7. * \brief Directory server core implementation.
  8. **/
  9. /** How far in the future do we allow a router to get? (seconds) */
  10. #define ROUTER_ALLOW_SKEW (30*60)
  11. extern or_options_t options; /**< command-line and config-file options */
  12. /** Do we need to regenerate the directory when someone asks for it? */
  13. static int the_directory_is_dirty = 1;
  14. static int list_running_servers(char **nicknames_out);
  15. static void directory_remove_unrecognized(void);
  16. /************** Fingerprint handling code ************/
  17. typedef struct fingerprint_entry_t {
  18. char *nickname;
  19. char *fingerprint;
  20. } fingerprint_entry_t;
  21. /** List of nickname-\>identity fingerprint mappings for all the routers
  22. * that we recognize. Used to prevent Sybil attacks. */
  23. static smartlist_t *fingerprint_list = NULL;
  24. /** Add the fingerprint <b>fp</b> for the nickname <b>nickname</b> to
  25. * the global list of recognized identity key fingerprints.
  26. */
  27. void /* Should be static; exposed for testing */
  28. add_fingerprint_to_dir(const char *nickname, const char *fp)
  29. {
  30. int i;
  31. fingerprint_entry_t *ent;
  32. if (!fingerprint_list)
  33. fingerprint_list = smartlist_create();
  34. for (i = 0; i < smartlist_len(fingerprint_list); ++i) {
  35. ent = smartlist_get(fingerprint_list, i);
  36. if (!strcasecmp(ent->nickname,nickname)) {
  37. tor_free(ent->fingerprint);
  38. ent->fingerprint = tor_strdup(fp);
  39. return;
  40. }
  41. }
  42. ent = tor_malloc(sizeof(fingerprint_entry_t));
  43. ent->nickname = tor_strdup(nickname);
  44. ent->fingerprint = tor_strdup(fp);
  45. smartlist_add(fingerprint_list, ent);
  46. }
  47. /** Add the nickname and fingerprint for this OR to the recognized list.
  48. */
  49. int
  50. dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk)
  51. {
  52. char fp[FINGERPRINT_LEN+1];
  53. if (crypto_pk_get_fingerprint(pk, fp)<0) {
  54. log_fn(LOG_ERR, "Error computing fingerprint");
  55. return -1;
  56. }
  57. add_fingerprint_to_dir(nickname, fp);
  58. return 0;
  59. }
  60. /** Parse the nickname-\>fingerprint mappings stored in the file named
  61. * <b>fname</b>. The file format is line-based, with each non-blank
  62. * holding one nickname, some space, and a fingerprint for that
  63. * nickname. On success, replace the current fingerprint list with
  64. * the contents of <b>fname</b> and return 0. On failure, leave the
  65. * current fingerprint list untouched, and return -1. */
  66. int
  67. dirserv_parse_fingerprint_file(const char *fname)
  68. {
  69. FILE *file;
  70. char line[FINGERPRINT_LEN+MAX_NICKNAME_LEN+20+1];
  71. char *nickname, *fingerprint;
  72. smartlist_t *fingerprint_list_new;
  73. int i, result;
  74. fingerprint_entry_t *ent;
  75. if(!(file = fopen(fname, "r"))) {
  76. log_fn(LOG_WARN, "Cannot open fingerprint file %s", fname);
  77. return -1;
  78. }
  79. fingerprint_list_new = smartlist_create();
  80. while( (result=parse_line_from_file(line, sizeof(line),file,&nickname,&fingerprint)) > 0) {
  81. if (strlen(nickname) > MAX_NICKNAME_LEN) {
  82. log(LOG_WARN, "Nickname %s too long in fingerprint file. Skipping.", nickname);
  83. continue;
  84. }
  85. if(strlen(fingerprint) != FINGERPRINT_LEN ||
  86. !crypto_pk_check_fingerprint_syntax(fingerprint)) {
  87. log_fn(LOG_WARN, "Invalid fingerprint (nickname %s, fingerprint %s). Skipping.",
  88. nickname, fingerprint);
  89. continue;
  90. }
  91. for (i = 0; i < smartlist_len(fingerprint_list_new); ++i) {
  92. ent = smartlist_get(fingerprint_list_new, i);
  93. if (0==strcasecmp(ent->nickname, nickname)) {
  94. log(LOG_WARN, "Duplicate nickname %s. Skipping.",nickname);
  95. break; /* out of the for. the 'if' below means skip to the next line. */
  96. }
  97. }
  98. if(i == smartlist_len(fingerprint_list_new)) { /* not a duplicate */
  99. ent = tor_malloc(sizeof(fingerprint_entry_t));
  100. ent->nickname = tor_strdup(nickname);
  101. ent->fingerprint = tor_strdup(fingerprint);
  102. smartlist_add(fingerprint_list_new, ent);
  103. }
  104. }
  105. fclose(file);
  106. if(result == 0) { /* eof; replace the global fingerprints list. */
  107. dirserv_free_fingerprint_list();
  108. fingerprint_list = fingerprint_list_new;
  109. /* Delete any routers whose fingerprints we no longer recognize */
  110. directory_remove_unrecognized();
  111. return 0;
  112. }
  113. /* error */
  114. log_fn(LOG_WARN, "Error reading from fingerprint file");
  115. for (i = 0; i < smartlist_len(fingerprint_list_new); ++i) {
  116. ent = smartlist_get(fingerprint_list_new, i);
  117. tor_free(ent->nickname);
  118. tor_free(ent->fingerprint);
  119. tor_free(ent);
  120. }
  121. smartlist_free(fingerprint_list_new);
  122. return -1;
  123. }
  124. /** Check whether <b>router</b> has a nickname/identity key combination that
  125. * we recognize from the fingerprint list. Return 1 if router's
  126. * identity and nickname match, -1 if we recognize the nickname but
  127. * the identity key is wrong, and 0 if the nickname is not known. */
  128. int
  129. dirserv_router_fingerprint_is_known(const routerinfo_t *router)
  130. {
  131. int i, found=0;
  132. fingerprint_entry_t *ent =NULL;
  133. char fp[FINGERPRINT_LEN+1];
  134. if (!fingerprint_list)
  135. fingerprint_list = smartlist_create();
  136. log_fn(LOG_DEBUG, "%d fingerprints known.", smartlist_len(fingerprint_list));
  137. for (i=0;i<smartlist_len(fingerprint_list);++i) {
  138. ent = smartlist_get(fingerprint_list, i);
  139. log_fn(LOG_DEBUG,"%s vs %s", router->nickname, ent->nickname);
  140. if (!strcasecmp(router->nickname,ent->nickname)) {
  141. found = 1;
  142. break;
  143. }
  144. }
  145. if (!found) { /* No such server known */
  146. log_fn(LOG_INFO,"no fingerprint found for %s",router->nickname);
  147. return 0;
  148. }
  149. if (crypto_pk_get_fingerprint(router->identity_pkey, fp)) {
  150. log_fn(LOG_WARN,"error computing fingerprint");
  151. return -1;
  152. }
  153. if (0==strcasecmp(ent->fingerprint, fp)) {
  154. log_fn(LOG_DEBUG,"good fingerprint for %s",router->nickname);
  155. return 1; /* Right fingerprint. */
  156. } else {
  157. log_fn(LOG_WARN,"mismatched fingerprint for %s",router->nickname);
  158. return -1; /* Wrong fingerprint. */
  159. }
  160. }
  161. /** Return true iff any router named <b>nickname</b> is in the fingerprint
  162. * list. */
  163. static int
  164. router_nickname_is_approved(const char *nickname)
  165. {
  166. int i;
  167. fingerprint_entry_t *ent;
  168. if (!fingerprint_list)
  169. return 0;
  170. for (i=0;i<smartlist_len(fingerprint_list);++i) {
  171. ent = smartlist_get(fingerprint_list, i);
  172. if (!strcasecmp(nickname,ent->nickname)) {
  173. return 1;
  174. }
  175. }
  176. return 0;
  177. }
  178. /** Clear the current fingerprint list. */
  179. void
  180. dirserv_free_fingerprint_list()
  181. {
  182. int i;
  183. fingerprint_entry_t *ent;
  184. if (!fingerprint_list)
  185. return;
  186. for (i = 0; i < smartlist_len(fingerprint_list); ++i) {
  187. ent = smartlist_get(fingerprint_list, i);
  188. tor_free(ent->nickname);
  189. tor_free(ent->fingerprint);
  190. tor_free(ent);
  191. }
  192. smartlist_free(fingerprint_list);
  193. fingerprint_list = NULL;
  194. }
  195. /*
  196. * Descriptor list
  197. */
  198. /** A directory server's view of a server descriptor. Contains both
  199. * parsed and unparsed versions. */
  200. typedef struct descriptor_entry_t {
  201. char *nickname;
  202. time_t published;
  203. size_t desc_len;
  204. char *descriptor;
  205. routerinfo_t *router;
  206. } descriptor_entry_t;
  207. /** List of all server descriptors that this dirserv is holding. */
  208. static smartlist_t *descriptor_list = NULL;
  209. /** Release the storage held by <b>desc</b> */
  210. static void free_descriptor_entry(descriptor_entry_t *desc)
  211. {
  212. tor_free(desc->descriptor);
  213. tor_free(desc->nickname);
  214. routerinfo_free(desc->router);
  215. free(desc);
  216. }
  217. /** Release all storage that the dirserv is holding for server
  218. * descriptors. */
  219. void
  220. dirserv_free_descriptors()
  221. {
  222. if (!descriptor_list)
  223. return;
  224. SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t *, d,
  225. free_descriptor_entry(d));
  226. smartlist_clear(descriptor_list);
  227. }
  228. /** Parse the server descriptor at *desc and maybe insert it into the
  229. * list of service descriptors, and (if the descriptor is well-formed)
  230. * advance *desc immediately past the descriptor's end.
  231. *
  232. * Return 1 if descriptor is well-formed and accepted;
  233. * 0 if well-formed and server is unapproved;
  234. * -1 if not well-formed or other error.
  235. */
  236. int
  237. dirserv_add_descriptor(const char **desc)
  238. {
  239. descriptor_entry_t *ent = NULL;
  240. routerinfo_t *ri = NULL;
  241. int i, r, found=-1;
  242. char *start, *end;
  243. char *desc_tmp = NULL;
  244. const char *cp;
  245. size_t desc_len;
  246. time_t now;
  247. if (!descriptor_list)
  248. descriptor_list = smartlist_create();
  249. start = strstr(*desc, "router ");
  250. if (!start) {
  251. log_fn(LOG_WARN, "no 'router' line found. This is not a descriptor.");
  252. return -1;
  253. }
  254. if ((end = strstr(start+6, "\nrouter "))) {
  255. ++end; /* Include NL. */
  256. } else if ((end = strstr(start+6, "\ndirectory-signature"))) {
  257. ++end;
  258. } else {
  259. end = start+strlen(start);
  260. }
  261. desc_len = end-start;
  262. cp = desc_tmp = tor_strndup(start, desc_len);
  263. /* Check: is the descriptor syntactically valid? */
  264. ri = router_parse_entry_from_string(cp, NULL);
  265. tor_free(desc_tmp);
  266. if (!ri) {
  267. log(LOG_WARN, "Couldn't parse descriptor");
  268. return -1;
  269. }
  270. /* Okay. Now check whether the fingerprint is recognized. */
  271. r = dirserv_router_fingerprint_is_known(ri);
  272. if(r<1) {
  273. if(r==0) {
  274. char fp[FINGERPRINT_LEN+1];
  275. log_fn(LOG_WARN, "Unknown nickname %s (%s:%d). Not adding.",
  276. ri->nickname, ri->address, ri->or_port);
  277. if (crypto_pk_get_fingerprint(ri->identity_pkey, fp) < 0) {
  278. log_fn(LOG_WARN, "Error computing fingerprint for %s", ri->nickname);
  279. } else {
  280. log_fn(LOG_WARN, "Fingerprint line: %s %s", ri->nickname, fp);
  281. }
  282. } else {
  283. log_fn(LOG_WARN, "Known nickname %s, wrong fingerprint. Not adding.", ri->nickname);
  284. }
  285. routerinfo_free(ri);
  286. *desc = end;
  287. return 0;
  288. }
  289. /* Is there too much clock skew? */
  290. now = time(NULL);
  291. if (ri->published_on > now+ROUTER_ALLOW_SKEW) {
  292. log_fn(LOG_WARN, "Publication time for nickname %s is too far in the future; possible clock skew. Not adding.", ri->nickname);
  293. routerinfo_free(ri);
  294. *desc = end;
  295. return 0;
  296. }
  297. if (ri->published_on < now-ROUTER_MAX_AGE) {
  298. log_fn(LOG_WARN, "Publication time for router with nickname %s is too far in the past. Not adding.", ri->nickname);
  299. routerinfo_free(ri);
  300. *desc = end;
  301. return 0;
  302. }
  303. /* Do we already have an entry for this router? */
  304. for (i = 0; i < smartlist_len(descriptor_list); ++i) {
  305. ent = smartlist_get(descriptor_list, i);
  306. if (!strcasecmp(ri->nickname, ent->nickname)) {
  307. found = i;
  308. break;
  309. }
  310. }
  311. if (found >= 0) {
  312. /* if so, decide whether to update it. */
  313. if (ent->published > ri->published_on) {
  314. /* We already have a newer descriptor */
  315. log_fn(LOG_INFO,"We already have a newer desc for nickname %s. Not adding.",ri->nickname);
  316. /* This isn't really an error; return success. */
  317. routerinfo_free(ri);
  318. *desc = end;
  319. return 1;
  320. }
  321. /* We don't have a newer one; we'll update this one. */
  322. log_fn(LOG_INFO,"Dirserv updating desc for nickname %s",ri->nickname);
  323. free_descriptor_entry(ent);
  324. smartlist_del_keeporder(descriptor_list, found);
  325. } else {
  326. /* Add at the end. */
  327. log_fn(LOG_INFO,"Dirserv adding desc for nickname %s",ri->nickname);
  328. }
  329. ent = tor_malloc(sizeof(descriptor_entry_t));
  330. ent->nickname = tor_strdup(ri->nickname);
  331. ent->published = ri->published_on;
  332. ent->desc_len = desc_len;
  333. ent->descriptor = tor_malloc(desc_len+1);
  334. strncpy(ent->descriptor, start, desc_len);
  335. ent->descriptor[desc_len] = '\0';
  336. ent->router = ri;
  337. smartlist_add(descriptor_list, ent);
  338. *desc = end;
  339. directory_set_dirty();
  340. return 1;
  341. }
  342. /** Remove all descriptors whose nicknames or fingerprints we don't
  343. * recognize. (Descriptors that used to be good can become
  344. * unrecognized when we reload the fingerprint list.)
  345. */
  346. static void
  347. directory_remove_unrecognized(void)
  348. {
  349. int i;
  350. descriptor_entry_t *ent;
  351. if (!descriptor_list)
  352. descriptor_list = smartlist_create();
  353. for (i = 0; i < smartlist_len(descriptor_list); ++i) {
  354. ent = smartlist_get(descriptor_list, i);
  355. if (dirserv_router_fingerprint_is_known(ent->router)<=0) {
  356. log(LOG_INFO, "Router %s is no longer recognized",
  357. ent->nickname);
  358. free_descriptor_entry(ent);
  359. smartlist_del(descriptor_list, i--);
  360. }
  361. }
  362. }
  363. /** Mark the directory as <b>dirty</b> -- when we're next asked for a
  364. * directory, we will rebuild it instead of reusing the most recently
  365. * generated one.
  366. */
  367. void
  368. directory_set_dirty()
  369. {
  370. the_directory_is_dirty = 1;
  371. }
  372. /** Load all descriptors from an earlier directory stored in the string
  373. * <b>dir</b>.
  374. */
  375. int
  376. dirserv_init_from_directory_string(const char *dir)
  377. {
  378. const char *cp = dir;
  379. while(1) {
  380. cp = strstr(cp, "\nrouter ");
  381. if (!cp) break;
  382. ++cp;
  383. if (dirserv_add_descriptor(&cp) < 0) {
  384. return -1;
  385. }
  386. --cp; /*Back up to newline.*/
  387. }
  388. return 0;
  389. }
  390. /** Set *<b>nicknames_out</b> to a comma-separated list of all the ORs that we
  391. * believe are currently running (because we have open connections to
  392. * them). Return 0 on success; -1 on error.
  393. */
  394. static int
  395. list_running_servers(char **nicknames_out)
  396. {
  397. connection_t **connection_array;
  398. int n_conns;
  399. connection_t *conn;
  400. char *cp;
  401. int i;
  402. int length;
  403. smartlist_t *nicknames;
  404. *nicknames_out = NULL;
  405. nicknames = smartlist_create();
  406. smartlist_add(nicknames, options.Nickname);
  407. get_connection_array(&connection_array, &n_conns);
  408. for (i = 0; i<n_conns; ++i) {
  409. conn = connection_array[i];
  410. if (conn->type != CONN_TYPE_OR || conn->state != OR_CONN_STATE_OPEN)
  411. continue; /* only list successfully handshaked OR's. */
  412. if(!conn->nickname) /* it's an OP, don't list it */
  413. continue;
  414. if (!router_nickname_is_approved(conn->nickname))
  415. continue; /* If we removed them from the approved list, don't list it.*/
  416. smartlist_add(nicknames, conn->nickname);
  417. }
  418. length = smartlist_len(nicknames) + 1; /* spaces + EOS + 1. */
  419. SMARTLIST_FOREACH(nicknames, char *, c, length += strlen(c));
  420. *nicknames_out = tor_malloc_zero(length);
  421. cp = *nicknames_out;
  422. for (i = 0; i<smartlist_len(nicknames); ++i) {
  423. if (i)
  424. strcat(cp, " ");
  425. strcat(cp, (char*)smartlist_get(nicknames,i)); /* can't overflow */
  426. while (*cp)
  427. ++cp;
  428. }
  429. smartlist_free(nicknames);
  430. return 0;
  431. }
  432. /** Remove any descriptors from the directory that are more than ROUTER_MAX_AGE
  433. * seconds old.
  434. */
  435. void
  436. dirserv_remove_old_servers(void)
  437. {
  438. int i;
  439. time_t cutoff;
  440. descriptor_entry_t *ent;
  441. if (!descriptor_list)
  442. descriptor_list = smartlist_create();
  443. cutoff = time(NULL) - ROUTER_MAX_AGE;
  444. for (i = 0; i < smartlist_len(descriptor_list); ++i) {
  445. ent = smartlist_get(descriptor_list, i);
  446. if (ent->published < cutoff) {
  447. /* descriptor_list[i] is too old. Remove it. */
  448. free_descriptor_entry(ent);
  449. smartlist_del(descriptor_list, i--);
  450. directory_set_dirty();
  451. }
  452. }
  453. }
  454. /** Dump all routers currently in the directory into the string
  455. * <b>s</b>, using at most <b>maxlen</b> characters, and signing the
  456. * directory with <b>private_key</b>. Return 0 on success, -1 on
  457. * failure.
  458. */
  459. int
  460. dirserv_dump_directory_to_string(char *s, unsigned int maxlen,
  461. crypto_pk_env_t *private_key)
  462. {
  463. char *cp, *eos;
  464. char digest[20];
  465. char signature[128];
  466. char published[33];
  467. time_t published_on;
  468. int i;
  469. eos = s+maxlen;
  470. if (!descriptor_list)
  471. descriptor_list = smartlist_create();
  472. if (list_running_servers(&cp))
  473. return -1;
  474. dirserv_remove_old_servers();
  475. published_on = time(NULL);
  476. strftime(published, 32, "%Y-%m-%d %H:%M:%S", gmtime(&published_on));
  477. snprintf(s, maxlen,
  478. "signed-directory\n"
  479. "published %s\n"
  480. "recommended-software %s\n"
  481. "running-routers %s\n\n", published, options.RecommendedVersions, cp);
  482. free(cp);
  483. i = strlen(s);
  484. cp = s+i;
  485. SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t *, d,
  486. if (strlcat(s, d->descriptor, maxlen) >= maxlen)
  487. goto truncated);
  488. /* These multiple strlcat calls are inefficient, but dwarfed by the RSA
  489. signature.
  490. */
  491. if (strlcat(s, "directory-signature ", maxlen) >= maxlen)
  492. goto truncated;
  493. if (strlcat(s, options.Nickname, maxlen) >= maxlen)
  494. goto truncated;
  495. if (strlcat(s, "\n", maxlen) >= maxlen)
  496. goto truncated;
  497. if (router_get_dir_hash(s,digest)) {
  498. log_fn(LOG_WARN,"couldn't compute digest");
  499. return -1;
  500. }
  501. if (crypto_pk_private_sign(private_key, digest, 20, signature) < 0) {
  502. log_fn(LOG_WARN,"couldn't sign digest");
  503. return -1;
  504. }
  505. log(LOG_DEBUG,"generated directory digest begins with %s",hex_str(digest,4));
  506. if (strlcat(cp, "-----BEGIN SIGNATURE-----\n", maxlen) >= maxlen)
  507. goto truncated;
  508. i = strlen(s);
  509. cp = s+i;
  510. if (base64_encode(cp, maxlen-i, signature, 128) < 0) {
  511. log_fn(LOG_WARN,"couldn't base64-encode signature");
  512. return -1;
  513. }
  514. if (strlcat(s, "-----END SIGNATURE-----\n", maxlen) >= maxlen)
  515. goto truncated;
  516. return 0;
  517. truncated:
  518. log_fn(LOG_WARN,"tried to exceed string length.");
  519. return -1;
  520. }
  521. /** Most recently generated encoded signed directory. */
  522. static char *the_directory = NULL;
  523. static int the_directory_len = -1;
  524. static char *cached_directory = NULL;
  525. static time_t cached_directory_published = 0;
  526. static int cached_directory_len = -1;
  527. void dirserv_set_cached_directory(const char *directory, time_t when)
  528. {
  529. time_t now;
  530. if (!options.AuthoritativeDir)
  531. return;
  532. now = time(NULL);
  533. if (when>cached_directory_published &&
  534. when<now+ROUTER_ALLOW_SKEW) {
  535. tor_free(cached_directory);
  536. cached_directory = tor_strdup(directory);
  537. cached_directory_len = strlen(cached_directory);
  538. }
  539. }
  540. /** Set *<b>directory</b> to the most recently generated encoded signed
  541. * directory, generating a new one as necessary. */
  542. size_t dirserv_get_directory(const char **directory)
  543. {
  544. char *new_directory;
  545. char filename[512];
  546. if (!options.AuthoritativeDir) {
  547. if (cached_directory) {
  548. *directory = cached_directory;
  549. return (size_t) cached_directory_len;
  550. } else {
  551. /* no directory yet retrieved */
  552. return 0;
  553. }
  554. }
  555. if (the_directory_is_dirty) {
  556. new_directory = tor_malloc(MAX_DIR_SIZE);
  557. if (dirserv_dump_directory_to_string(new_directory, MAX_DIR_SIZE,
  558. get_identity_key())) {
  559. log(LOG_WARN, "Error creating directory.");
  560. free(new_directory);
  561. return 0;
  562. }
  563. tor_free(the_directory);
  564. the_directory = new_directory;
  565. the_directory_len = strlen(the_directory);
  566. log_fn(LOG_INFO,"New directory (size %d):\n%s",the_directory_len,
  567. the_directory);
  568. the_directory_is_dirty = 0;
  569. /* Now read the directory we just made in order to update our own
  570. * router lists. This does more signature checking than is strictly
  571. * necessary, but safe is better than sorry. */
  572. new_directory = tor_strdup(the_directory);
  573. /* use a new copy of the dir, since get_dir_from_string scribbles on it */
  574. if (router_load_routerlist_from_directory(new_directory, get_identity_key())) {
  575. log_fn(LOG_ERR, "We just generated a directory we can't parse. Dying.");
  576. exit(0);
  577. }
  578. free(new_directory);
  579. sprintf(filename,"%s/cached-directory", options.DataDirectory);
  580. if(write_str_to_file(filename,the_directory) < 0) {
  581. log_fn(LOG_WARN, "Couldn't write cached directory to disk. Ignoring.");
  582. }
  583. } else {
  584. log(LOG_INFO,"Directory still clean, reusing.");
  585. }
  586. *directory = the_directory;
  587. return the_directory_len;
  588. }
  589. /** Set *<b>rr</b> to the most recently generated encoded signed
  590. * running-routers list, generating a new one as necessary. */
  591. size_t dirserv_get_runningrouters(const char **rr)
  592. {
  593. /* XXX008 fill in this function */
  594. return 0;
  595. }
  596. /*
  597. Local Variables:
  598. mode:c
  599. indent-tabs-mode:nil
  600. c-basic-offset:2
  601. End:
  602. */