routers.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  1. /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #define OR_PUBLICKEY_BEGIN_TAG "-----BEGIN RSA PUBLIC KEY-----\n"
  5. #define OR_PUBLICKEY_END_TAG "-----END RSA PUBLIC KEY-----\n"
  6. #define OR_SIGNATURE_BEGIN_TAG "-----BEGIN SIGNATURE-----\n"
  7. #define OR_SIGNATURE_END_TAG "-----END SIGNATURE-----\n"
  8. #include "or.h"
  9. /****************************************************************************/
  10. /* router array */
  11. static directory_t *directory = NULL;
  12. extern or_options_t options; /* command-line and config-file options */
  13. extern routerinfo_t *my_routerinfo; /* from main.c */
  14. /****************************************************************************/
  15. struct directory_token;
  16. typedef struct directory_token directory_token_t;
  17. /* static function prototypes */
  18. void routerlist_free(routerinfo_t *list);
  19. static char *eat_whitespace(char *s);
  20. static char *eat_whitespace_no_nl(char *s);
  21. static char *find_whitespace(char *s);
  22. static void router_free_exit_policy(routerinfo_t *router);
  23. static routerinfo_t *router_get_entry_from_string_tok(char**s,
  24. directory_token_t *tok);
  25. static int router_get_list_from_string_tok(char **s, directory_t **dest,
  26. directory_token_t *tok);
  27. static int router_add_exit_policy(routerinfo_t *router,
  28. directory_token_t *tok);
  29. static int
  30. router_resolve_directory(directory_t *dir);
  31. /****************************************************************************/
  32. int learn_my_address(struct sockaddr_in *me) {
  33. /* local host information */
  34. char localhostname[512];
  35. struct hostent *localhost;
  36. static struct sockaddr_in answer;
  37. static int already_learned=0;
  38. if(!already_learned) {
  39. /* obtain local host information */
  40. if(gethostname(localhostname,512) < 0) {
  41. log_fn(LOG_ERR,"Error obtaining local hostname");
  42. return -1;
  43. }
  44. log_fn(LOG_DEBUG,"localhostname is '%s'.",localhostname);
  45. localhost = gethostbyname(localhostname);
  46. if (!localhost) {
  47. log_fn(LOG_ERR,"Error obtaining local host info.");
  48. return -1;
  49. }
  50. memset(&answer,0,sizeof(struct sockaddr_in));
  51. answer.sin_family = AF_INET;
  52. memcpy((void *)&answer.sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
  53. answer.sin_port = htons((uint16_t) options.ORPort);
  54. log_fn(LOG_DEBUG,"chose address as '%s'.",inet_ntoa(answer.sin_addr));
  55. if (!strncmp("127.",inet_ntoa(answer.sin_addr), 4) &&
  56. strcasecmp(localhostname, "localhost")) {
  57. /* We're a loopback IP but we're not called localhost. Uh oh! */
  58. log_fn(LOG_WARNING, "Got a loopback address: /etc/hosts may be wrong");
  59. }
  60. already_learned = 1;
  61. }
  62. memcpy(me,&answer,sizeof(struct sockaddr_in));
  63. return 0;
  64. }
  65. void router_retry_connections(void) {
  66. int i;
  67. routerinfo_t *router;
  68. for (i=0;i<directory->n_routers;i++) {
  69. router = directory->routers[i];
  70. if(!connection_exact_get_by_addr_port(router->addr,router->or_port)) { /* not in the list */
  71. log_fn(LOG_DEBUG,"connecting to OR %s:%u.",router->address,router->or_port);
  72. connection_or_connect(router);
  73. }
  74. }
  75. }
  76. routerinfo_t *router_pick_directory_server(void) {
  77. /* currently, pick the first router with a positive dir_port */
  78. int i;
  79. routerinfo_t *router;
  80. if(!directory)
  81. return NULL;
  82. for(i=0;i<directory->n_routers;i++) {
  83. router = directory->routers[i];
  84. if(router->dir_port > 0)
  85. return router;
  86. }
  87. return NULL;
  88. }
  89. routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) {
  90. int i;
  91. routerinfo_t *router;
  92. assert(directory);
  93. for(i=0;i<directory->n_routers;i++) {
  94. router = directory->routers[i];
  95. if ((router->addr == addr) && (router->or_port == port))
  96. return router;
  97. }
  98. return NULL;
  99. }
  100. routerinfo_t *router_get_by_pk(crypto_pk_env_t *pk)
  101. {
  102. int i;
  103. routerinfo_t *router;
  104. assert(directory);
  105. for(i=0;i<directory->n_routers;i++) {
  106. router = directory->routers[i];
  107. /* XXX Should this really be a separate link key? */
  108. if (0 == crypto_pk_cmp_keys(router->pkey, pk))
  109. return router;
  110. }
  111. return NULL;
  112. }
  113. void router_get_directory(directory_t **pdirectory) {
  114. *pdirectory = directory;
  115. }
  116. /* return 1 if addr and port corresponds to my addr and my or_listenport. else 0,
  117. * or -1 for failure.
  118. */
  119. int router_is_me(uint32_t addr, uint16_t port)
  120. {
  121. /* XXXX Should this check the key too? */
  122. struct sockaddr_in me; /* my router identity */
  123. if(!options.OnionRouter) {
  124. /* we're not an OR. This obviously isn't us. */
  125. return 0;
  126. }
  127. if(learn_my_address(&me) < 0)
  128. return -1;
  129. if(ntohl(me.sin_addr.s_addr) == addr && ntohs(me.sin_port) == port)
  130. return 1;
  131. return 0;
  132. }
  133. /* delete a list of routers from memory */
  134. void routerinfo_free(routerinfo_t *router)
  135. {
  136. struct exit_policy_t *e = NULL, *etmp = NULL;
  137. if (!router)
  138. return;
  139. if (router->address)
  140. free(router->address);
  141. if (router->pkey)
  142. crypto_free_pk_env(router->pkey);
  143. if (router->signing_pkey)
  144. crypto_free_pk_env(router->signing_pkey);
  145. e = router->exit_policy;
  146. while (e) {
  147. etmp = e->next;
  148. if (e->string) free(e->string);
  149. if (e->address) free(e->address);
  150. if (e->port) free(e->port);
  151. free(e);
  152. e = etmp;
  153. }
  154. free(router);
  155. }
  156. void directory_free(directory_t *directory)
  157. {
  158. int i;
  159. for (i = 0; i < directory->n_routers; ++i)
  160. routerinfo_free(directory->routers[i]);
  161. free(directory->routers);
  162. if(directory->software_versions)
  163. free(directory->software_versions);
  164. free(directory);
  165. }
  166. void router_forget_router(uint32_t addr, uint16_t port) {
  167. int i;
  168. routerinfo_t *router;
  169. router = router_get_by_addr_port(addr,port);
  170. if(!router) /* we don't seem to know about him in the first place */
  171. return;
  172. /* now walk down router_array until we get to router */
  173. for(i=0;i<directory->n_routers;i++)
  174. if(directory->routers[i] == router)
  175. break;
  176. assert(i != directory->n_routers); /* if so then router_get_by_addr_port should have returned null */
  177. // free(router); /* don't actually free; we'll free it when we free the whole thing */
  178. // log(LOG_DEBUG,"router_forget_router(): Forgot about router %d:%d",addr,port);
  179. for(; i<directory->n_routers-1;i++)
  180. directory->routers[i] = directory->routers[i+1];
  181. /* XXX bug, we're not decrementing n_routers here? needs more attention. -RD */
  182. }
  183. /* load the router list */
  184. int router_get_list_from_file(char *routerfile)
  185. {
  186. int fd; /* router file */
  187. struct stat statbuf;
  188. char *string;
  189. assert(routerfile);
  190. if (strcspn(routerfile,CONFIG_LEGAL_FILENAME_CHARACTERS) != 0) {
  191. log_fn(LOG_ERR,"Filename %s contains illegal characters.",routerfile);
  192. return -1;
  193. }
  194. if(stat(routerfile, &statbuf) < 0) {
  195. log_fn(LOG_ERR,"Could not stat %s.",routerfile);
  196. return -1;
  197. }
  198. /* open the router list */
  199. fd = open(routerfile,O_RDONLY,0);
  200. if (fd<0) {
  201. log_fn(LOG_ERR,"Could not open %s.",routerfile);
  202. return -1;
  203. }
  204. string = tor_malloc(statbuf.st_size+1);
  205. if(read(fd,string,statbuf.st_size) != statbuf.st_size) {
  206. log_fn(LOG_ERR,"Couldn't read all %ld bytes of file '%s'.",
  207. (long)statbuf.st_size,routerfile);
  208. free(string);
  209. close(fd);
  210. return -1;
  211. }
  212. close(fd);
  213. string[statbuf.st_size] = 0; /* null terminate it */
  214. if(router_get_list_from_string(string) < 0) {
  215. log_fn(LOG_ERR,"The routerfile itself was corrupt.");
  216. free(string);
  217. return -1;
  218. }
  219. free(string);
  220. return 0;
  221. }
  222. typedef enum {
  223. K_ACCEPT,
  224. K_DIRECTORY_SIGNATURE,
  225. K_RECOMMENDED_SOFTWARE,
  226. K_REJECT,
  227. K_ROUTER,
  228. K_SIGNED_DIRECTORY,
  229. K_SIGNING_KEY,
  230. _SIGNATURE,
  231. _PUBLIC_KEY,
  232. _ERR,
  233. _EOF
  234. } directory_keyword;
  235. struct token_table_ent { char *t; int v; };
  236. static struct token_table_ent token_table[] = {
  237. { "accept", K_ACCEPT },
  238. { "directory-signature", K_DIRECTORY_SIGNATURE },
  239. { "reject", K_REJECT },
  240. { "router", K_ROUTER },
  241. { "recommended-software", K_RECOMMENDED_SOFTWARE },
  242. { "signed-directory", K_SIGNED_DIRECTORY },
  243. { "signing-key", K_SIGNING_KEY },
  244. { NULL, -1 }
  245. };
  246. #define MAX_ARGS 8
  247. struct directory_token {
  248. directory_keyword tp;
  249. union {
  250. struct {
  251. char *args[MAX_ARGS+1];
  252. int n_args;
  253. } cmd;
  254. char *signature;
  255. char *error;
  256. crypto_pk_env_t *public_key;
  257. } val;
  258. };
  259. /* Free any malloced resources allocated for a token. Don't call this if
  260. you inherit the reference to those resources.
  261. */
  262. static void
  263. router_release_token(directory_token_t *tok)
  264. {
  265. switch (tok->tp)
  266. {
  267. case _SIGNATURE:
  268. free(tok->val.signature);
  269. break;
  270. case _PUBLIC_KEY:
  271. crypto_free_pk_env(tok->val.public_key);
  272. break;
  273. default:
  274. break;
  275. }
  276. }
  277. static int
  278. _router_get_next_token(char **s, directory_token_t *tok) {
  279. char *next;
  280. crypto_pk_env_t *pkey = NULL;
  281. char *signature = NULL;
  282. int i, done;
  283. tok->tp = _ERR;
  284. tok->val.error = "";
  285. *s = eat_whitespace(*s);
  286. if (!**s) {
  287. tok->tp = _EOF;
  288. return 0;
  289. } else if (**s == '-') {
  290. next = strchr(*s, '\n');
  291. if (! next) { tok->val.error = "No newline at EOF"; return -1; }
  292. ++next;
  293. if (! strncmp(*s, OR_PUBLICKEY_BEGIN_TAG, next-*s)) {
  294. next = strstr(*s, OR_PUBLICKEY_END_TAG);
  295. if (!next) { tok->val.error = "No public key end tag found"; return -1; }
  296. next = strchr(next, '\n'); /* Part of OR_PUBLICKEY_END_TAG; can't fail.*/
  297. ++next;
  298. if (!(pkey = crypto_new_pk_env(CRYPTO_PK_RSA)))
  299. return -1;
  300. if (crypto_pk_read_public_key_from_string(pkey, *s, next-*s)) {
  301. crypto_free_pk_env(pkey);
  302. tok->val.error = "Couldn't parse public key.";
  303. return -1;
  304. }
  305. tok->tp = _PUBLIC_KEY;
  306. tok->val.public_key = pkey;
  307. *s = next;
  308. return 0;
  309. } else if (! strncmp(*s, OR_SIGNATURE_BEGIN_TAG, next-*s)) {
  310. /* Advance past newline; can't fail. */
  311. *s = strchr(*s, '\n');
  312. ++*s;
  313. /* Find end of base64'd data */
  314. next = strstr(*s, OR_SIGNATURE_END_TAG);
  315. if (!next) { tok->val.error = "No signature end tag found"; return -1; }
  316. signature = tor_malloc(256);
  317. i = base64_decode(signature, 256, *s, next-*s);
  318. if (i<0) {
  319. free(signature);
  320. tok->val.error = "Error decoding signature."; return -1;
  321. } else if (i != 128) {
  322. free(signature);
  323. tok->val.error = "Bad length on decoded signature."; return -1;
  324. }
  325. tok->tp = _SIGNATURE;
  326. tok->val.signature = signature;
  327. next = strchr(next, '\n'); /* Part of OR_SIGNATURE_END_TAG; can't fail.*/
  328. *s = next+1;
  329. return 0;
  330. } else {
  331. tok->val.error = "Unrecognized begin line"; return -1;
  332. }
  333. } else {
  334. next = find_whitespace(*s);
  335. if (!next) {
  336. tok->val.error = "Unexpected EOF"; return -1;
  337. }
  338. for (i = 0 ; token_table[i].t ; ++i) {
  339. if (!strncmp(token_table[i].t, *s, next-*s)) {
  340. tok->tp = token_table[i].v;
  341. i = 0;
  342. done = (*next == '\n');
  343. *s = eat_whitespace_no_nl(next);
  344. while (**s != '\n' && i <= MAX_ARGS && !done) {
  345. next = find_whitespace(*s);
  346. if (*next == '\n')
  347. done = 1;
  348. *next = 0;
  349. tok->val.cmd.args[i++] = *s;
  350. *s = eat_whitespace_no_nl(next+1);
  351. };
  352. tok->val.cmd.n_args = i;
  353. if (i > MAX_ARGS) {
  354. tok->tp = _ERR;
  355. tok->val.error = "Too many arguments"; return -1;
  356. }
  357. return 0;
  358. }
  359. }
  360. tok->val.error = "Unrecognized command"; return -1;
  361. }
  362. }
  363. #ifdef DEBUG_ROUTER_TOKENS
  364. static void
  365. router_dump_token(directory_token_t *tok) {
  366. int i;
  367. switch(tok->tp)
  368. {
  369. case _SIGNATURE:
  370. puts("(signature)");
  371. return;
  372. case _PUBLIC_KEY:
  373. puts("(public key)");
  374. return;
  375. case _ERR:
  376. printf("(Error: %s\n)", tok->val.error);
  377. return;
  378. case _EOF:
  379. puts("EOF");
  380. return;
  381. case K_ACCEPT: printf("Accept"); break;
  382. case K_DIRECTORY_SIGNATURE: printf("Directory-Signature"); break;
  383. case K_REJECT: printf("Reject"); break;
  384. case K_RECOMMENDED_SOFTWARE: printf("Server-Software"); break;
  385. case K_ROUTER: printf("Router"); break;
  386. case K_SIGNED_DIRECTORY: printf("Signed-Directory"); break;
  387. case K_SIGNING_KEY: printf("Signing-Key"); break;
  388. default:
  389. printf("?????? %d\n", tok->tp); return;
  390. }
  391. for (i = 0; i < tok->val.cmd.n_args; ++i) {
  392. printf(" \"%s\"", tok->val.cmd.args[i]);
  393. }
  394. printf("\n");
  395. return;
  396. }
  397. static int
  398. router_get_next_token(char **s, directory_token_t *tok) {
  399. int i;
  400. i = _router_get_next_token(s, tok);
  401. router_dump_token(tok);
  402. return i;
  403. }
  404. #else
  405. #define router_get_next_token _router_get_next_token
  406. #endif
  407. /* return the first char of s that is not whitespace and not a comment */
  408. static char *eat_whitespace(char *s) {
  409. assert(s);
  410. while(isspace(*s) || *s == '#') {
  411. while(isspace(*s))
  412. s++;
  413. if(*s == '#') { /* read to a \n or \0 */
  414. while(*s && *s != '\n')
  415. s++;
  416. if(!*s)
  417. return s;
  418. }
  419. }
  420. return s;
  421. }
  422. static char *eat_whitespace_no_nl(char *s) {
  423. while(*s == ' ' || *s == '\t')
  424. ++s;
  425. return s;
  426. }
  427. /* return the first char of s that is whitespace or '#' or '\0 */
  428. static char *find_whitespace(char *s) {
  429. assert(s);
  430. while(*s && !isspace(*s) && *s != '#')
  431. s++;
  432. return s;
  433. }
  434. int router_get_list_from_string(char *s)
  435. {
  436. if (router_get_list_from_string_impl(s, &directory)) {
  437. log(LOG_ERR, "Error parsing router file");
  438. return -1;
  439. }
  440. if (router_resolve_directory(directory)) {
  441. log(LOG_ERR, "Error resolving directory");
  442. return -1;
  443. }
  444. return 0;
  445. }
  446. int router_get_list_from_string_impl(char *s, directory_t **dest) {
  447. directory_token_t tok;
  448. if (router_get_next_token(&s, &tok)) {
  449. log(LOG_ERR, "Error reading routers: %s", tok.val.error);
  450. return -1;
  451. }
  452. return router_get_list_from_string_tok(&s, dest, &tok);
  453. }
  454. static int router_get_dir_hash(char *s, char *digest)
  455. {
  456. char *start, *end;
  457. start = strstr(s, "signed-directory");
  458. if (!start) {
  459. log(LOG_ERR,"router_get_dir_hash(): couldn't find \"signed-directory\"");
  460. return -1;
  461. }
  462. end = strstr(start, "directory-signature");
  463. if (!end) {
  464. log(LOG_ERR,"router_get_dir_hash(): couldn't find \"directory-signature\"");
  465. return -1;
  466. }
  467. end = strchr(end, '\n');
  468. if (!end) {
  469. log(LOG_ERR,"router_get_dir_hash(): couldn't find EOL");
  470. return -1;
  471. }
  472. ++end;
  473. if (crypto_SHA_digest(start, end-start, digest)) {
  474. log(LOG_ERR,"router_get_dir_hash(): couldn't compute digest");
  475. return -1;
  476. }
  477. return 0;
  478. }
  479. /* return 0 if myversion is in start. Else return -1. */
  480. int compare_recommended_versions(char *myversion, char *start) {
  481. int len_myversion = strlen(myversion);
  482. char *comma;
  483. char *end = start + strlen(start);
  484. log_fn(LOG_DEBUG,"checking '%s' in '%s'.", myversion, start);
  485. for(;;) {
  486. comma = strchr(start, ',');
  487. if( ((comma ? comma : end) - start == len_myversion) &&
  488. !strncmp(start, myversion, len_myversion)) /* only do strncmp if the length matches */
  489. return 0; /* success, it's there */
  490. if(!comma)
  491. return -1; /* nope */
  492. start = comma+1;
  493. }
  494. }
  495. int router_get_dir_from_string(char *s, crypto_pk_env_t *pkey)
  496. {
  497. if (router_get_dir_from_string_impl(s, &directory, pkey)) {
  498. log(LOG_ERR, "router_get_dir_from_string: Couldn't parse directory.");
  499. return -1;
  500. }
  501. if (router_resolve_directory(directory)) {
  502. log(LOG_ERR, "Error resolving directory");
  503. return -1;
  504. }
  505. if (compare_recommended_versions(VERSION, directory->software_versions) < 0) {
  506. log(LOG_ERR, "You are running tor version %s, which is no longer supported.\nPlease upgrade to one of %s.", VERSION, RECOMMENDED_SOFTWARE_VERSIONS);
  507. if(options.IgnoreVersion) {
  508. log(LOG_WARNING, "IgnoreVersion is set. If it breaks, we told you so.");
  509. } else {
  510. log(LOG_ERR,"Set IgnoreVersion config variable if you want to survive this error.");
  511. fflush(0);
  512. exit(0);
  513. }
  514. }
  515. return 0;
  516. }
  517. int router_get_dir_from_string_impl(char *s, directory_t **dest,
  518. crypto_pk_env_t *pkey)
  519. {
  520. directory_token_t tok;
  521. char digest[20];
  522. char signed_digest[128];
  523. directory_t *new_dir = NULL;
  524. char *versions;
  525. #define NEXT_TOK() \
  526. do { \
  527. if (router_get_next_token(&s, &tok)) { \
  528. log(LOG_ERR, "Error reading directory: %s", tok.val.error); \
  529. return -1; \
  530. } } while (0)
  531. #define TOK_IS(type,name) \
  532. do { \
  533. if (tok.tp != type) { \
  534. router_release_token(&tok); \
  535. log(LOG_ERR, "Error reading directory: expected %s", name); \
  536. return -1; \
  537. } } while(0)
  538. if (router_get_dir_hash(s, digest)) {
  539. log(LOG_ERR, "Unable to compute digest of directory");
  540. return -1;
  541. }
  542. NEXT_TOK();
  543. TOK_IS(K_SIGNED_DIRECTORY, "signed-directory");
  544. NEXT_TOK();
  545. TOK_IS(K_RECOMMENDED_SOFTWARE, "recommended-software");
  546. if (tok.val.cmd.n_args != 1) {
  547. log(LOG_ERR, "Invalid recommded-software line");
  548. return -1;
  549. }
  550. versions = strdup(tok.val.cmd.args[0]);
  551. NEXT_TOK();
  552. if (router_get_list_from_string_tok(&s, &new_dir, &tok)) {
  553. log(LOG_ERR, "Error reading routers from directory");
  554. return -1;
  555. }
  556. new_dir->software_versions = versions;
  557. TOK_IS(K_DIRECTORY_SIGNATURE, "directory-signature");
  558. NEXT_TOK();
  559. TOK_IS(_SIGNATURE, "signature");
  560. if (pkey) {
  561. if (crypto_pk_public_checksig(pkey, tok.val.signature, 128, signed_digest)
  562. != 20) {
  563. log(LOG_ERR, "Error reading directory: invalid signature.");
  564. free(tok.val.signature);
  565. return -1;
  566. }
  567. if (memcmp(digest, signed_digest, 20)) {
  568. log(LOG_ERR, "Error reading directory: signature does not match.");
  569. free(tok.val.signature);
  570. return -1;
  571. }
  572. }
  573. free(tok.val.signature);
  574. NEXT_TOK();
  575. TOK_IS(_EOF, "end of directory");
  576. if (*dest)
  577. directory_free(*dest);
  578. *dest = new_dir;
  579. return 0;
  580. #undef NEXT_TOK
  581. #undef TOK_IS
  582. }
  583. static int router_get_list_from_string_tok(char **s, directory_t **dest,
  584. directory_token_t *tok)
  585. {
  586. routerinfo_t *router;
  587. routerinfo_t **rarray;
  588. int rarray_len = 0;
  589. assert(s);
  590. rarray = (routerinfo_t **)tor_malloc((sizeof(routerinfo_t *))*MAX_ROUTERS_IN_DIR);
  591. while (tok->tp == K_ROUTER) {
  592. router = router_get_entry_from_string_tok(s, tok);
  593. if (!router) {
  594. log(LOG_ERR, "Error reading router");
  595. return -1;
  596. }
  597. if (rarray_len >= MAX_ROUTERS_IN_DIR) {
  598. log(LOG_ERR, "router_get_list_from_string_tok(): too many routers");
  599. routerinfo_free(router);
  600. continue;
  601. }
  602. rarray[rarray_len++] = router;
  603. }
  604. if (*dest)
  605. directory_free(*dest);
  606. *dest = (directory_t *)tor_malloc(sizeof(directory_t));
  607. (*dest)->routers = rarray;
  608. (*dest)->n_routers = rarray_len;
  609. (*dest)->software_versions = NULL;
  610. return 0;
  611. }
  612. static int
  613. router_resolve(routerinfo_t *router)
  614. {
  615. struct hostent *rent;
  616. rent = (struct hostent *)gethostbyname(router->address);
  617. if (!rent) {
  618. log(LOG_ERR,"router_resolve(): Could not get address for router %s.",router->address);
  619. return -1;
  620. }
  621. assert(rent->h_length == 4);
  622. memcpy(&router->addr, rent->h_addr,rent->h_length);
  623. router->addr = ntohl(router->addr); /* get it back into host order */
  624. return 0;
  625. }
  626. static int
  627. router_resolve_directory(directory_t *dir)
  628. {
  629. int i, max, remove;
  630. if (!dir)
  631. dir = directory;
  632. max = dir->n_routers;
  633. for (i = 0; i < max; ++i) {
  634. remove = 0;
  635. if (router_resolve(dir->routers[i])) {
  636. log(LOG_INFO, "Couldn't resolve router %s; removing",
  637. dir->routers[i]->address);
  638. remove = 1;
  639. routerinfo_free(dir->routers[i]);
  640. } else if (router_is_me(dir->routers[i]->addr, dir->routers[i]->or_port)) {
  641. my_routerinfo = dir->routers[i];
  642. remove = 1;
  643. }
  644. if (remove) {
  645. dir->routers[i] = dir->routers[--max];
  646. --dir->n_routers;
  647. --i;
  648. }
  649. }
  650. return 0;
  651. }
  652. routerinfo_t *router_get_entry_from_string(char **s) {
  653. directory_token_t tok;
  654. routerinfo_t *router;
  655. if (router_get_next_token(s, &tok)) return NULL;
  656. router = router_get_entry_from_string_tok(s, &tok);
  657. if (tok.tp != _EOF) {
  658. router_release_token(&tok);
  659. return NULL;
  660. }
  661. return router;
  662. }
  663. /* reads a single router entry from s.
  664. * updates s so it points to after the router it just read.
  665. * mallocs a new router, returns it if all goes well, else returns NULL.
  666. */
  667. static routerinfo_t *router_get_entry_from_string_tok(char**s, directory_token_t *tok) {
  668. routerinfo_t *router = NULL;
  669. #define NEXT_TOKEN() \
  670. do { if (router_get_next_token(s, tok)) { \
  671. log(LOG_ERR, "Error reading directory: %s", tok->val.error); \
  672. goto err; \
  673. } } while(0)
  674. #define ARGS tok->val.cmd.args
  675. if (tok->tp != K_ROUTER) {
  676. router_release_token(tok);
  677. log(LOG_ERR,"router_get_entry_from_string(): Entry does not start with \"router\"");
  678. return NULL;
  679. }
  680. router = tor_malloc(sizeof(routerinfo_t));
  681. memset(router,0,sizeof(routerinfo_t)); /* zero it out first */
  682. /* C doesn't guarantee that NULL is represented by 0 bytes. You'll
  683. thank me for this someday. */
  684. router->pkey = router->signing_pkey = NULL;
  685. if (tok->val.cmd.n_args != 5) {
  686. log(LOG_ERR,"router_get_entry_from_string(): Wrong # of arguments to \"router\"");
  687. goto err;
  688. }
  689. /* read router.address */
  690. if (!(router->address = strdup(ARGS[0])))
  691. goto err;
  692. router->addr = 0;
  693. /* Read router->or_port */
  694. router->or_port = atoi(ARGS[1]);
  695. if(!router->or_port) {
  696. log(LOG_ERR,"router_get_entry_from_string(): or_port unreadable or 0. Failing.");
  697. goto err;
  698. }
  699. /* Router->ap_port */
  700. router->ap_port = atoi(ARGS[2]);
  701. /* Router->dir_port */
  702. router->dir_port = atoi(ARGS[3]);
  703. /* Router->bandwidth */
  704. router->bandwidth = atoi(ARGS[4]);
  705. if (!router->bandwidth) {
  706. log(LOG_ERR,"router_get_entry_from_string(): bandwidth unreadable or 0. Failing.");
  707. }
  708. log(LOG_DEBUG,"or_port %d, ap_port %d, dir_port %d, bandwidth %d.",
  709. router->or_port, router->ap_port, router->dir_port, router->bandwidth);
  710. NEXT_TOKEN();
  711. if (tok->tp != _PUBLIC_KEY) {
  712. log(LOG_ERR,"router_get_entry_from_string(): Missing public key");
  713. goto err;
  714. } /* Check key length */
  715. router->pkey = tok->val.public_key;
  716. NEXT_TOKEN();
  717. if (tok->tp == K_SIGNING_KEY) {
  718. NEXT_TOKEN();
  719. if (tok->tp != _PUBLIC_KEY) {
  720. log(LOG_ERR,"router_get_entry_from_string(): Missing signing key");
  721. goto err;
  722. }
  723. router->signing_pkey = tok->val.public_key;
  724. NEXT_TOKEN();
  725. }
  726. while (tok->tp == K_ACCEPT || tok->tp == K_REJECT) {
  727. router_add_exit_policy(router, tok);
  728. NEXT_TOKEN();
  729. }
  730. return router;
  731. err:
  732. router_release_token(tok);
  733. if(router->address)
  734. free(router->address);
  735. if(router->pkey)
  736. crypto_free_pk_env(router->pkey);
  737. if(router->signing_pkey)
  738. crypto_free_pk_env(router->signing_pkey);
  739. router_free_exit_policy(router);
  740. free(router);
  741. return NULL;
  742. #undef ARGS
  743. #undef NEXT_TOKEN
  744. }
  745. static void router_free_exit_policy(routerinfo_t *router) {
  746. struct exit_policy_t *tmpe;
  747. while(router->exit_policy) {
  748. tmpe = router->exit_policy;
  749. router->exit_policy = tmpe->next;
  750. free(tmpe->string);
  751. free(tmpe->address);
  752. free(tmpe->port);
  753. free(tmpe);
  754. }
  755. }
  756. #if 0
  757. void test_write_pkey(crypto_pk_env_t *pkey) {
  758. char *string;
  759. int len;
  760. log(LOG_DEBUG,"Trying test write.");
  761. if(crypto_pk_write_public_key_to_string(pkey,&string,&len)<0) {
  762. log(LOG_DEBUG,"router_get_entry_from_string(): write pkey to string failed\n");
  763. return;
  764. }
  765. log(LOG_DEBUG,"I did it: len %d, string '%s'.",len,string);
  766. free(string);
  767. }
  768. #endif
  769. static int router_add_exit_policy(routerinfo_t *router,
  770. directory_token_t *tok) {
  771. struct exit_policy_t *tmpe, *newe;
  772. char *arg, *colon;
  773. if (tok->val.cmd.n_args != 1)
  774. return -1;
  775. arg = tok->val.cmd.args[0];
  776. newe = tor_malloc(sizeof(struct exit_policy_t));
  777. memset(newe,0,sizeof(struct exit_policy_t));
  778. newe->string = tor_malloc(8+strlen(arg));
  779. if (tok->tp == K_REJECT) {
  780. strcpy(newe->string, "reject ");
  781. newe->policy_type = EXIT_POLICY_REJECT;
  782. } else {
  783. assert(tok->tp == K_ACCEPT);
  784. strcpy(newe->string, "accept ");
  785. newe->policy_type = EXIT_POLICY_ACCEPT;
  786. }
  787. strcat(newe->string, arg);
  788. colon = strchr(arg,':');
  789. if(!colon)
  790. goto policy_read_failed;
  791. *colon = 0;
  792. newe->address = strdup(arg);
  793. newe->port = strdup(colon+1);
  794. log(LOG_DEBUG,"router_add_exit_policy(): %s %s:%s",
  795. newe->policy_type == EXIT_POLICY_REJECT ? "reject" : "accept",
  796. newe->address, newe->port);
  797. /* now link newe onto the end of exit_policy */
  798. if(!router->exit_policy) {
  799. router->exit_policy = newe;
  800. return 0;
  801. }
  802. for(tmpe=router->exit_policy; tmpe->next; tmpe=tmpe->next) ;
  803. tmpe->next = newe;
  804. return 0;
  805. policy_read_failed:
  806. assert(newe->string);
  807. log(LOG_INFO,"router_add_exit_policy(): Couldn't parse line '%s'. Dropping", newe->string);
  808. if(newe->string)
  809. free(newe->string);
  810. if(newe->address)
  811. free(newe->address);
  812. if(newe->port)
  813. free(newe->port);
  814. free(newe);
  815. return -1;
  816. }
  817. /* Return 0 if my exit policy says to allow connection to conn.
  818. * Else return -1.
  819. */
  820. int router_compare_to_exit_policy(connection_t *conn) {
  821. struct exit_policy_t *tmpe;
  822. if(!my_routerinfo) {
  823. log(LOG_WARNING, "router_compare_to_exit_policy(): my_routerinfo undefined! Rejected.");
  824. return -1;
  825. }
  826. for(tmpe=my_routerinfo->exit_policy; tmpe; tmpe=tmpe->next) {
  827. assert(tmpe->address);
  828. assert(tmpe->port);
  829. /* Totally ignore the address field of the exit policy, for now. */
  830. if(!strcmp(tmpe->port,"*") || atoi(tmpe->port) == conn->port) {
  831. log(LOG_INFO,"router_compare_to_exit_policy(): Port '%s' matches '%d'. %s.",
  832. tmpe->port, conn->port,
  833. tmpe->policy_type == EXIT_POLICY_ACCEPT ? "Accepting" : "Rejecting");
  834. if(tmpe->policy_type == EXIT_POLICY_ACCEPT)
  835. return 0;
  836. else
  837. return -1;
  838. }
  839. }
  840. return 0; /* accept all by default. */
  841. }
  842. /*
  843. Local Variables:
  844. mode:c
  845. indent-tabs-mode:nil
  846. c-basic-offset:2
  847. End:
  848. */