dirserv.c 27 KB

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