dirserv.c 24 KB

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