routers.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /**
  2. * routers.c
  3. * Routines for loading the list of routers and their public RSA keys.
  4. *
  5. * Matej Pfajfar <mp292@cam.ac.uk>
  6. */
  7. /*
  8. * Changes :
  9. * $Log$
  10. * Revision 1.1 2002/06/26 22:45:50 arma
  11. * Initial revision
  12. *
  13. * Revision 1.16 2002/04/02 14:28:01 badbytes
  14. * Final finishes.
  15. *
  16. * Revision 1.15 2002/03/25 10:48:48 badbytes
  17. * Added explicit dependency on <netinet/in.h>.
  18. *
  19. * Revision 1.14 2002/01/27 19:24:33 mp292
  20. * Fixed a bug in parameter checking.
  21. *
  22. * Revision 1.13 2002/01/26 22:19:15 mp292
  23. * Reviewed according to Secure-Programs-HOWTO.
  24. *
  25. * Revision 1.12 2002/01/18 20:42:25 mp292
  26. * Slight modification to the way keys are read from the route file.
  27. *
  28. * Revision 1.11 2002/01/14 13:05:39 badbytes
  29. * System testing in progress.
  30. *
  31. * Revision 1.10 2002/01/11 15:47:25 badbytes
  32. * *** empty log message ***
  33. *
  34. * Revision 1.9 2001/12/18 15:51:58 badbytes
  35. * Connection with onion router established. Will continue testing tomorrow.
  36. *
  37. * Revision 1.8 2001/12/17 13:36:15 badbytes
  38. * Writing handle_connection()
  39. *
  40. * Revision 1.7 2001/12/17 08:42:45 badbytes
  41. * getrouters() now returns an array of routers and also writes the length of the array to an int*.
  42. *
  43. * Revision 1.6 2001/12/14 14:08:50 badbytes
  44. * getrouters() now returns an array of pointers rather than a linked list
  45. *
  46. * Revision 1.5 2001/12/14 14:05:56 badbytes
  47. * Added routent_t** make_rarray(routent_t* list);
  48. *
  49. * Revision 1.4 2001/12/14 13:25:17 badbytes
  50. * Moved back from common/
  51. *
  52. * Revision 1.2 2001/12/14 11:24:57 badbytes
  53. * Tested.
  54. *
  55. * Revision 1.1 2001/12/13 15:15:11 badbytes
  56. * Started coding the onion proxy.
  57. *
  58. */
  59. #include <openssl/pem.h>
  60. #include <openssl/err.h>
  61. #include <netdb.h>
  62. #include <string.h>
  63. #include <netinet/in.h>
  64. #include "routers.h"
  65. #include "../common/log.h"
  66. #include "../common/utils.h"
  67. #include "../common/config.h"
  68. /* delete a list of routers from memory */
  69. void delete_routerlist(routent_t *list)
  70. {
  71. routent_t *tmp = NULL;
  72. if (!list)
  73. return;
  74. do
  75. {
  76. tmp=list->next;
  77. free(list->address);
  78. RSA_free(list->pkey);
  79. free(list);
  80. list = tmp;
  81. }
  82. while (list != NULL);
  83. return;
  84. }
  85. /* create an NULL-terminated array of pointers pointing to elements of a router list */
  86. /* this is done in two passes through the list - inefficient but irrelevant as this is
  87. * only done once when op/or start up */
  88. routent_t **make_rarray(routent_t* list, size_t *len)
  89. {
  90. routent_t *tmp=NULL;
  91. int listlen = 0;
  92. routent_t **array=NULL;
  93. routent_t **p=NULL;
  94. if ((!list) || (!len))
  95. return NULL;
  96. /* get the length of the list */
  97. tmp = list;
  98. do
  99. {
  100. listlen++;
  101. tmp = tmp->next;
  102. }
  103. while (tmp != NULL);
  104. array = malloc((listlen+1)*sizeof(routent_t *));
  105. if (!array)
  106. {
  107. log(LOG_ERR,"Error allocating memory.");
  108. return NULL;
  109. }
  110. tmp=list;
  111. p = array;
  112. do
  113. {
  114. *p = tmp;
  115. p++;
  116. tmp = tmp->next;
  117. }
  118. while(tmp != NULL);
  119. *p=NULL;
  120. *len = listlen;
  121. return array;
  122. }
  123. /* load the router list */
  124. routent_t **getrouters(char *routerfile, size_t *lenp)
  125. {
  126. int retval = 0;
  127. char *retp = NULL;
  128. routent_t *router=NULL, *routerlist=NULL, *lastrouter=NULL;
  129. FILE *rf; /* router file */
  130. fpos_t fpos;
  131. char line[512];
  132. char *token;
  133. char *errtest; /* detecting errors in strtoul() calls */
  134. struct hostent *rent;
  135. if ((!routerfile) || (!lenp)) /* invalid parameters */
  136. return NULL;
  137. if (strspn(routerfile,CONFIG_LEGAL_FILENAME_CHARACTERS) != strlen(routerfile)) /* invalid filename */
  138. {
  139. log(LOG_ERR,"Could not open %s because it contains illegal characters.",routerfile);
  140. return NULL;
  141. }
  142. /* open the router list */
  143. rf = fopen(routerfile,"r");
  144. if (!rf)
  145. {
  146. log(LOG_ERR,"Could not open %s.",routerfile);
  147. return NULL;
  148. }
  149. retp= fgets(line,512,rf);
  150. while (retp)
  151. {
  152. log(LOG_DEBUG,"getrouters() : Line :%s",line);
  153. token = (char *)strtok(line,OP_ROUTERLIST_SEPCHARS);
  154. if (token)
  155. {
  156. log(LOG_DEBUG,"getrouters() : Token : %s",token);
  157. if (token[0] != '#') /* ignore comment lines */
  158. {
  159. router = malloc(sizeof(routent_t));
  160. if (!router)
  161. {
  162. log(LOG_ERR,"Could not allocate memory.");
  163. fclose(rf);
  164. delete_routerlist(routerlist);
  165. return NULL;
  166. }
  167. /* read the address */
  168. router->address = malloc(strlen(token)+1);
  169. if (!router->address)
  170. {
  171. log(LOG_ERR,"Could not allocate memory.");
  172. fclose(rf);
  173. free(router);
  174. delete_routerlist(routerlist);
  175. return NULL;
  176. }
  177. strcpy(router->address,token);
  178. rent = (struct hostent *)gethostbyname(router->address);
  179. if (!rent)
  180. {
  181. log(LOG_ERR,"Could not get address for router %s.",router->address);
  182. fclose(rf);
  183. free(router->address);
  184. free(router);
  185. delete_routerlist(routerlist);
  186. return NULL;
  187. }
  188. memcpy(&router->addr, rent->h_addr,rent->h_length);
  189. /* read the network port */
  190. token = (char *)strtok(NULL,OP_ROUTERLIST_SEPCHARS);
  191. if (token) /* network port */
  192. {
  193. log(LOG_DEBUG,"getrouters() : Token :%s",token);
  194. router->port = (uint16_t)strtoul(token,&errtest,0);
  195. if ((*token != '\0') && (*errtest == '\0')) /* network port conversion was successful */
  196. {
  197. router->port = htons(router->port);
  198. /* read the entry port */
  199. token = (char *)strtok(NULL,OP_ROUTERLIST_SEPCHARS);
  200. if (token) /* entry port */
  201. {
  202. log(LOG_DEBUG,"getrouters() : Token :%s",token);
  203. router->entry_port = (uint16_t)strtoul(token,&errtest,0);
  204. if ((*token != '\0') && (*errtest == '\0')) /* entry port number conversion was successful */
  205. {
  206. router->entry_port = htons(router->entry_port);
  207. /* check that there is a public key entry for that router */
  208. retval = fgetpos(rf, &fpos); /* save the current file position
  209. * we wil return to it later if we find a public key */
  210. if (retval == -1)
  211. {
  212. log(LOG_ERR,"Could not save position in %s.",routerfile);
  213. free(router->address);
  214. free(router);
  215. fclose(rf);
  216. delete_routerlist(routerlist);
  217. return NULL;
  218. }
  219. do /* read through to the next non-empty line */
  220. {
  221. retp=fgets(line,512,rf);
  222. if (!retp)
  223. {
  224. log(LOG_ERR,"Could not find a public key entry for router %s:%u.",router->address,router->port);
  225. free(router->address);
  226. free(router);
  227. fclose(rf);
  228. delete_routerlist(routerlist);
  229. return NULL;
  230. }
  231. log(LOG_DEBUG,"getrouters() : Line:%s",line);
  232. if ((*line != '#') && (strspn(line,OP_ROUTERLIST_SEPCHARS) != strlen(line) ))
  233. {
  234. break;
  235. }
  236. } while (1);
  237. if (!strcmp(line,OP_PUBLICKEY_BEGIN_TAG)) /* we've got the public key */
  238. {
  239. retval = fsetpos(rf,&fpos); /* get us back to where we were otherwise crypto lib won't find the key */
  240. if (retval == -1)
  241. {
  242. log(LOG_ERR,"Could not set position in %s.",routerfile);
  243. free(router->address);
  244. free(router);
  245. fclose(rf);
  246. delete_routerlist(routerlist);
  247. return NULL;
  248. }
  249. }
  250. else /* we found something else; this isn't right */
  251. {
  252. log(LOG_ERR,"Could not find a public key entry for router %s:%u.",router->address,router->port);
  253. free(router->address);
  254. free(router);
  255. fclose(rf);
  256. delete_routerlist(routerlist);
  257. return NULL;
  258. }
  259. log(LOG_DEBUG,"getrouters() : Reading the key ...");
  260. /* read the public key into router->pkey */
  261. router->pkey=NULL;
  262. router->pkey = PEM_read_RSAPublicKey(rf,NULL,NULL,NULL);
  263. if (!router->pkey) /* something went wrong */
  264. {
  265. log(LOG_ERR,"Could not read public key for router %s:%u.",router->address,router->port);
  266. free(router->address);
  267. free(router);
  268. fclose(rf);
  269. delete_routerlist(routerlist);
  270. return NULL;
  271. }
  272. else /* read the key */
  273. {
  274. log(LOG_DEBUG,"getrouters() : Public key size = %u.", RSA_size(router->pkey));
  275. if (RSA_size(router->pkey) != 128) /* keys MUST be 1024 bits in size */
  276. {
  277. log(LOG_ERR,"Key for router %s:%u is not 1024 bits. All keys must be exactly 1024 bits long.",router->address,router->port);
  278. free(router->address);
  279. RSA_free(router->pkey);
  280. free(router);
  281. fclose(rf);
  282. delete_routerlist(routerlist);
  283. return NULL;
  284. }
  285. router->next = NULL;
  286. /* save the entry into the routerlist linked list */
  287. if (!routerlist) /* this is the first entry */
  288. routerlist = router;
  289. else
  290. lastrouter->next = (void *)router;
  291. lastrouter = router;
  292. }
  293. }
  294. else
  295. {
  296. log(LOG_ERR,"Entry for router %s doesn't seem to contain a valid entry funnel port.",router->address);
  297. free(router->address);
  298. free(router);
  299. fclose(rf);
  300. delete_routerlist(routerlist);
  301. return NULL;
  302. }
  303. }
  304. else
  305. {
  306. log(LOG_ERR,"Entry for router %s doesn't seem to contain an entry funnel port.",router->address);
  307. free(router->address);
  308. free(router);
  309. fclose(rf);
  310. delete_routerlist(routerlist);
  311. return NULL;
  312. }
  313. }
  314. else
  315. {
  316. log(LOG_ERR,"Entry for router %s doesn't seem to contain a valid network funnel port.",router->address);
  317. free(router->address);
  318. free(router);
  319. fclose(rf);
  320. delete_routerlist(routerlist);
  321. return NULL;
  322. }
  323. }
  324. else
  325. {
  326. log(LOG_ERR,"Entry for router %s doesn't seem to contain a network funnel port.",router->address);
  327. free(router->address);
  328. free(router);
  329. fclose(rf);
  330. delete_routerlist(routerlist);
  331. return NULL;
  332. }
  333. }
  334. }
  335. retp=fgets(line,512,rf);
  336. }
  337. fclose(rf);
  338. return make_rarray(routerlist, lenp);
  339. }