dirserv.c 26 KB

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