routerlist.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463
  1. /* Copyright 2001-2003 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #define _GNU_SOURCE
  5. /* XXX this is required on rh7 to make strptime not complain. how bad
  6. * is this for portability?
  7. */
  8. #include "or.h"
  9. /****************************************************************************/
  10. static routerlist_t *routerlist = NULL; /* router array */
  11. extern or_options_t options; /* command-line and config-file options */
  12. /****************************************************************************/
  13. /* Enumeration of possible token types. The ones starting with K_ correspond
  14. * to directory 'keywords'. _SIGNATURE and _PUBLIC_KEY are self-explanatory.
  15. * _ERR is an error in the tokenizing process, _EOF is an end-of-file marker,
  16. * and _NIL is used to encode not-a-token.
  17. */
  18. typedef enum {
  19. K_ACCEPT,
  20. K_DIRECTORY_SIGNATURE,
  21. K_RECOMMENDED_SOFTWARE,
  22. K_REJECT,
  23. K_ROUTER,
  24. K_SIGNED_DIRECTORY,
  25. K_SIGNING_KEY,
  26. K_ONION_KEY,
  27. K_LINK_KEY,
  28. K_ROUTER_SIGNATURE,
  29. K_PUBLISHED,
  30. K_RUNNING_ROUTERS,
  31. K_PLATFORM,
  32. K_OPT,
  33. K_BANDWIDTH,
  34. K_PORTS,
  35. _UNRECOGNIZED,
  36. _ERR,
  37. _EOF,
  38. _NIL
  39. } directory_keyword;
  40. typedef struct directory_token_t {
  41. directory_keyword tp; /* Type of the token. */
  42. int n_args;
  43. char **args;
  44. char *object_type;
  45. int object_size;
  46. char *object_body;
  47. crypto_pk_env_t *key; /* For public keys only. */
  48. char *error; /* For _ERR tokens only. */
  49. } directory_token_t;
  50. /* ********************************************************************** */
  51. /* Every keyword takes either... */
  52. typedef enum {
  53. NO_ARGS, /* (1) no arguments, ever */
  54. ARGS, /* (2) a list of arguments separated by spaces */
  55. CONCAT_ARGS, /* or (3) the rest of the line, treated as a single argument. */
  56. } arg_syntax;
  57. typedef enum {
  58. NO_OBJ,
  59. NEED_OBJ,
  60. NEED_KEY,
  61. OBJ_OK,
  62. } obj_syntax;
  63. typedef enum {
  64. ANY = 0,
  65. DIR_ONLY,
  66. RTR_ONLY,
  67. } where_syntax;
  68. /* Table mapping keywods to token value and to argument rules. */
  69. static struct {
  70. char *t; int v; arg_syntax s; obj_syntax os; where_syntax ws;
  71. } token_table[] = {
  72. { "accept", K_ACCEPT, ARGS, NO_OBJ, RTR_ONLY },
  73. { "directory-signature", K_DIRECTORY_SIGNATURE, NO_ARGS, NEED_OBJ, DIR_ONLY},
  74. { "reject", K_REJECT, ARGS, NO_OBJ, RTR_ONLY },
  75. { "router", K_ROUTER, ARGS, NO_OBJ, RTR_ONLY },
  76. { "recommended-software", K_RECOMMENDED_SOFTWARE, ARGS, NO_OBJ, DIR_ONLY },
  77. { "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ, DIR_ONLY },
  78. { "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY, RTR_ONLY },
  79. { "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY, RTR_ONLY },
  80. { "link-key", K_LINK_KEY, NO_ARGS, NEED_KEY, RTR_ONLY },
  81. { "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ, RTR_ONLY },
  82. { "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ, ANY },
  83. { "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ, DIR_ONLY },
  84. { "platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ, RTR_ONLY },
  85. { "ports", K_PORTS, ARGS, NO_OBJ, RTR_ONLY },
  86. { "bandwidth", K_BANDWIDTH, ARGS, NO_OBJ, RTR_ONLY },
  87. { "opt", K_OPT, CONCAT_ARGS, OBJ_OK, ANY },
  88. { NULL, -1 }
  89. };
  90. /* ********************************************************************** */
  91. /* static function prototypes */
  92. static routerinfo_t *
  93. router_pick_directory_server_impl(void);
  94. static int
  95. router_get_list_from_string_impl(const char **s, routerlist_t **dest,
  96. int n_good_nicknames,
  97. const char **good_nickname_lst);
  98. static int
  99. router_get_routerlist_from_directory_impl(const char *s, routerlist_t **dest,
  100. crypto_pk_env_t *pkey);
  101. static int
  102. router_add_exit_policy(routerinfo_t *router, directory_token_t *tok);
  103. static int
  104. router_resolve_routerlist(routerlist_t *dir);
  105. static int router_get_hash_impl(const char *s, char *digest,
  106. const char *start_str, const char *end_str);
  107. static void token_free(directory_token_t *tok);
  108. static smartlist_t *find_all_exitpolicy(smartlist_t *s);
  109. static directory_token_t *find_first_by_keyword(smartlist_t *s,
  110. directory_keyword keyword);
  111. static int tokenize_string(const char *start, const char *end,
  112. smartlist_t *out, int is_dir);
  113. static directory_token_t *get_next_token(const char **s, where_syntax where);
  114. /****************************************************************************/
  115. extern int has_fetched_directory;
  116. /* try to find a running dirserver. if there are no dirservers
  117. * in our routerlist, reload the routerlist and try again. */
  118. routerinfo_t *router_pick_directory_server(void) {
  119. routerinfo_t *choice;
  120. choice = router_pick_directory_server_impl();
  121. if(!choice) {
  122. log_fn(LOG_WARN,"No dirservers known. Reloading and trying again.");
  123. has_fetched_directory=0; /* reset it */
  124. if(options.RouterFile) {
  125. if(router_set_routerlist_from_file(options.RouterFile) < 0)
  126. return NULL;
  127. } else {
  128. if(config_assign_default_dirservers() < 0)
  129. return NULL;
  130. }
  131. /* give it another try */
  132. choice = router_pick_directory_server_impl();
  133. }
  134. return choice;
  135. }
  136. /* pick a random running router with a positive dir_port */
  137. static routerinfo_t *router_pick_directory_server_impl(void) {
  138. int i;
  139. routerinfo_t *router, *dirserver=NULL;
  140. smartlist_t *sl;
  141. if(!routerlist)
  142. return NULL;
  143. sl = smartlist_create(MAX_ROUTERS_IN_DIR);
  144. for(i=0;i<routerlist->n_routers;i++) {
  145. router = routerlist->routers[i];
  146. if(router->dir_port > 0 && router->is_running)
  147. smartlist_add(sl, router);
  148. }
  149. router = smartlist_choose(sl);
  150. smartlist_free(sl);
  151. if(router)
  152. return router;
  153. log_fn(LOG_INFO,"No dirservers are reachable. Trying them all again.");
  154. /* no running dir servers found? go through and mark them all as up,
  155. * and we'll cycle through the list again. */
  156. for(i=0;i<routerlist->n_routers;i++) {
  157. router = routerlist->routers[i];
  158. if(router->dir_port > 0) {
  159. router->is_running = 1;
  160. dirserver = router;
  161. }
  162. }
  163. if(!dirserver)
  164. log_fn(LOG_WARN,"No dirservers in directory! Returning NULL.");
  165. return dirserver;
  166. }
  167. void router_add_running_routers_to_smartlist(smartlist_t *sl) {
  168. routerinfo_t *router;
  169. int i;
  170. if(!routerlist)
  171. return;
  172. for(i=0;i<routerlist->n_routers;i++) {
  173. router = routerlist->routers[i];
  174. if(router->is_running &&
  175. (!options.ORPort ||
  176. connection_twin_get_by_addr_port(router->addr, router->or_port) ))
  177. smartlist_add(sl, router);
  178. }
  179. }
  180. routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) {
  181. int i;
  182. routerinfo_t *router;
  183. assert(routerlist);
  184. for(i=0;i<routerlist->n_routers;i++) {
  185. router = routerlist->routers[i];
  186. if ((router->addr == addr) && (router->or_port == port))
  187. return router;
  188. }
  189. return NULL;
  190. }
  191. routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk)
  192. {
  193. int i;
  194. routerinfo_t *router;
  195. assert(routerlist);
  196. for(i=0;i<routerlist->n_routers;i++) {
  197. router = routerlist->routers[i];
  198. if (0 == crypto_pk_cmp_keys(router->link_pkey, pk))
  199. return router;
  200. }
  201. return NULL;
  202. }
  203. routerinfo_t *router_get_by_nickname(char *nickname)
  204. {
  205. int i;
  206. routerinfo_t *router;
  207. assert(routerlist);
  208. for(i=0;i<routerlist->n_routers;i++) {
  209. router = routerlist->routers[i];
  210. if (0 == strcmp(router->nickname, nickname))
  211. return router;
  212. }
  213. return NULL;
  214. }
  215. /* a way to access routerlist outside this file */
  216. void router_get_routerlist(routerlist_t **prouterlist) {
  217. *prouterlist = routerlist;
  218. }
  219. /* delete a router from memory */
  220. void routerinfo_free(routerinfo_t *router)
  221. {
  222. struct exit_policy_t *e;
  223. if (!router)
  224. return;
  225. tor_free(router->address);
  226. tor_free(router->nickname);
  227. if (router->onion_pkey)
  228. crypto_free_pk_env(router->onion_pkey);
  229. if (router->link_pkey)
  230. crypto_free_pk_env(router->link_pkey);
  231. if (router->identity_pkey)
  232. crypto_free_pk_env(router->identity_pkey);
  233. while (router->exit_policy) {
  234. e = router->exit_policy;
  235. router->exit_policy = e->next;
  236. tor_free(e->string);
  237. free(e);
  238. }
  239. free(router);
  240. }
  241. static void routerlist_free(routerlist_t *rl)
  242. {
  243. int i;
  244. for (i = 0; i < rl->n_routers; ++i)
  245. routerinfo_free(rl->routers[i]);
  246. tor_free(rl->routers);
  247. tor_free(rl->software_versions);
  248. free(rl);
  249. }
  250. void router_mark_as_down(char *nickname) {
  251. routerinfo_t *router = router_get_by_nickname(nickname);
  252. if(!router) /* we don't seem to know about him in the first place */
  253. return;
  254. log_fn(LOG_DEBUG,"Marking %s as down.",router->nickname);
  255. router->is_running = 0;
  256. }
  257. /* ------------------------------------------------------------ */
  258. /* Replace the current router list with the one stored in 'routerfile'. */
  259. int router_set_routerlist_from_file(char *routerfile)
  260. {
  261. char *string;
  262. string = read_file_to_str(routerfile);
  263. if(!string) {
  264. log_fn(LOG_WARN,"Failed to load routerfile %s.",routerfile);
  265. return -1;
  266. }
  267. if(router_set_routerlist_from_string(string) < 0) {
  268. log_fn(LOG_WARN,"The routerfile itself was corrupt.");
  269. free(string);
  270. return -1;
  271. }
  272. free(string);
  273. return 0;
  274. }
  275. /* Helper function: read routerinfo elements from s, and throw out the
  276. * ones that don't parse and resolve. Replace the current
  277. * routerlist. */
  278. int router_set_routerlist_from_string(const char *s)
  279. {
  280. if (router_get_list_from_string_impl(&s, &routerlist, -1, NULL)) {
  281. log(LOG_WARN, "Error parsing router file");
  282. return -1;
  283. }
  284. if (router_resolve_routerlist(routerlist)) {
  285. log(LOG_WARN, "Error resolving routerlist");
  286. return -1;
  287. }
  288. return 0;
  289. }
  290. /* Set 'digest' to the SHA-1 digest of the hash of the directory in 's'.
  291. * Return 0 on success, nonzero on failure.
  292. */
  293. int router_get_dir_hash(const char *s, char *digest)
  294. {
  295. return router_get_hash_impl(s,digest,
  296. "signed-directory","directory-signature");
  297. }
  298. /* Set 'digest' to the SHA-1 digest of the hash of the first router in 's'.
  299. * Return 0 on success, nonzero on failure.
  300. */
  301. int router_get_router_hash(const char *s, char *digest)
  302. {
  303. return router_get_hash_impl(s,digest,
  304. "router ","router-signature");
  305. }
  306. /* return 1 if myversion is in versionlist. Else return 0.
  307. * (versionlist contains a comma-separated list of versions.) */
  308. int is_recommended_version(const char *myversion,
  309. const char *versionlist) {
  310. int len_myversion = strlen(myversion);
  311. char *comma;
  312. const char *end = versionlist + strlen(versionlist);
  313. log_fn(LOG_DEBUG,"checking '%s' in '%s'.", myversion, versionlist);
  314. for(;;) {
  315. comma = strchr(versionlist, ',');
  316. if( ((comma ? comma : end) - versionlist == len_myversion) &&
  317. !strncmp(versionlist, myversion, len_myversion))
  318. /* only do strncmp if the length matches */
  319. return 1; /* success, it's there */
  320. if(!comma)
  321. return 0; /* nope */
  322. versionlist = comma+1;
  323. }
  324. }
  325. /* Replace the current routerlist with the routers stored in the directory
  326. * 's'. If pkey is provided, make sure that 's' is signed with pkey. */
  327. int router_set_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey)
  328. {
  329. if (router_get_routerlist_from_directory_impl(s, &routerlist, pkey)) {
  330. log_fn(LOG_WARN, "Couldn't parse directory.");
  331. return -1;
  332. }
  333. if (router_resolve_routerlist(routerlist)) {
  334. log_fn(LOG_WARN, "Error resolving routerlist");
  335. return -1;
  336. }
  337. if (is_recommended_version(VERSION,
  338. routerlist->software_versions) < 0) {
  339. log(options.IgnoreVersion ? LOG_WARN : LOG_ERR,
  340. "You are running Tor version %s, which will not work with this network.\n"
  341. "Please use %s%s.",
  342. VERSION, strchr(routerlist->software_versions,',') ? "one of " : "",
  343. routerlist->software_versions);
  344. if(options.IgnoreVersion) {
  345. log(LOG_WARN, "IgnoreVersion is set. If it breaks, we told you so.");
  346. } else {
  347. fflush(0);
  348. exit(0);
  349. }
  350. }
  351. return 0;
  352. }
  353. /* Helper function: resolve the hostname for 'router' */
  354. static int
  355. router_resolve(routerinfo_t *router)
  356. {
  357. struct hostent *rent;
  358. rent = (struct hostent *)gethostbyname(router->address);
  359. if (!rent) {
  360. log_fn(LOG_WARN,"Could not get address for router %s (%s).",
  361. router->address, router->nickname);
  362. return -1;
  363. }
  364. assert(rent->h_length == 4);
  365. memcpy(&router->addr, rent->h_addr,rent->h_length);
  366. router->addr = ntohl(router->addr); /* get it back into host order */
  367. return 0;
  368. }
  369. /* Helper function: resolve every router in rl. */
  370. static int
  371. router_resolve_routerlist(routerlist_t *rl)
  372. {
  373. int i, max, remove;
  374. if (!rl)
  375. rl = routerlist;
  376. max = rl->n_routers;
  377. for (i = 0; i < max; ++i) {
  378. remove = 0;
  379. if (router_resolve(rl->routers[i])) {
  380. log_fn(LOG_WARN, "Couldn't resolve router %s; not using",
  381. rl->routers[i]->address);
  382. remove = 1;
  383. } else if (options.Nickname &&
  384. !strcmp(rl->routers[i]->nickname, options.Nickname)) {
  385. remove = 1;
  386. }
  387. if (remove) {
  388. routerinfo_free(rl->routers[i]);
  389. rl->routers[i] = rl->routers[--max];
  390. --rl->n_routers;
  391. --i;
  392. }
  393. }
  394. return 0;
  395. }
  396. /* Addr is 0 for "IP unknown".
  397. *
  398. * Returns -1 for 'rejected', 0 for accepted, 1 for 'maybe' (since IP is
  399. * unknown.
  400. */
  401. int router_compare_addr_to_exit_policy(uint32_t addr, uint16_t port,
  402. struct exit_policy_t *policy)
  403. {
  404. int maybe_reject = 0;
  405. int maybe_accept = 0;
  406. int match = 0;
  407. int maybe = 0;
  408. struct in_addr in;
  409. struct exit_policy_t *tmpe;
  410. for(tmpe=policy; tmpe; tmpe=tmpe->next) {
  411. // log_fn(LOG_DEBUG,"Considering exit policy %s", tmpe->string);
  412. maybe = 0;
  413. if (!addr) {
  414. /* Address is unknown. */
  415. if (port >= tmpe->prt_min && port <= tmpe->prt_max) {
  416. /* The port definitely matches. */
  417. if (tmpe->msk == 0) {
  418. match = 1;
  419. } else {
  420. maybe = 1;
  421. }
  422. } else if (!port) {
  423. /* The port maybe matches. */
  424. maybe = 1;
  425. }
  426. } else {
  427. /* Address is known */
  428. if ((addr & tmpe->msk) == (tmpe->addr & tmpe->msk)) {
  429. if (port >= tmpe->prt_min && port <= tmpe->prt_max) {
  430. /* Exact match for the policy */
  431. match = 1;
  432. } else if (!port) {
  433. maybe = 1;
  434. }
  435. }
  436. }
  437. if (maybe) {
  438. if (tmpe->policy_type == EXIT_POLICY_REJECT)
  439. maybe_reject = 1;
  440. else
  441. maybe_accept = 1;
  442. }
  443. if (match) {
  444. in.s_addr = htonl(addr);
  445. log_fn(LOG_DEBUG,"Address %s:%d matches exit policy '%s'",
  446. inet_ntoa(in), port, tmpe->string);
  447. if(tmpe->policy_type == EXIT_POLICY_ACCEPT) {
  448. /* If we already hit a clause that might trigger a 'reject', than we
  449. * can't be sure of this certain 'accept'.*/
  450. return maybe_reject ? ADDR_POLICY_UNKNOWN : ADDR_POLICY_ACCEPTED;
  451. } else {
  452. return maybe_accept ? ADDR_POLICY_UNKNOWN : ADDR_POLICY_REJECTED;
  453. }
  454. }
  455. }
  456. /* accept all by default. */
  457. return maybe_reject ? ADDR_POLICY_UNKNOWN : ADDR_POLICY_ACCEPTED;
  458. }
  459. /* return 1 if all running routers will reject addr:port, return 0 if
  460. any might accept it. */
  461. int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port) {
  462. int i;
  463. routerinfo_t *router;
  464. for (i=0;i<routerlist->n_routers;i++) {
  465. router = routerlist->routers[i];
  466. if (router->is_running && router_compare_addr_to_exit_policy(
  467. addr, port, router->exit_policy) != ADDR_POLICY_REJECTED)
  468. return 0; /* this one could be ok. good enough. */
  469. }
  470. return 1; /* all will reject. */
  471. }
  472. int router_exit_policy_rejects_all(routerinfo_t *router) {
  473. return router_compare_addr_to_exit_policy(0, 0, router->exit_policy)
  474. == ADDR_POLICY_REJECTED;
  475. }
  476. static int parse_time(const char *cp, time_t *t)
  477. {
  478. struct tm st_tm;
  479. #ifdef HAVE_STRPTIME
  480. if (!strptime(cp, "%Y-%m-%d %H:%M:%S", &st_tm)) {
  481. log_fn(LOG_WARN, "Published time was unparseable"); return -1;
  482. }
  483. #else
  484. unsigned int year=0, month=0, day=0, hour=100, minute=100, second=100;
  485. if (sscanf(cp, "%u-%u-%u %u:%u:%u", &year, &month,
  486. &day, &hour, &minute, &second) < 6) {
  487. log_fn(LOG_WARN, "Published time was unparseable"); return -1;
  488. }
  489. if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
  490. hour > 23 || minute > 59 || second > 61) {
  491. log_fn(LOG_WARN, "Published time was nonsensical"); return -1;
  492. }
  493. st_tm.tm_year = year;
  494. st_tm.tm_mon = month-1;
  495. st_tm.tm_mday = day;
  496. st_tm.tm_hour = hour;
  497. st_tm.tm_min = minute;
  498. st_tm.tm_sec = second;
  499. #endif
  500. *t = tor_timegm(&st_tm);
  501. return 0;
  502. }
  503. /* Helper function: parse a directory from 's' and, when done, store the
  504. * resulting routerlist in *dest, freeing the old value if necessary.
  505. * If pkey is provided, we check the directory signature with pkey.
  506. */
  507. static int
  508. router_get_routerlist_from_directory_impl(const char *str,
  509. routerlist_t **dest,
  510. crypto_pk_env_t *pkey)
  511. {
  512. directory_token_t *tok;
  513. char digest[20];
  514. char signed_digest[128];
  515. routerlist_t *new_dir = NULL;
  516. char *versions = NULL;
  517. time_t published_on;
  518. char *good_nickname_lst[1024];
  519. int n_good_nicknames = 0;
  520. int i, r;
  521. const char *end;
  522. smartlist_t *tokens = NULL;
  523. if (router_get_dir_hash(str, digest)) {
  524. log_fn(LOG_WARN, "Unable to compute digest of directory");
  525. goto err;
  526. }
  527. log(LOG_DEBUG,"Received directory hashes to %02x:%02x:%02x:%02x",
  528. ((int)digest[0])&0xff,((int)digest[1])&0xff,
  529. ((int)digest[2])&0xff,((int)digest[3])&0xff);
  530. if ((end = strstr(str,"\nrouter "))) {
  531. ++end;
  532. } else if ((end = strstr(str, "\ndirectory-signature"))) {
  533. ++end;
  534. } else {
  535. end = str + strlen(str);
  536. }
  537. tokens = smartlist_create(128);
  538. if (tokenize_string(str,end,tokens,1)) {
  539. log_fn(LOG_WARN, "Error tokenizing directory"); goto err;
  540. }
  541. if (tokens->num_used < 1) {
  542. log_fn(LOG_WARN, "Impossibly short directory header"); goto err;
  543. }
  544. if ((tok = find_first_by_keyword(tokens, _UNRECOGNIZED))) {
  545. log_fn(LOG_WARN, "Unrecognized keyword in \"%s\"; can't parse directory.",
  546. tok->args[0]);
  547. goto err;
  548. }
  549. tok = (directory_token_t*)tokens->list[0];
  550. if (tok->tp != K_SIGNED_DIRECTORY) {
  551. log_fn(LOG_WARN, "Directory doesn't start with signed-directory.");
  552. goto err;
  553. }
  554. if (!(tok = find_first_by_keyword(tokens, K_PUBLISHED))) {
  555. log_fn(LOG_WARN, "Missing published time on directory.");
  556. goto err;
  557. }
  558. assert(tok->n_args == 1);
  559. if (parse_time(tok->args[0], &published_on) < 0) {
  560. goto err;
  561. }
  562. if (!(tok = find_first_by_keyword(tokens, K_RECOMMENDED_SOFTWARE))) {
  563. log_fn(LOG_WARN, "Missing recommended-software line from directory.");
  564. goto err;
  565. }
  566. if (tok->n_args != 1) {
  567. log_fn(LOG_WARN, "Invalid recommended-software line"); goto err;
  568. }
  569. versions = tor_strdup(tok->args[0]);
  570. if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
  571. log_fn(LOG_WARN, "Missing running-routers line from directory.");
  572. goto err;
  573. }
  574. n_good_nicknames = tok->n_args;
  575. memcpy(good_nickname_lst, tok->args, n_good_nicknames*sizeof(char *));
  576. tok->n_args = 0; /* Don't free the strings in good_nickname_lst yet. */
  577. /* Read the router list from s, advancing s up past the end of the last
  578. * router. */
  579. str = end;
  580. if (router_get_list_from_string_impl(&str, &new_dir,
  581. n_good_nicknames,
  582. (const char**)good_nickname_lst)) {
  583. log_fn(LOG_WARN, "Error reading routers from directory");
  584. goto err;
  585. }
  586. for (i = 0; i < n_good_nicknames; ++i) {
  587. tor_free(good_nickname_lst[i]); /* now free them */
  588. }
  589. new_dir->software_versions = versions; versions = NULL;
  590. new_dir->published_on = published_on;
  591. for (i = 0; i < tokens->num_used; ++i) {
  592. token_free((directory_token_t*)tokens->list[i]);
  593. }
  594. smartlist_free(tokens);
  595. tokens = smartlist_create(128);
  596. if (tokenize_string(str,str+strlen(str),tokens,1)<0) {
  597. log_fn(LOG_WARN, "Error tokenizing signature"); goto err;
  598. }
  599. if (tokens->num_used != 1 ||
  600. ((directory_token_t*)tokens->list[0])->tp != K_DIRECTORY_SIGNATURE){
  601. log_fn(LOG_WARN,"Expected a single directory signature"); goto err;
  602. }
  603. tok = (directory_token_t*)tokens->list[0];
  604. if (strcmp(tok->object_type, "SIGNATURE") || tok->object_size != 128) {
  605. log_fn(LOG_WARN, "Bad object type or length on directory signature");
  606. goto err;
  607. }
  608. if (pkey) {
  609. if (crypto_pk_public_checksig(pkey, tok->object_body, 128, signed_digest)
  610. != 20) {
  611. log_fn(LOG_WARN, "Error reading directory: invalid signature.");
  612. goto err;
  613. }
  614. log(LOG_DEBUG,"Signed directory hash starts %02x:%02x:%02x:%02x",
  615. ((int)signed_digest[0])&0xff,((int)signed_digest[1])&0xff,
  616. ((int)signed_digest[2])&0xff,((int)signed_digest[3])&0xff);
  617. if (memcmp(digest, signed_digest, 20)) {
  618. log_fn(LOG_WARN, "Error reading directory: signature does not match.");
  619. goto err;
  620. }
  621. }
  622. if (*dest)
  623. routerlist_free(*dest);
  624. *dest = new_dir;
  625. r = 0;
  626. goto done;
  627. err:
  628. r = -1;
  629. if (new_dir)
  630. routerlist_free(new_dir);
  631. tor_free(versions);
  632. for (i = 0; i < n_good_nicknames; ++i) {
  633. tor_free(good_nickname_lst[i]);
  634. }
  635. done:
  636. if (tokens) {
  637. for (i = 0; i < tokens->num_used; ++i) {
  638. token_free((directory_token_t*)tokens->list[i]);
  639. }
  640. smartlist_free(tokens);
  641. }
  642. return r;
  643. }
  644. /* Helper function: Given a string *s containing a concatenated
  645. * sequence of router descriptors, parses them and stores the result
  646. * in *dest. If good_nickname_lst is provided, then routers whose
  647. * nicknames are not listed are marked as nonrunning. Advances *s to
  648. * a point immediately following the last router entry. Returns 0 on
  649. * success and -1 on failure.
  650. */
  651. static int
  652. router_get_list_from_string_impl(const char **s, routerlist_t **dest,
  653. int n_good_nicknames,
  654. const char **good_nickname_lst)
  655. {
  656. routerinfo_t *router;
  657. routerinfo_t **rarray;
  658. int rarray_len = 0;
  659. int i;
  660. const char *end;
  661. assert(s && *s);
  662. rarray = (routerinfo_t **)
  663. tor_malloc((sizeof(routerinfo_t *))*MAX_ROUTERS_IN_DIR);
  664. while (1) {
  665. *s = eat_whitespace(*s);
  666. /* Don't start parsing the rest of *s unless it contains a router. */
  667. if (strncmp(*s, "router ", 7)!=0)
  668. break;
  669. if ((end = strstr(*s+1, "\nrouter "))) {
  670. end++;
  671. } else if ((end = strstr(*s+1, "\ndirectory-signature"))) {
  672. end++;
  673. } else {
  674. end = *s+strlen(*s);
  675. }
  676. router = router_get_entry_from_string(*s, end);
  677. *s = end;
  678. if (!router) {
  679. log_fn(LOG_WARN, "Error reading router; skipping");
  680. continue;
  681. }
  682. if (n_good_nicknames>=0) {
  683. router->is_running = 0;
  684. for (i = 0; i < n_good_nicknames; ++i) {
  685. if (0==strcasecmp(good_nickname_lst[i], router->nickname)) {
  686. router->is_running = 1;
  687. break;
  688. }
  689. }
  690. } else {
  691. router->is_running = 1; /* start out assuming all dirservers are up */
  692. }
  693. rarray[rarray_len++] = router;
  694. log_fn(LOG_DEBUG,"just added router #%d.",rarray_len);
  695. }
  696. if (*dest)
  697. routerlist_free(*dest);
  698. *dest = (routerlist_t *)tor_malloc(sizeof(routerlist_t));
  699. (*dest)->routers = rarray;
  700. (*dest)->n_routers = rarray_len;
  701. (*dest)->software_versions = NULL;
  702. return 0;
  703. }
  704. /* Helper function: reads a single router entry from *s, and advances
  705. * *s so it points to just after the router it just read.
  706. * mallocs a new router and returns it if all goes well, else returns
  707. * NULL.
  708. *
  709. * DOCDOC
  710. */
  711. routerinfo_t *router_get_entry_from_string(const char *s,
  712. const char *end) {
  713. routerinfo_t *router = NULL;
  714. char signed_digest[128];
  715. char digest[128];
  716. smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
  717. directory_token_t *tok;
  718. int t, i;
  719. int ports_set, bw_set;
  720. if (!end) {
  721. end = s + strlen(s);
  722. }
  723. if (router_get_router_hash(s, digest) < 0) {
  724. log_fn(LOG_WARN, "Couldn't compute router hash.");
  725. return NULL;
  726. }
  727. tokens = smartlist_create(128);
  728. if (tokenize_string(s,end,tokens,0)) {
  729. log_fn(LOG_WARN, "Error tokeninzing router descriptor."); goto err;
  730. }
  731. if (tokens->num_used < 2) {
  732. log_fn(LOG_WARN, "Impossibly short router descriptor.");
  733. goto err;
  734. }
  735. if ((tok = find_first_by_keyword(tokens, _UNRECOGNIZED))) {
  736. log_fn(LOG_WARN, "Unrecognized keyword in \"%s\"; skipping descriptor.",
  737. tok->args[0]);
  738. goto err;
  739. }
  740. tok = (directory_token_t*)tokens->list[0];
  741. if (tok->tp != K_ROUTER) {
  742. log_fn(LOG_WARN,"Entry does not start with \"router\"");
  743. goto err;
  744. }
  745. router = tor_malloc_zero(sizeof(routerinfo_t));
  746. router->onion_pkey = router->identity_pkey = router->link_pkey = NULL;
  747. ports_set = bw_set = 0;
  748. if (tok->n_args == 2 || tok->n_args == 6) {
  749. router->nickname = tor_strdup(tok->args[0]);
  750. if (strlen(router->nickname) > MAX_NICKNAME_LEN) {
  751. log_fn(LOG_WARN,"Router nickname too long.");
  752. goto err;
  753. }
  754. if (strspn(router->nickname, LEGAL_NICKNAME_CHARACTERS) !=
  755. strlen(router->nickname)) {
  756. log_fn(LOG_WARN, "Router nickname contains illegal characters.");
  757. goto err;
  758. }
  759. router->address = tor_strdup(tok->args[1]);
  760. router->addr = 0;
  761. if (tok->n_args == 6) {
  762. router->or_port = atoi(tok->args[2]);
  763. router->socks_port = atoi(tok->args[3]);
  764. router->dir_port = atoi(tok->args[4]);
  765. router->bandwidthrate = atoi(tok->args[5]);
  766. ports_set = bw_set = 1;
  767. }
  768. } else {
  769. log_fn(LOG_WARN,"Wrong # of arguments to \"router\"");
  770. goto err;
  771. }
  772. tok = find_first_by_keyword(tokens, K_PORTS);
  773. if (tok && ports_set) {
  774. log_fn(LOG_WARN,"Redundant ports line");
  775. goto err;
  776. } else if (tok) {
  777. if (tok->n_args != 3) {
  778. log_fn(LOG_WARN,"Wrong # of arguments to \"ports\"");
  779. goto err;
  780. }
  781. router->or_port = atoi(tok->args[0]);
  782. router->socks_port = atoi(tok->args[1]);
  783. router->dir_port = atoi(tok->args[2]);
  784. ports_set = 1;
  785. }
  786. tok = find_first_by_keyword(tokens, K_BANDWIDTH);
  787. if (tok && bw_set) {
  788. log_fn(LOG_WARN,"Redundant bandwidth line");
  789. goto err;
  790. } else if (tok) {
  791. if (tok->n_args < 1) {
  792. log_fn(LOG_WARN,"Not enough arguments to \"bandwidth\"");
  793. goto err;
  794. }
  795. router->bandwidthrate = atoi(tok->args[0]);
  796. bw_set = 1;
  797. }
  798. if (!(tok = find_first_by_keyword(tokens, K_PUBLISHED))) {
  799. log_fn(LOG_WARN, "Missing published time"); goto err;
  800. }
  801. assert(tok->n_args == 1);
  802. if (parse_time(tok->args[0], &router->published_on) < 0)
  803. goto err;
  804. if (!(tok = find_first_by_keyword(tokens, K_ONION_KEY))) {
  805. log_fn(LOG_WARN, "Missing onion key"); goto err;
  806. }
  807. /* XXX Check key length */
  808. router->onion_pkey = tok->key;
  809. tok->key = NULL; /* Prevent free */
  810. if (!(tok = find_first_by_keyword(tokens, K_LINK_KEY))) {
  811. log_fn(LOG_WARN, "Missing onion key"); goto err;
  812. }
  813. /* XXX Check key length */
  814. router->link_pkey = tok->key;
  815. tok->key = NULL; /* Prevent free */
  816. if (!(tok = find_first_by_keyword(tokens, K_SIGNING_KEY))) {
  817. log_fn(LOG_WARN, "Missing onion key"); goto err;
  818. }
  819. /* XXX Check key length */
  820. router->identity_pkey = tok->key;
  821. tok->key = NULL; /* Prevent free */
  822. exit_policy_tokens = find_all_exitpolicy(tokens);
  823. for (i = 0; i < exit_policy_tokens->num_used; ++i) {
  824. if (router_add_exit_policy(router,
  825. (directory_token_t*)exit_policy_tokens->list[i])<0) {
  826. log_fn(LOG_WARN, "Error in exit policy"); goto err;
  827. }
  828. }
  829. if (!(tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE))) {
  830. log_fn(LOG_WARN, "Missing router signature"); goto err;
  831. }
  832. if (strcmp(tok->object_type, "SIGNATURE") || tok->object_size != 128) {
  833. log_fn(LOG_WARN, "Bad object type or length on router signature");
  834. goto err;
  835. }
  836. if ((t=crypto_pk_public_checksig(router->identity_pkey, tok->object_body,
  837. 128, signed_digest)) != 20) {
  838. log_fn(LOG_WARN, "Invalid signature %d",t); goto err;
  839. }
  840. if (memcmp(digest, signed_digest, 20)) {
  841. log_fn(LOG_WARN, "Mismatched signature"); goto err;
  842. }
  843. if (!ports_set) {
  844. log_fn(LOG_WARN,"No ports declared; failing."); goto err;
  845. }
  846. if (!bw_set) {
  847. log_fn(LOG_WARN,"No bandwidth declared; failing."); goto err;
  848. }
  849. if(!router->or_port) {
  850. log_fn(LOG_WARN,"or_port unreadable or 0. Failing.");
  851. goto err;
  852. }
  853. if (!router->bandwidthrate) {
  854. log_fn(LOG_WARN,"bandwidthrate unreadable or 0. Failing.");
  855. goto err;
  856. }
  857. #if XXXBC
  858. router->bandwidthburst = atoi(ARGS[6]);
  859. if (!router->bandwidthburst) {
  860. log_fn(LOG_WARN,"bandwidthburst unreadable or 0. Failing.");
  861. goto err;
  862. }
  863. #else
  864. router->bandwidthburst = 10*router->bandwidthrate;
  865. #endif
  866. log_fn(LOG_DEBUG,"or_port %d, socks_port %d, dir_port %d, bandwidthrate %u, bandwidthburst %u.",
  867. router->or_port, router->socks_port, router->dir_port,
  868. (unsigned) router->bandwidthrate, (unsigned) router->bandwidthburst);
  869. goto done;
  870. return router;
  871. err:
  872. routerinfo_free(router);
  873. router = NULL;
  874. done:
  875. if (tokens) {
  876. for (i = 0; i < tokens->num_used; ++i) {
  877. token_free((directory_token_t*)tokens->list[i]);
  878. }
  879. smartlist_free(tokens);
  880. }
  881. if (exit_policy_tokens) {
  882. smartlist_free(exit_policy_tokens);
  883. }
  884. return router;
  885. }
  886. /* Parse the exit policy in the string 's' and add it to 'router'.
  887. */
  888. int
  889. router_add_exit_policy_from_string(routerinfo_t *router, const char *s)
  890. {
  891. directory_token_t *tok = NULL;
  892. const char *cp;
  893. char *tmp;
  894. int r;
  895. int len, idx;
  896. /* *s might not end with \n, so we need to extend it with one. */
  897. len = strlen(s);
  898. cp = tmp = tor_malloc(len+2);
  899. for (idx = 0; idx < len; ++idx) {
  900. tmp[idx] = tolower(s[idx]);
  901. }
  902. tmp[len]='\n';
  903. tmp[len+1]='\0';
  904. tok = get_next_token(&cp, RTR_ONLY);
  905. if (tok->tp == _ERR) {
  906. log_fn(LOG_WARN, "Error reading exit policy: %s", tok->error);
  907. goto err;
  908. }
  909. if (tok->tp != K_ACCEPT && tok->tp != K_REJECT) {
  910. log_fn(LOG_WARN, "Expected 'accept' or 'reject'.");
  911. goto err;
  912. }
  913. /* Now that we've gotten an exit policy, add it to the router. */
  914. r = router_add_exit_policy(router, tok);
  915. goto done;
  916. err:
  917. r = -1;
  918. done:
  919. free(tmp);
  920. token_free(tok);
  921. return r;
  922. }
  923. /* Given a K_ACCEPT or K_REJECT token and a router, create a new exit_policy_t
  924. * corresponding to the token, and add it to 'router' */
  925. static int
  926. router_add_exit_policy(routerinfo_t *router, directory_token_t *tok) {
  927. struct exit_policy_t *tmpe, *newe;
  928. struct in_addr in;
  929. char *arg, *address, *mask, *port, *endptr;
  930. int bits;
  931. assert(tok->tp == K_REJECT || tok->tp == K_ACCEPT);
  932. if (tok->n_args != 1)
  933. return -1;
  934. arg = tok->args[0];
  935. newe = tor_malloc_zero(sizeof(struct exit_policy_t));
  936. newe->string = tor_malloc(8+strlen(arg));
  937. if (tok->tp == K_REJECT) {
  938. strcpy(newe->string, "reject ");
  939. newe->policy_type = EXIT_POLICY_REJECT;
  940. } else {
  941. strcpy(newe->string, "accept ");
  942. newe->policy_type = EXIT_POLICY_ACCEPT;
  943. }
  944. strcat(newe->string, arg); /* can't overflow */
  945. address = arg;
  946. mask = strchr(arg,'/');
  947. port = strchr(mask?mask:arg,':');
  948. /* Break 'arg' into separate strings. 'arg' was already strdup'd by
  949. * _router_get_next_token, so it's safe to modify.
  950. */
  951. if (mask)
  952. *mask++ = 0;
  953. if (port)
  954. *port++ = 0;
  955. if (strcmp(address, "*") == 0) {
  956. newe->addr = 0;
  957. } else if (tor_inet_aton(address, &in) != 0) {
  958. newe->addr = ntohl(in.s_addr);
  959. } else {
  960. log_fn(LOG_WARN, "Malformed IP %s in exit policy; rejecting.",
  961. address);
  962. goto policy_read_failed;
  963. }
  964. if (!mask) {
  965. if (strcmp(address, "*") == 0)
  966. newe->msk = 0;
  967. else
  968. newe->msk = 0xFFFFFFFFu;
  969. } else {
  970. endptr = NULL;
  971. bits = (int) strtol(mask, &endptr, 10);
  972. if (!*endptr) {
  973. /* strtol handled the whole mask. */
  974. newe->msk = ~((1<<(32-bits))-1);
  975. } else if (tor_inet_aton(mask, &in) != 0) {
  976. newe->msk = ntohl(in.s_addr);
  977. } else {
  978. log_fn(LOG_WARN, "Malformed mask %s on exit policy; rejecting.",
  979. mask);
  980. goto policy_read_failed;
  981. }
  982. }
  983. if (!port || strcmp(port, "*") == 0) {
  984. newe->prt_min = 0;
  985. newe->prt_max = 65535;
  986. } else {
  987. endptr = NULL;
  988. newe->prt_min = (uint16_t) strtol(port, &endptr, 10);
  989. if (*endptr == '-') {
  990. port = endptr+1;
  991. endptr = NULL;
  992. newe->prt_max = (uint16_t) strtol(port, &endptr, 10);
  993. if (*endptr) {
  994. log_fn(LOG_WARN, "Malformed port %s on exit policy; rejecting.",
  995. port);
  996. }
  997. } else if (*endptr) {
  998. log_fn(LOG_WARN, "Malformed port %s on exit policy; rejecting.",
  999. port);
  1000. goto policy_read_failed;
  1001. } else {
  1002. newe->prt_max = newe->prt_min;
  1003. }
  1004. }
  1005. in.s_addr = htonl(newe->addr);
  1006. address = tor_strdup(inet_ntoa(in));
  1007. in.s_addr = htonl(newe->msk);
  1008. log_fn(LOG_DEBUG,"%s %s/%s:%d-%d",
  1009. newe->policy_type == EXIT_POLICY_REJECT ? "reject" : "accept",
  1010. address, inet_ntoa(in), newe->prt_min, newe->prt_max);
  1011. tor_free(address);
  1012. /* now link newe onto the end of exit_policy */
  1013. if(!router->exit_policy) {
  1014. router->exit_policy = newe;
  1015. return 0;
  1016. }
  1017. for(tmpe=router->exit_policy; tmpe->next; tmpe=tmpe->next) ;
  1018. tmpe->next = newe;
  1019. return 0;
  1020. policy_read_failed:
  1021. assert(newe->string);
  1022. log_fn(LOG_WARN,"Couldn't parse line '%s'. Dropping", newe->string);
  1023. tor_free(newe->string);
  1024. free(newe);
  1025. return -1;
  1026. }
  1027. /* ------------------------------------------------------------ */
  1028. /* Tokenizer for router descriptors and directories. */
  1029. /* Free any malloced resources allocated for a token. Does not free
  1030. * the token itself.
  1031. */
  1032. static void
  1033. token_free(directory_token_t *tok)
  1034. {
  1035. int i;
  1036. assert(tok);
  1037. if (tok->args) {
  1038. for (i = 0; i < tok->n_args; ++i) {
  1039. tor_free(tok->args[i]);
  1040. }
  1041. tor_free(tok->args);
  1042. }
  1043. tor_free(tok->object_type);
  1044. tor_free(tok->object_body);
  1045. if (tok->key)
  1046. crypto_free_pk_env(tok->key);
  1047. tor_free(tok);
  1048. }
  1049. /* Helper function: read the next token from *s, and stores it into a new
  1050. * directory token *tok.
  1051. */
  1052. static directory_token_t *
  1053. get_next_token(const char **s, where_syntax where) {
  1054. const char *next, *obstart;
  1055. int i, done, allocated;
  1056. directory_token_t *tok;
  1057. arg_syntax a_syn;
  1058. obj_syntax o_syn = NO_OBJ;
  1059. #define RET_ERR(msg) \
  1060. do { if (tok) token_free(tok); \
  1061. tok = tor_malloc_zero(sizeof(directory_token_t));\
  1062. tok->tp = _ERR; \
  1063. tok->error = msg; \
  1064. goto done_tokenizing; } while (0)
  1065. tok = tor_malloc_zero(sizeof(directory_token_t));
  1066. tok->tp = _ERR;
  1067. *s = eat_whitespace(*s);
  1068. if (!**s) {
  1069. tok->tp = _EOF;
  1070. return tok;
  1071. }
  1072. next = find_whitespace(*s);
  1073. if (!next) {
  1074. tok->error = "Unexpected EOF"; return tok;
  1075. }
  1076. /* It's a keyword... but which one? */
  1077. for (i = 0 ; token_table[i].t ; ++i) {
  1078. if (!strncmp(token_table[i].t, *s, next-*s)) {
  1079. /* We've found the keyword. */
  1080. tok->tp = token_table[i].v;
  1081. a_syn = token_table[i].s;
  1082. o_syn = token_table[i].os;
  1083. if (token_table[i].ws != ANY && token_table[i].ws != where) {
  1084. if (where == DIR_ONLY) {
  1085. RET_ERR("Found a router-only token in a directory section");
  1086. } else {
  1087. RET_ERR("Found a directory-only token in a router descriptor");
  1088. }
  1089. }
  1090. if (a_syn == ARGS) {
  1091. /* This keyword takes multiple arguments. */
  1092. i = 0;
  1093. done = (*next == '\n');
  1094. allocated = 32;
  1095. tok->args = (char**)tor_malloc(sizeof(char*)*32);
  1096. *s = eat_whitespace_no_nl(next);
  1097. while (**s != '\n' && !done) {
  1098. next = find_whitespace(*s);
  1099. if (*next == '\n')
  1100. done = 1;
  1101. if (i == allocated) {
  1102. allocated *= 2;
  1103. tok->args = (char**)tor_realloc(tok->args,sizeof(char*)*allocated);
  1104. }
  1105. tok->args[i++] = tor_strndup(*s,next-*s);
  1106. *s = eat_whitespace_no_nl(next+1);
  1107. }
  1108. tok->n_args = i;
  1109. } else if (a_syn == CONCAT_ARGS) {
  1110. /* The keyword takes the line as a single argument */
  1111. *s = eat_whitespace_no_nl(next);
  1112. next = strchr(*s, '\n');
  1113. if (!next)
  1114. RET_ERR("Unexpected EOF");
  1115. tok->args = (char**) tor_malloc(sizeof(char*));
  1116. tok->args[0] = tor_strndup(*s,next-*s);
  1117. tok->n_args = 1;
  1118. *s = eat_whitespace_no_nl(next+1);
  1119. } else {
  1120. /* The keyword takes no arguments. */
  1121. assert(a_syn == NO_ARGS);
  1122. *s = eat_whitespace_no_nl(next);
  1123. if (**s != '\n') {
  1124. RET_ERR("Unexpected arguments");
  1125. }
  1126. tok->n_args = 0;
  1127. *s = eat_whitespace_no_nl(*s+1);
  1128. }
  1129. break;
  1130. }
  1131. }
  1132. if (tok->tp == _ERR) {
  1133. tok->tp = _UNRECOGNIZED;
  1134. next = strchr(*s, '\n');
  1135. if (!next) {
  1136. RET_ERR("Unexpected EOF");
  1137. }
  1138. tok->args = (char**) tor_malloc(sizeof(char*));
  1139. tok->args[0] = tor_strndup(*s,next-*s);
  1140. tok->n_args = 1;
  1141. *s = next+1;
  1142. o_syn = OBJ_OK;
  1143. }
  1144. *s = eat_whitespace(*s);
  1145. if (strncmp(*s, "-----BEGIN ", 11)) {
  1146. goto done_tokenizing;
  1147. }
  1148. obstart = *s;
  1149. *s += 11; /* length of "-----BEGIN ". */
  1150. next = strchr(*s, '\n');
  1151. if (next-*s < 6 || strncmp(next-5, "-----\n", 6)) {
  1152. RET_ERR("Malformed object: bad begin line");
  1153. }
  1154. tok->object_type = tor_strndup(*s, next-*s-5);
  1155. *s = next+1;
  1156. next = strstr(*s, "-----END ");
  1157. if (!next) {
  1158. RET_ERR("Malformed object: missing end line");
  1159. }
  1160. if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) {
  1161. if (strncmp(next, "-----END RSA PUBLIC KEY-----\n", 29))
  1162. RET_ERR("Malformed object: mismatched end line");
  1163. next = strchr(next,'\n')+1;
  1164. tok->key = crypto_new_pk_env(CRYPTO_PK_RSA);
  1165. if (crypto_pk_read_public_key_from_string(tok->key, obstart, next-obstart))
  1166. RET_ERR("Couldn't parse public key.");
  1167. *s = next;
  1168. } else {
  1169. tok->object_body = tor_malloc(next-*s); /* really, this is too much RAM. */
  1170. i = base64_decode(tok->object_body, 256, *s, next-*s);
  1171. if (i<0) {
  1172. RET_ERR("Malformed object: bad base64-encoded data");
  1173. }
  1174. tok->object_size = i;
  1175. *s = next + 9; /* length of "-----END ". */
  1176. i = strlen(tok->object_type);
  1177. if (strncmp(*s, tok->object_type, i) || strncmp(*s+i, "-----\n", 6)) {
  1178. RET_ERR("Malformed object: mismatched end tag");
  1179. }
  1180. *s += i+6;
  1181. }
  1182. switch(o_syn)
  1183. {
  1184. case NO_OBJ:
  1185. if (tok->object_body)
  1186. RET_ERR("Unexpected object for keyword");
  1187. if (tok->key)
  1188. RET_ERR("Unexpected public key for keyword");
  1189. break;
  1190. case NEED_OBJ:
  1191. if (!tok->object_body)
  1192. RET_ERR("Missing object for keyword");
  1193. break;
  1194. case NEED_KEY:
  1195. if (!tok->key)
  1196. RET_ERR("Missing publid key for keyword");
  1197. break;
  1198. case OBJ_OK:
  1199. break;
  1200. }
  1201. done_tokenizing:
  1202. #if 0
  1203. for (i = 0; token_table[i].t ; ++i) {
  1204. if (token_table[i].v == tok->tp) {
  1205. fputs(token_table[i].t, stdout);
  1206. break;
  1207. i = -1;
  1208. }
  1209. }
  1210. if (i) {
  1211. if (tok->tp == _UNRECOGNIZED) fputs("UNRECOGNIZED", stdout);
  1212. if (tok->tp == _ERR) fputs("ERR",stdout);
  1213. if (tok->tp == _EOF) fputs("EOF",stdout);
  1214. if (tok->tp == _NIL) fputs("_NIL",stdout);
  1215. }
  1216. for(i = 0; i < tok->n_args; ++i) {
  1217. fprintf(stdout," \"%s\"", tok->args[i]);
  1218. }
  1219. if (tok->error) { fprintf(stdout," *%s*", tok->error); }
  1220. fputs("\n",stdout);
  1221. #endif
  1222. return tok;
  1223. #undef RET_ERR
  1224. }
  1225. static int
  1226. tokenize_string(const char *start, const char *end, smartlist_t *out,
  1227. int is_dir)
  1228. {
  1229. const char **s;
  1230. directory_token_t *tok = NULL;
  1231. where_syntax where = is_dir ? DIR_ONLY : RTR_ONLY;
  1232. s = &start;
  1233. while (*s < end && (!tok || tok->tp != _EOF)) {
  1234. tok = get_next_token(s, where);
  1235. if (tok->tp == _ERR) {
  1236. log_fn(LOG_WARN, "parse error: %s", tok->error);
  1237. return -1;
  1238. }
  1239. smartlist_add(out, tok);
  1240. *s = eat_whitespace(*s);
  1241. }
  1242. return 0;
  1243. }
  1244. static directory_token_t *
  1245. find_first_by_keyword(smartlist_t *s, directory_keyword keyword)
  1246. {
  1247. int i;
  1248. directory_token_t *tok;
  1249. for (i = 0; i < s->num_used; ++i) {
  1250. tok = (directory_token_t*) s->list[i];
  1251. if (tok->tp == keyword) {
  1252. return tok;
  1253. }
  1254. }
  1255. return NULL;
  1256. }
  1257. static smartlist_t *
  1258. find_all_exitpolicy(smartlist_t *s)
  1259. {
  1260. int i;
  1261. directory_token_t *tok;
  1262. smartlist_t *out = smartlist_create(s->num_used);
  1263. for (i = 0; i < s->num_used; ++i) {
  1264. tok = (directory_token_t*) s->list[i];
  1265. if (tok->tp == K_ACCEPT || tok->tp == K_REJECT) {
  1266. smartlist_add(out,tok);
  1267. }
  1268. }
  1269. return out;
  1270. }
  1271. /* Compute the SHA digest of the substring of s taken from the first
  1272. * occurrence of start_str through the first newline after the first
  1273. * subsequent occurrence of end_str; store the 20-byte result in 'digest';
  1274. * return 0 on success.
  1275. *
  1276. * If no such substring exists, return -1.
  1277. */
  1278. static int router_get_hash_impl(const char *s, char *digest,
  1279. const char *start_str,
  1280. const char *end_str)
  1281. {
  1282. char *start, *end;
  1283. start = strstr(s, start_str);
  1284. if (!start) {
  1285. log_fn(LOG_WARN,"couldn't find \"%s\"",start_str);
  1286. return -1;
  1287. }
  1288. end = strstr(start+strlen(start_str), end_str);
  1289. if (!end) {
  1290. log_fn(LOG_WARN,"couldn't find \"%s\"",end_str);
  1291. return -1;
  1292. }
  1293. end = strchr(end, '\n');
  1294. if (!end) {
  1295. log_fn(LOG_WARN,"couldn't find EOL");
  1296. return -1;
  1297. }
  1298. ++end;
  1299. if (crypto_SHA_digest(start, end-start, digest)) {
  1300. log_fn(LOG_WARN,"couldn't compute digest");
  1301. return -1;
  1302. }
  1303. return 0;
  1304. }
  1305. /*
  1306. Local Variables:
  1307. mode:c
  1308. indent-tabs-mode:nil
  1309. c-basic-offset:2
  1310. End:
  1311. */