dirserv.c 27 KB

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