routers.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #define OR_PUBLICKEY_END_TAG "-----END RSA PUBLIC KEY-----\n"
  5. #include "or.h"
  6. /****************************************************************************/
  7. /* router array */
  8. static routerinfo_t **router_array = NULL;
  9. static int rarray_len = 0;
  10. extern or_options_t options; /* command-line and config-file options */
  11. extern routerinfo_t *my_routerinfo; /* from main.c */
  12. /****************************************************************************/
  13. /* static function prototypes */
  14. static void routerlist_free(routerinfo_t *list);
  15. static routerinfo_t **make_rarray(routerinfo_t* list, int *len);
  16. static char *eat_whitespace(char *s);
  17. static char *find_whitespace(char *s);
  18. static routerinfo_t *router_get_entry_from_string(char **s);
  19. static void router_add_exit_policy(routerinfo_t *router, char *string);
  20. static void router_free_exit_policy(routerinfo_t *router);
  21. /****************************************************************************/
  22. int learn_my_address(struct sockaddr_in *me) {
  23. /* local host information */
  24. char localhostname[512];
  25. struct hostent *localhost;
  26. /* obtain local host information */
  27. if(gethostname(localhostname,512) < 0) {
  28. log(LOG_ERR,"Error obtaining local hostname.");
  29. return -1;
  30. }
  31. log(LOG_DEBUG,"learn_my_address(): localhostname is '%s'.",localhostname);
  32. localhost = gethostbyname(localhostname);
  33. if (!localhost) {
  34. log(LOG_ERR,"Error obtaining local host info.");
  35. return -1;
  36. }
  37. memset(me,0,sizeof(struct sockaddr_in));
  38. me->sin_family = AF_INET;
  39. memcpy((void *)&me->sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
  40. me->sin_port = htons(options.ORPort);
  41. log(LOG_DEBUG,"learn_my_address(): chose address as '%s'.",inet_ntoa(me->sin_addr));
  42. return 0;
  43. }
  44. void router_retry_connections(void) {
  45. int i;
  46. routerinfo_t *router;
  47. for (i=0;i<rarray_len;i++) {
  48. router = router_array[i];
  49. if(!connection_exact_get_by_addr_port(router->addr,router->or_port)) { /* not in the list */
  50. log(LOG_DEBUG,"retry_all_connections(): connecting to OR %s:%u.",router->address,router->or_port);
  51. connection_or_connect_as_or(router);
  52. }
  53. }
  54. }
  55. routerinfo_t *router_pick_directory_server(void) {
  56. /* currently, pick the first router with a positive dir_port */
  57. int i;
  58. routerinfo_t *router;
  59. if(!router_array)
  60. return NULL;
  61. for(i=0;i<rarray_len;i++) {
  62. router = router_array[i];
  63. if(router->dir_port > 0)
  64. return router;
  65. }
  66. return NULL;
  67. }
  68. routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) {
  69. int i;
  70. routerinfo_t *router;
  71. assert(router_array);
  72. for(i=0;i<rarray_len;i++) {
  73. router = router_array[i];
  74. if ((router->addr == addr) && (router->or_port == port))
  75. return router;
  76. }
  77. return NULL;
  78. }
  79. routerinfo_t *router_get_first_in_route(unsigned int *route, int routelen) {
  80. return router_array[route[routelen-1]];
  81. }
  82. /* a wrapper around new_route. put all these in routers.c perhaps? */
  83. unsigned int *router_new_route(int *routelen) {
  84. return new_route(options.CoinWeight, router_array, rarray_len, routelen);
  85. }
  86. /* a wrapper around create_onion */
  87. unsigned char *router_create_onion(unsigned int *route, int routelen, int *len, crypt_path_t **cpath) {
  88. return create_onion(router_array,rarray_len,route,routelen,len,cpath);
  89. }
  90. /* return 1 if addr and port corresponds to my addr and my or_listenport. else 0,
  91. * or -1 for failure.
  92. */
  93. int router_is_me(uint32_t addr, uint16_t port)
  94. {
  95. struct sockaddr_in me; /* my router identity */
  96. if(!options.ORPort) {
  97. /* we're not an OR. This obviously isn't us. */
  98. return 0;
  99. }
  100. if(learn_my_address(&me) < 0)
  101. return -1;
  102. if(ntohl(me.sin_addr.s_addr) == addr && ntohs(me.sin_port) == port)
  103. return 1;
  104. return 0;
  105. #if 0
  106. /* local host information */
  107. char localhostname[512];
  108. struct hostent *localhost;
  109. struct in_addr *a;
  110. char *tmp1;
  111. char *addr = NULL;
  112. int i = 0;
  113. /* obtain local host information */
  114. if (gethostname(localhostname,512) < 0) {
  115. log(LOG_ERR,"router_is_me(): Error obtaining local hostname.");
  116. return -1;
  117. }
  118. localhost = gethostbyname(localhostname);
  119. if (!localhost) {
  120. log(LOG_ERR,"router_is_me(): Error obtaining local host info.");
  121. return -1;
  122. }
  123. /* check host addresses for a match with or_address above */
  124. addr = localhost->h_addr_list[i++]; /* set to the first local address */
  125. while(addr)
  126. {
  127. a = (struct in_addr *)addr;
  128. tmp1 = strdup(inet_ntoa(*a)); /* can't call inet_ntoa twice in the same
  129. printf, since it overwrites its static
  130. memory each time */
  131. log(LOG_DEBUG,"router_is_me(): Comparing '%s' to '%s'.",tmp1,
  132. inet_ntoa( *((struct in_addr *)&or_address) ) );
  133. free(tmp1);
  134. if (!memcmp((void *)&or_address, (void *)addr, sizeof(uint32_t))) { /* addresses match */
  135. log(LOG_DEBUG,"router_is_me(): Addresses match. Comparing ports.");
  136. if (or_listenport == my_or_listenport) { /* ports also match */
  137. log(LOG_DEBUG,"router_is_me(): Ports match too.");
  138. return 1;
  139. }
  140. }
  141. addr = localhost->h_addr_list[i++];
  142. }
  143. return 0;
  144. #endif
  145. }
  146. /* delete a list of routers from memory */
  147. static void routerlist_free(routerinfo_t *list)
  148. {
  149. routerinfo_t *tmp = NULL;
  150. if (!list)
  151. return;
  152. do
  153. {
  154. tmp=list->next;
  155. free((void *)list->address);
  156. crypto_free_pk_env(list->pkey);
  157. free((void *)list);
  158. list = tmp;
  159. }
  160. while (list != NULL);
  161. return;
  162. }
  163. void rarray_free(routerinfo_t **list) {
  164. if(!list)
  165. return;
  166. routerlist_free(*list);
  167. free(list);
  168. }
  169. void router_forget_router(uint32_t addr, uint16_t port) {
  170. int i;
  171. routerinfo_t *router;
  172. router = router_get_by_addr_port(addr,port);
  173. if(!router) /* we don't seem to know about him in the first place */
  174. return;
  175. /* now walk down router_array until we get to router */
  176. for(i=0;i<rarray_len;i++)
  177. if(router_array[i] == router)
  178. break;
  179. assert(i != rarray_len); /* if so then router_get_by_addr_port should have returned null */
  180. // free(router); /* don't actually free; we'll free it when we free the whole thing */
  181. // log(LOG_DEBUG,"router_forget_router(): Forgot about router %d:%d",addr,port);
  182. for(; i<rarray_len-1;i++)
  183. router_array[i] = router_array[i+1];
  184. }
  185. /* create a NULL-terminated array of pointers pointing to elements of a router list */
  186. /* this is done in two passes through the list - inefficient but irrelevant as this is
  187. * only done once when op/or start up */
  188. static routerinfo_t **make_rarray(routerinfo_t* list, int *len)
  189. {
  190. routerinfo_t *tmp=NULL;
  191. int listlen = 0;
  192. routerinfo_t **array=NULL;
  193. routerinfo_t **p=NULL;
  194. if ((!list) || (!len))
  195. return NULL;
  196. /* get the length of the list */
  197. tmp = list;
  198. do
  199. {
  200. listlen++;
  201. tmp = tmp->next;
  202. }
  203. while (tmp != NULL);
  204. array = malloc((listlen+1)*sizeof(routerinfo_t *));
  205. if (!array)
  206. {
  207. log(LOG_ERR,"Error allocating memory.");
  208. return NULL;
  209. }
  210. tmp=list;
  211. p = array;
  212. do
  213. {
  214. *p = tmp;
  215. p++;
  216. tmp = tmp->next;
  217. }
  218. while(tmp != NULL);
  219. *p=NULL;
  220. *len = listlen;
  221. return array;
  222. }
  223. /* load the router list */
  224. int router_get_list_from_file(char *routerfile)
  225. {
  226. int fd; /* router file */
  227. struct stat statbuf;
  228. char *string;
  229. assert(routerfile);
  230. if (strcspn(routerfile,CONFIG_LEGAL_FILENAME_CHARACTERS) != 0) {
  231. log(LOG_ERR,"router_get_list_from_file(): Filename %s contains illegal characters.",routerfile);
  232. return -1;
  233. }
  234. if(stat(routerfile, &statbuf) < 0) {
  235. log(LOG_ERR,"router_get_list_from_file(): Could not stat %s.",routerfile);
  236. return -1;
  237. }
  238. /* open the router list */
  239. fd = open(routerfile,O_RDONLY,0);
  240. if (fd<0) {
  241. log(LOG_ERR,"router_get_list_from_file(): Could not open %s.",routerfile);
  242. return -1;
  243. }
  244. string = malloc(statbuf.st_size+1);
  245. if(!string) {
  246. log(LOG_ERR,"router_get_list_from_file(): Out of memory.");
  247. return -1;
  248. }
  249. if(read(fd,string,statbuf.st_size) != statbuf.st_size) {
  250. log(LOG_ERR,"router_get_list_from_file(): Couldn't read all %d bytes of file '%s'.",statbuf.st_size,routerfile);
  251. free(string);
  252. close(fd);
  253. return -1;
  254. }
  255. close(fd);
  256. string[statbuf.st_size] = 0; /* null terminate it */
  257. if(router_get_list_from_string(string) < 0) {
  258. log(LOG_ERR,"router_get_list_from_file(): The routerfile itself was corrupt.");
  259. free(string);
  260. return -1;
  261. }
  262. free(string);
  263. return 0;
  264. }
  265. int router_get_list_from_string(char *s) {
  266. routerinfo_t *routerlist=NULL;
  267. routerinfo_t *router;
  268. routerinfo_t **new_router_array;
  269. int new_rarray_len;
  270. assert(s);
  271. while(*s) { /* while not at the end of the string */
  272. router = router_get_entry_from_string(&s);
  273. if(router == NULL) {
  274. routerlist_free(routerlist);
  275. return -1;
  276. }
  277. switch(router_is_me(router->addr, router->or_port)) {
  278. case 0: /* it's not me */
  279. router->next = routerlist;
  280. routerlist = router;
  281. break;
  282. case 1: /* it is me */
  283. if(!my_routerinfo) /* save it, so we can use it for directories */
  284. my_routerinfo = router;
  285. else
  286. routerlist_free(router);
  287. break;
  288. default:
  289. log(LOG_ERR,"router_get_list_from_string(): router_is_me returned error.");
  290. routerlist_free(routerlist);
  291. return -1;
  292. }
  293. s = eat_whitespace(s);
  294. }
  295. new_router_array = make_rarray(routerlist, &new_rarray_len);
  296. if(new_router_array) { /* success! replace the old one */
  297. rarray_free(router_array); /* free the old one first */
  298. router_array = new_router_array;
  299. rarray_len = new_rarray_len;
  300. return 0;
  301. }
  302. return -1;
  303. }
  304. /* return the first char of s that is not whitespace and not a comment */
  305. static char *eat_whitespace(char *s) {
  306. assert(s);
  307. while(isspace(*s) || *s == '#') {
  308. while(isspace(*s))
  309. s++;
  310. if(*s == '#') { /* read to a \n or \0 */
  311. while(*s && *s != '\n')
  312. s++;
  313. if(!*s)
  314. return s;
  315. }
  316. }
  317. return s;
  318. }
  319. /* return the first char of s that is whitespace or '#' or '\0 */
  320. static char *find_whitespace(char *s) {
  321. assert(s);
  322. while(*s && !isspace(*s) && *s != '#')
  323. s++;
  324. return s;
  325. }
  326. /* reads a single router entry from s.
  327. * updates s so it points to after the router it just read.
  328. * mallocs a new router, returns it if all goes well, else returns NULL.
  329. */
  330. static routerinfo_t *router_get_entry_from_string(char **s) {
  331. routerinfo_t *router;
  332. char *next;
  333. struct hostent *rent;
  334. router = malloc(sizeof(routerinfo_t));
  335. if (!router) {
  336. log(LOG_ERR,"router_get_entry_from_string(): Could not allocate memory.");
  337. return NULL;
  338. }
  339. memset(router,0,sizeof(routerinfo_t)); /* zero it out first */
  340. /* Bug: if find_whitespace returns a '#', we'll squish it. */
  341. #define NEXT_TOKEN(s, next) \
  342. *s = eat_whitespace(*s); \
  343. next = find_whitespace(*s); \
  344. if(!*next) { \
  345. goto router_read_failed; \
  346. } \
  347. *next = 0;
  348. /* read router->address */
  349. NEXT_TOKEN(s, next);
  350. router->address = strdup(*s);
  351. *s = next+1;
  352. rent = (struct hostent *)gethostbyname(router->address);
  353. if (!rent) {
  354. log(LOG_ERR,"router_get_entry_from_string(): Could not get address for router %s.",router->address);
  355. goto router_read_failed;
  356. }
  357. assert(rent->h_length == 4);
  358. memcpy(&router->addr, rent->h_addr,rent->h_length);
  359. router->addr = ntohl(router->addr); /* get it back into host order */
  360. /* read router->or_port */
  361. NEXT_TOKEN(s, next);
  362. router->or_port = atoi(*s);
  363. if(!router->or_port) {
  364. log(LOG_ERR,"router_get_entry_from_string(): or_port '%s' unreadable or 0. Failing.",*s);
  365. goto router_read_failed;
  366. }
  367. *s = next+1;
  368. /* read router->op_port */
  369. NEXT_TOKEN(s, next);
  370. router->op_port = atoi(*s);
  371. *s = next+1;
  372. /* read router->ap_port */
  373. NEXT_TOKEN(s, next);
  374. router->ap_port = atoi(*s);
  375. *s = next+1;
  376. /* read router->dir_port */
  377. NEXT_TOKEN(s, next);
  378. router->dir_port = atoi(*s);
  379. *s = next+1;
  380. /* read router->bandwidth */
  381. NEXT_TOKEN(s, next);
  382. router->bandwidth = atoi(*s);
  383. if(!router->bandwidth) {
  384. log(LOG_ERR,"router_get_entry_from_string(): bandwidth '%s' unreadable or 0. Failing.",*s);
  385. goto router_read_failed;
  386. }
  387. *s = next+1;
  388. log(LOG_DEBUG,"or_port %d, op_port %d, ap_port %d, dir_port %d, bandwidth %d.",
  389. router->or_port, router->op_port, router->ap_port, router->dir_port, router->bandwidth);
  390. *s = eat_whitespace(*s);
  391. next = strstr(*s,OR_PUBLICKEY_END_TAG);
  392. router->pkey = crypto_new_pk_env(CRYPTO_PK_RSA);
  393. if(!next || !router->pkey) {
  394. log(LOG_ERR,"router_get_entry_from_string(): Couldn't find pk in string");
  395. goto router_read_failed;
  396. }
  397. /* now advance *s so it's at the end of this router entry */
  398. next = strchr(next, '\n');
  399. assert(next); /* can't fail, we just checked it was here */
  400. *next = 0;
  401. // log(LOG_DEBUG,"Key about to be read is: '%s'",*s);
  402. if((crypto_pk_read_public_key_from_string(router->pkey, *s, strlen(*s))<0)) {
  403. log(LOG_ERR,"router_get_entry_from_string(): Couldn't read pk from string");
  404. goto router_read_failed;
  405. }
  406. log(LOG_DEBUG,"router_get_entry_from_string(): Public key size = %u.", crypto_pk_keysize(router->pkey));
  407. if (crypto_pk_keysize(router->pkey) != 128) { /* keys MUST be 1024 bits in size */
  408. log(LOG_ERR,"Key for router %s:%u is not 1024 bits. All keys must be exactly 1024 bits long.",
  409. router->address,router->or_port);
  410. goto router_read_failed;
  411. }
  412. // test_write_pkey(router->pkey);
  413. *s = next+1;
  414. while(**s != '\n') {
  415. /* pull in a line of exit policy */
  416. next = strchr(*s, '\n');
  417. if(!next)
  418. goto router_read_failed;
  419. *next = 0;
  420. router_add_exit_policy(router, *s);
  421. *s = next+1;
  422. }
  423. return router;
  424. router_read_failed:
  425. if(router->address)
  426. free(router->address);
  427. if(router->pkey)
  428. crypto_free_pk_env(router->pkey);
  429. router_free_exit_policy(router);
  430. free(router);
  431. return NULL;
  432. }
  433. static void router_free_exit_policy(routerinfo_t *router) {
  434. struct exit_policy_t *tmpe;
  435. while(router->exit_policy) {
  436. tmpe = router->exit_policy;
  437. router->exit_policy = tmpe->next;
  438. free(tmpe->string);
  439. free(tmpe->address);
  440. free(tmpe->port);
  441. free(tmpe);
  442. }
  443. }
  444. #if 0
  445. void test_write_pkey(crypto_pk_env_t *pkey) {
  446. char *string;
  447. int len;
  448. log(LOG_DEBUG,"Trying test write.");
  449. if(crypto_pk_write_public_key_to_string(pkey,&string,&len)<0) {
  450. log(LOG_DEBUG,"router_get_entry_from_string(): write pkey to string failed\n");
  451. return;
  452. }
  453. log(LOG_DEBUG,"I did it: len %d, string '%s'.",len,string);
  454. free(string);
  455. }
  456. #endif
  457. static void router_add_exit_policy(routerinfo_t *router, char *string) {
  458. struct exit_policy_t *tmpe, *newe;
  459. char *n;
  460. string = eat_whitespace(string);
  461. if(!*string) /* it was all whitespace or comment */
  462. return;
  463. newe = malloc(sizeof(struct exit_policy_t));
  464. memset(newe,0,sizeof(struct exit_policy_t));
  465. newe->string = strdup(string);
  466. n = find_whitespace(string);
  467. *n = 0;
  468. if(!strcasecmp(string,"reject")) {
  469. newe->policy_type = EXIT_POLICY_REJECT;
  470. } else if(!strcasecmp(string,"accept")) {
  471. newe->policy_type = EXIT_POLICY_ACCEPT;
  472. } else {
  473. goto policy_read_failed;
  474. }
  475. string = eat_whitespace(n+1);
  476. if(!*string) {
  477. goto policy_read_failed;
  478. }
  479. n = strchr(string,':');
  480. if(!n)
  481. goto policy_read_failed;
  482. *n = 0;
  483. newe->address = strdup(string);
  484. string = n+1;
  485. n = find_whitespace(string);
  486. *n = 0;
  487. newe->port = strdup(string);
  488. log(LOG_DEBUG,"router_add_exit_policy(): type %d, address '%s', port '%s'.",
  489. newe->policy_type, newe->address, newe->port);
  490. /* now link newe onto the end of exit_policy */
  491. if(!router->exit_policy) {
  492. router->exit_policy = newe;
  493. return;
  494. }
  495. for(tmpe=router->exit_policy; tmpe->next; tmpe=tmpe->next) ;
  496. tmpe->next = newe;
  497. return;
  498. policy_read_failed:
  499. assert(newe->string);
  500. log(LOG_INFO,"router_add_exit_policy(): Couldn't parse line '%s'. Dropping", newe->string);
  501. if(newe->string)
  502. free(newe->string);
  503. if(newe->address)
  504. free(newe->address);
  505. if(newe->port)
  506. free(newe->port);
  507. free(newe);
  508. return;
  509. }
  510. /* Return 0 if my exit policy says to allow connection to conn.
  511. * Else return -1.
  512. */
  513. int router_compare_to_exit_policy(connection_t *conn) {
  514. struct exit_policy_t *tmpe;
  515. if(!my_routerinfo) {
  516. log(LOG_WARNING, "router_compare_to_exit_policy(): my_routerinfo undefined! Rejected.");
  517. return -1;
  518. }
  519. for(tmpe=my_routerinfo->exit_policy; tmpe; tmpe=tmpe->next) {
  520. assert(tmpe->address);
  521. assert(tmpe->port);
  522. /* Totally ignore the address field of the exit policy, for now. */
  523. if(!strcmp(tmpe->port,"*") || atoi(tmpe->port) == conn->port) {
  524. log(LOG_INFO,"router_compare_to_exit_policy(): Port '%s' matches '%d'. %s.",
  525. tmpe->port, conn->port,
  526. tmpe->policy_type == EXIT_POLICY_ACCEPT ? "Accepting" : "Rejecting");
  527. if(tmpe->policy_type == EXIT_POLICY_ACCEPT)
  528. return 0;
  529. else
  530. return -1;
  531. }
  532. }
  533. return 0; /* accept all by default. */
  534. }
  535. /*
  536. Local Variables:
  537. mode:c
  538. indent-tabs-mode:nil
  539. c-basic-offset:2
  540. End:
  541. */