test_microdesc.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /* Copyright (c) 2010-2013, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "orconfig.h"
  4. #include "or.h"
  5. #include "config.h"
  6. #include "dirvote.h"
  7. #include "microdesc.h"
  8. #include "routerlist.h"
  9. #include "routerparse.h"
  10. #include "test.h"
  11. #include <openssl/rsa.h>
  12. #include <openssl/bn.h>
  13. #include <openssl/pem.h>
  14. #ifdef _WIN32
  15. /* For mkdir() */
  16. #include <direct.h>
  17. #else
  18. #include <dirent.h>
  19. #endif
  20. static const char test_md1[] =
  21. "onion-key\n"
  22. "-----BEGIN RSA PUBLIC KEY-----\n"
  23. "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
  24. "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
  25. "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
  26. "-----END RSA PUBLIC KEY-----\n";
  27. static const char test_md2[] =
  28. "onion-key\n"
  29. "-----BEGIN RSA PUBLIC KEY-----\n"
  30. "MIGJAoGBAMIixIowh2DyPmDNMDwBX2DHcYcqdcH1zdIQJZkyV6c6rQHnvbcaDoSg\n"
  31. "jgFSLJKpnGmh71FVRqep+yVB0zI1JY43kuEnXry2HbZCD9UDo3d3n7t015X5S7ON\n"
  32. "bSSYtQGPwOr6Epf96IF6DoQxy4iDnPUAlejuhAG51s1y6/rZQ3zxAgMBAAE=\n"
  33. "-----END RSA PUBLIC KEY-----\n";
  34. static const char test_md3[] =
  35. "@last-listed 2009-06-22\n"
  36. "onion-key\n"
  37. "-----BEGIN RSA PUBLIC KEY-----\n"
  38. "MIGJAoGBAMH3340d4ENNGrqx7UxT+lB7x6DNUKOdPEOn4teceE11xlMyZ9TPv41c\n"
  39. "qj2fRZzfxlc88G/tmiaHshmdtEpklZ740OFqaaJVj4LjPMKFNE+J7Xc1142BE9Ci\n"
  40. "KgsbjGYe2RY261aADRWLetJ8T9QDMm+JngL4288hc8pq1uB/3TAbAgMBAAE=\n"
  41. "-----END RSA PUBLIC KEY-----\n"
  42. "p accept 1-700,800-1000\n"
  43. "family nodeX nodeY nodeZ\n";
  44. static void
  45. test_md_cache(void *data)
  46. {
  47. or_options_t *options = NULL;
  48. microdesc_cache_t *mc = NULL ;
  49. smartlist_t *added = NULL, *wanted = NULL;
  50. microdesc_t *md1, *md2, *md3;
  51. char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN];
  52. const char *test_md3_noannotation = strchr(test_md3, '\n')+1;
  53. time_t time1, time2, time3;
  54. char *fn = NULL, *s = NULL;
  55. (void)data;
  56. options = get_options_mutable();
  57. tt_assert(options);
  58. time1 = time(NULL);
  59. time2 = time(NULL) - 2*24*60*60;
  60. time3 = time(NULL) - 15*24*60*60;
  61. /* Possibly, turn this into a test setup/cleanup pair */
  62. tor_free(options->DataDirectory);
  63. options->DataDirectory = tor_strdup(get_fname("md_datadir_test"));
  64. #ifdef _WIN32
  65. tt_int_op(0, ==, mkdir(options->DataDirectory));
  66. #else
  67. tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
  68. #endif
  69. tt_assert(!strcmpstart(test_md3_noannotation, "onion-key"));
  70. crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256);
  71. crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256);
  72. crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation),
  73. DIGEST_SHA256);
  74. mc = get_microdesc_cache();
  75. added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0,
  76. time1, NULL);
  77. tt_int_op(1, ==, smartlist_len(added));
  78. md1 = smartlist_get(added, 0);
  79. smartlist_free(added);
  80. added = NULL;
  81. wanted = smartlist_new();
  82. added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
  83. time2, wanted);
  84. /* Should fail, since we didn't list test_md2's digest in wanted */
  85. tt_int_op(0, ==, smartlist_len(added));
  86. smartlist_free(added);
  87. added = NULL;
  88. smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN));
  89. smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN));
  90. added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
  91. time2, wanted);
  92. /* Now it can work. md2 should have been added */
  93. tt_int_op(1, ==, smartlist_len(added));
  94. md2 = smartlist_get(added, 0);
  95. /* And it should have gotten removed from 'wanted' */
  96. tt_int_op(smartlist_len(wanted), ==, 1);
  97. tt_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN);
  98. smartlist_free(added);
  99. added = NULL;
  100. added = microdescs_add_to_cache(mc, test_md3, NULL,
  101. SAVED_NOWHERE, 0, -1, NULL);
  102. /* Must fail, since SAVED_NOWHERE precludes annotations */
  103. tt_int_op(0, ==, smartlist_len(added));
  104. smartlist_free(added);
  105. added = NULL;
  106. added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
  107. SAVED_NOWHERE, 0, time3, NULL);
  108. /* Now it can work */
  109. tt_int_op(1, ==, smartlist_len(added));
  110. md3 = smartlist_get(added, 0);
  111. smartlist_free(added);
  112. added = NULL;
  113. /* Okay. We added 1...3. Let's poke them to see how they look, and make
  114. * sure they're really in the journal. */
  115. tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
  116. tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
  117. tt_ptr_op(md3, ==, microdesc_cache_lookup_by_digest256(mc, d3));
  118. tt_int_op(md1->last_listed, ==, time1);
  119. tt_int_op(md2->last_listed, ==, time2);
  120. tt_int_op(md3->last_listed, ==, time3);
  121. tt_int_op(md1->saved_location, ==, SAVED_IN_JOURNAL);
  122. tt_int_op(md2->saved_location, ==, SAVED_IN_JOURNAL);
  123. tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL);
  124. tt_int_op(md1->bodylen, ==, strlen(test_md1));
  125. tt_int_op(md2->bodylen, ==, strlen(test_md2));
  126. tt_int_op(md3->bodylen, ==, strlen(test_md3_noannotation));
  127. tt_mem_op(md1->body, ==, test_md1, strlen(test_md1));
  128. tt_mem_op(md2->body, ==, test_md2, strlen(test_md2));
  129. tt_mem_op(md3->body, ==, test_md3_noannotation,
  130. strlen(test_md3_noannotation));
  131. tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new",
  132. options->DataDirectory);
  133. s = read_file_to_str(fn, RFTS_BIN, NULL);
  134. tt_assert(s);
  135. tt_mem_op(md1->body, ==, s + md1->off, md1->bodylen);
  136. tt_mem_op(md2->body, ==, s + md2->off, md2->bodylen);
  137. tt_mem_op(md3->body, ==, s + md3->off, md3->bodylen);
  138. tt_ptr_op(md1->family, ==, NULL);
  139. tt_ptr_op(md3->family, !=, NULL);
  140. tt_int_op(smartlist_len(md3->family), ==, 3);
  141. tt_str_op(smartlist_get(md3->family, 0), ==, "nodeX");
  142. /* Now rebuild the cache! */
  143. tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
  144. tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE);
  145. tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE);
  146. tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE);
  147. /* The journal should be empty now */
  148. tor_free(s);
  149. s = read_file_to_str(fn, RFTS_BIN, NULL);
  150. tt_str_op(s, ==, "");
  151. tor_free(s);
  152. tor_free(fn);
  153. /* read the cache. */
  154. tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
  155. options->DataDirectory);
  156. s = read_file_to_str(fn, RFTS_BIN, NULL);
  157. tt_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
  158. tt_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
  159. tt_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
  160. /* Okay, now we are going to forget about the cache entirely, and reload it
  161. * from the disk. */
  162. microdesc_free_all();
  163. mc = get_microdesc_cache();
  164. md1 = microdesc_cache_lookup_by_digest256(mc, d1);
  165. md2 = microdesc_cache_lookup_by_digest256(mc, d2);
  166. md3 = microdesc_cache_lookup_by_digest256(mc, d3);
  167. tt_assert(md1);
  168. tt_assert(md2);
  169. tt_assert(md3);
  170. tt_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
  171. tt_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
  172. tt_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
  173. tt_int_op(md1->last_listed, ==, time1);
  174. tt_int_op(md2->last_listed, ==, time2);
  175. tt_int_op(md3->last_listed, ==, time3);
  176. /* Okay, now we are going to clear out everything older than a week old.
  177. * In practice, that means md3 */
  178. microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/);
  179. tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
  180. tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
  181. tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
  182. md3 = NULL; /* it's history now! */
  183. /* rebuild again, make sure it stays gone. */
  184. tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
  185. tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
  186. tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
  187. tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
  188. /* Re-add md3, and make sure we can rebuild the cache. */
  189. added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
  190. SAVED_NOWHERE, 0, time3, NULL);
  191. tt_int_op(1, ==, smartlist_len(added));
  192. md3 = smartlist_get(added, 0);
  193. smartlist_free(added);
  194. added = NULL;
  195. tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE);
  196. tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE);
  197. tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL);
  198. tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
  199. tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE);
  200. done:
  201. if (options)
  202. tor_free(options->DataDirectory);
  203. microdesc_free_all();
  204. smartlist_free(added);
  205. if (wanted)
  206. SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
  207. smartlist_free(wanted);
  208. tor_free(s);
  209. tor_free(fn);
  210. }
  211. static const char truncated_md[] =
  212. "@last-listed 2013-08-08 19:02:59\n"
  213. "onion-key\n"
  214. "-----BEGIN RSA PUBLIC KEY-----\n"
  215. "MIGJAoGBAM91vLFNaM+gGhnRIdz2Cm/Kl7Xz0cOobIdVzhS3cKUJfk867hCuTipS\n"
  216. "NveLBzNopvgXKruAAzEj3cACxk6Q8lv5UWOGCD1UolkgsWSE62RBjap44g+oc9J1\n"
  217. "RI9968xOTZw0VaBQg9giEILNXl0djoikQ+5tQRUvLDDa67gpa5Q1AgMBAAE=\n"
  218. "-----END RSA PUBLIC KEY-----\n"
  219. "family @\n";
  220. static void
  221. test_md_cache_broken(void *data)
  222. {
  223. or_options_t *options;
  224. char *fn=NULL;
  225. microdesc_cache_t *mc = NULL;
  226. (void)data;
  227. options = get_options_mutable();
  228. tt_assert(options);
  229. tor_free(options->DataDirectory);
  230. options->DataDirectory = tor_strdup(get_fname("md_datadir_test2"));
  231. #ifdef _WIN32
  232. tt_int_op(0, ==, mkdir(options->DataDirectory));
  233. #else
  234. tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
  235. #endif
  236. tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
  237. options->DataDirectory);
  238. write_str_to_file(fn, truncated_md, 1);
  239. mc = get_microdesc_cache();
  240. tt_assert(mc);
  241. done:
  242. if (options)
  243. tor_free(options->DataDirectory);
  244. tor_free(fn);
  245. microdesc_free_all();
  246. }
  247. /* Generated by chutney. */
  248. static const char test_ri[] =
  249. "router test005r 127.0.0.1 5005 0 7005\n"
  250. "platform Tor 0.2.5.4-alpha-dev on Linux\n"
  251. "protocols Link 1 2 Circuit 1\n"
  252. "published 2014-05-06 22:57:55\n"
  253. "fingerprint 09DE 3BA2 48C2 1C3F 3760 6CD3 8460 43A6 D5EC F59E\n"
  254. "uptime 0\n"
  255. "bandwidth 1073741824 1073741824 0\n"
  256. "extra-info-digest 361F9428F9FA4DD854C03DDBCC159D0D9FA996C9\n"
  257. "onion-key\n"
  258. "-----BEGIN RSA PUBLIC KEY-----\n"
  259. "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
  260. "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
  261. "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
  262. "-----END RSA PUBLIC KEY-----\n"
  263. "signing-key\n"
  264. "-----BEGIN RSA PUBLIC KEY-----\n"
  265. "MIGJAoGBANbGUC4802Ke6C3nOVxN0U0HhIRrs32cQFEL4v+UUMJPgjbistHBvOax\n"
  266. "CWVR/sMXM2kKJeGThJ9ZUs2p9dDG4WHPUXgkMqzTTEeeFa7pQKU0brgbmLaJq0Pi\n"
  267. "mxmqC5RkTHa5bQvq6QlSFprAEoovV27cWqBM9jVdV9hyc//6kwPzAgMBAAE=\n"
  268. "-----END RSA PUBLIC KEY-----\n"
  269. "hidden-service-dir\n"
  270. "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n"
  271. "reject *:25\n"
  272. "reject *:119\n"
  273. "reject *:135-139\n"
  274. "reject *:445\n"
  275. "reject *:563\n"
  276. "reject *:1214\n"
  277. "reject *:4661-4666\n"
  278. "reject *:6346-6429\n"
  279. "reject *:6699\n"
  280. "reject *:6881-6999\n"
  281. "accept *:*\n"
  282. "router-signature\n"
  283. "-----BEGIN SIGNATURE-----\n"
  284. "ImzX5PF2vRCrG1YzGToyjoxYhgh1vtHEDjmP+tIS/iil1DSnHZNpHSuHp0L1jE9S\n"
  285. "yZyrtKaqpBE/aecAM3j4CWCn/ipnAAQkHcyRLin1bYvqBtRzyopVCRlUhF+uWrLq\n"
  286. "t0xkIE39ss/EwmQr7iIgkdVH4oRIMsjYnFFJBG26nYY=\n"
  287. "-----END SIGNATURE-----\n";
  288. static const char test_md_8[] =
  289. "onion-key\n"
  290. "-----BEGIN RSA PUBLIC KEY-----\n"
  291. "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
  292. "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
  293. "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
  294. "-----END RSA PUBLIC KEY-----\n"
  295. "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n";
  296. static const char test_md_16[] =
  297. "onion-key\n"
  298. "-----BEGIN RSA PUBLIC KEY-----\n"
  299. "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
  300. "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
  301. "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
  302. "-----END RSA PUBLIC KEY-----\n"
  303. "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n"
  304. "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n";
  305. static const char test_md_18[] =
  306. "onion-key\n"
  307. "-----BEGIN RSA PUBLIC KEY-----\n"
  308. "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
  309. "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
  310. "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
  311. "-----END RSA PUBLIC KEY-----\n"
  312. "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n"
  313. "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
  314. "id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4\n";
  315. static void
  316. test_md_generate(void *arg)
  317. {
  318. routerinfo_t *ri;
  319. microdesc_t *md = NULL;
  320. (void)arg;
  321. ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL);
  322. tt_assert(ri);
  323. md = dirvote_create_microdescriptor(ri, 8);
  324. tt_str_op(md->body, ==, test_md_8);
  325. /* XXXX test family lines. */
  326. /* XXXX test method 14 for A lines. */
  327. /* XXXX test method 15 for P6 lines. */
  328. microdesc_free(md);
  329. md = NULL;
  330. md = dirvote_create_microdescriptor(ri, 16);
  331. tt_str_op(md->body, ==, test_md_16);
  332. microdesc_free(md);
  333. md = NULL;
  334. md = dirvote_create_microdescriptor(ri, 18);
  335. tt_str_op(md->body, ==, test_md_18);
  336. done:
  337. microdesc_free(md);
  338. routerinfo_free(ri);
  339. }
  340. /* Taken at random from my ~/.tor/cached-microdescs file and then
  341. * hand-munged */
  342. static const char MD_PARSE_TEST_DATA[] =
  343. /* Good 0 */
  344. "onion-key\n"
  345. "-----BEGIN RSA PUBLIC KEY-----\n"
  346. "MIGJAoGBANsKd1GRfOuSR1MkcwKqs6SVy4Gi/JXplt/bHDkIGm6Q96TeJ5uyVgUL\n"
  347. "DBr/ij6+JqgVFeriuiMzHKREytzjdaTuKsKBFFpLwb+Ppcjr5nMIH/AR6/aHO8hW\n"
  348. "T3B9lx5T6Kl7CqZ4yqXxYRHzn50EPTIZuz0y9se4J4gi9mLmL+pHAgMBAAE=\n"
  349. "-----END RSA PUBLIC KEY-----\n"
  350. "p accept 20-23,43,53,79-81,88,110,143,194,220,443,464,531,543-544\n"
  351. "id rsa1024 GEo59/iR1GWSIWZDzXTd5QxtqnU\n"
  352. /* Bad 0: I've messed with the onion-key in the second one. */
  353. "onion-key\n"
  354. "-----BEGIN RSA PUBLIC KEY-----\n"
  355. "MIGJAoGBAMr4o/pflVwscx11vC1AKEADlKEqnhpvCIjAEzNEenMhvGQHRlA0EXLC\n"
  356. "7G7O5bhnCwEHqK8Pvg8cuX/fD8v08TF1EVPhwPa0UI6ab8KnPP2F!!!!!!b92DG7EQIk3q\n"
  357. "d68Uxp7E9/t3v1WWZjzDqvEe0par6ul+DKW6HMlTGebFo5Q4e8R1AgMBAAE=\n"
  358. "-----END RSA PUBLIC KEY-----\n"
  359. "ntor-onion-key 761Dmm27via7lXygNHM3l+oJLrYU2Nye0Uz4pkpipyY=\n"
  360. "p accept 53\n"
  361. "id rsa1024 3Y4fwXhtgkdGDZ5ef5mtb6TJRQQ\n"
  362. /* Good 1 */
  363. "onion-key\n"
  364. "-----BEGIN RSA PUBLIC KEY-----\n"
  365. "MIGJAoGBANsMSjVi3EX8ZHfm/dvPF6KdVR66k1tVul7Jp+dDbDajBYNhgKRzVCxy\n"
  366. "Yac1CBuQjOqK89tKap9PQBnhF087eDrfaZDqYTLwB2W2sBJncVej15WEPXPRBifo\n"
  367. "iFZ8337kgczkaY+IOfSuhtbOUyDOoDpRJheIKBNq0ZiTqtLbbadVAgMBAAE=\n"
  368. "-----END RSA PUBLIC KEY-----\n"
  369. "ntor-onion-key ncfiHJjSgdDEW/gc6q6/7idac7j+x7ejQrRm6i75pGA=\n"
  370. "p accept 443,6660-6669,6697,7000-7001\n"
  371. "id rsa1024 XXuLzw3mfBELEq3veXoNhdehwD4\n"
  372. /* Good 2 */
  373. "onion-key\n"
  374. "-----BEGIN RSA PUBLIC KEY-----\n"
  375. "MIGJAoGBANQfBlrHrh9F/CAOytrNFgi0ikWMW/HZxuoszF9X+AQ+MudR8bcxxOGl\n"
  376. "1RFwb74s8E3uuzrCkNFvSw9Ar1L02F2DOX0gLsxEGuYC4Ave9NUteGqSqDyEJQUJ\n"
  377. "KlfxCPn2qC9nvNT7wR/Dg2WRvAEKnJmkpb57N3+WSAOPLjKOFEz3AgMBAAE=\n"
  378. "-----END RSA PUBLIC KEY-----\n"
  379. "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
  380. "id rsa1024 6y60AEI9a1PUUlRPO0YQT9WzrjI\n"
  381. /* Bad 1: Here I've messed with the ntor key */
  382. "onion-key\n"
  383. "-----BEGIN RSA PUBLIC KEY-----\n"
  384. "MIGJAoGBAPjy2HacU3jDNO5nTOFGSwNa0qKCNn4yhtrDVcAJ5alIQeBWZZGJLZ0q\n"
  385. "Cqylw1vYqxu8E09g+QXXFbAgBv1U9TICaATxrIJhIJzc8TJPhqJemp1kq0DvHLDx\n"
  386. "mxwlkNnCD/P5NS+JYB3EjOlU9EnSKUWNU61+Co344m2JqhEau40vAgMBAAE=\n"
  387. "-----END RSA PUBLIC KEY-----\n"
  388. "ntor-onion-key 4i2Fp9JHTUr1uQs0pxD5j5spl4/RG56S2P0gQxU=\n"
  389. "id rsa1024 nMRmNEGysA0NmlALVaUmI7D5jLU\n"
  390. /* Good 3: I've added a weird token in this one. This shouldn't prevent
  391. * it parsing */
  392. "onion-key\n"
  393. "-----BEGIN RSA PUBLIC KEY-----\n"
  394. "MIGJAoGBAKmosxudyNA/yJNz3S890VqV/ebylzoD11Sc0b/d5tyNNaNZjcYy5vRD\n"
  395. "kwyxFRMbP2TLZQ1zRfNwY7IDnYjU2SbW0pxuM6M8WRtsmx/YOE3kHMVAFJNrTUqU\n"
  396. "6D1zB3IiRDS5q5+NoRxwqo+hYUck60O3WTwEoqb+l3lvXeu7z9rFAgMBAAE=\n"
  397. "-----END RSA PUBLIC KEY-----\n"
  398. "flux-capacitor 1.21 GW\n"
  399. "ntor-onion-key MWBoEkl+RlBiGX44XKIvTSqbznTNZStOmUYtcYRQQyY=\n"
  400. "id rsa1024 R+A5O9qRvRac4FT3C4L2QnFyxsc\n"
  401. /* Good 4: Here I've made the 'id rsa' token odd. It should still parse
  402. * just fine. */
  403. "onion-key\n"
  404. "-----BEGIN RSA PUBLIC KEY-----\n"
  405. "MIGJAoGBAOh+WMkdNe/Pkjb8UjQyfLOlFgpuVFrxAIGnJsmWWx0yBE97DQxGyh2n\n"
  406. "h8G5OJZHRarJQyCIf7vpZQAi0oP0OkGGaCaDQsM+D8TnqhnU++RWGnMqY/cXxPrL\n"
  407. "MEq+n6aGiLmzkO7ah8yorZpoREk4GqLUIN89/tHHGOhJL3c4CPGjAgMBAAE=\n"
  408. "-----END RSA PUBLIC KEY-----\n"
  409. "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
  410. "id rsa1234 jlqAKFD2E7uMKv+8TmKSeo7NBho\n"
  411. /* Good 5: Extra id type. */
  412. "onion-key\n"
  413. "-----BEGIN RSA PUBLIC KEY-----\n"
  414. "MIGJAoGBAMdgPPc5uaw4y/q+SUTN/I8Y+Gvdx9kKgWV4dmDGJ0mxsVZmo1v6+v3F\n"
  415. "12M2f9m99G3WB8F8now29C+9XyEv8MBHj1lHRdUFHSQes3YTFvDNlgj+FjLqO5TJ\n"
  416. "adOOmfu4DCUUtUEDyQKbNVL4EkMTXY73omTVsjcH3xxFjTx5wixhAgMBAAE=\n"
  417. "-----END RSA PUBLIC KEY-----\n"
  418. "ntor-onion-key AAVnWZcnDbxasdZwKqb4fL6O9sZV+XsRNHTpNd1YMz8=\n"
  419. "id rsa1024 72EfBL11QuwX2vU8y+p9ExGfGEg\n"
  420. "id expolding hedgehog 0+A5O9qRvRac4FT3C4L2QnFyxsc\n"
  421. /* Good 6: I've given this a bogus policy. It should parse. */
  422. "onion-key\n"
  423. "-----BEGIN RSA PUBLIC KEY-----\n"
  424. "MIGJAoGBALNuufwhPMF8BooxYMNvhYJMPqUB8hQDt8wGmPKphJcD1sVD1i4gAZM2\n"
  425. "HIo+zUBlljDrRWL5NzVzd1yxUJAiQxvXS5dRRFY3B70M7wTVpXw53xe0/BM5t1AX\n"
  426. "n0MFk7Jl6XIKMlzRalZvmMvE/odtyWXkP4Nd1MyZ1QcIwrQ2iwyrAgMBAAE=\n"
  427. "-----END RSA PUBLIC KEY-----\n"
  428. "p condone 1-10\n"
  429. "ntor-onion-key 2/nMJ+L4dd/2GpMyTYjz3zC59MvQy4MIzJZhdzKHekg=\n"
  430. "id rsa1024 FHyh10glEMA6MCmBb5R9Y+X/MhQ\n"
  431. /* Good 7: I've given this one another sort of odd policy. Should parse. */
  432. "onion-key\n"
  433. "-----BEGIN RSA PUBLIC KEY-----\n"
  434. "MIGJAoGBAKcd3FmQ8iAADghyvX8eca0ePqtJ2w1IDdUdTlf5Y/8+OMdp//sD01yC\n"
  435. "YmiX45LK5ge1O3AzcakYCO6fb3pyIqvXdvm24OjyYZELQ40cmKSLjdhcSf4Fr/N9\n"
  436. "uR/CkknR9cEePu1wZ5WBIGmGdXI6s7t3LB+e7XFyBYAx6wMGlnX7AgMBAAE=\n"
  437. "-----END RSA PUBLIC KEY-----\n"
  438. "p accept frogs-mice\n"
  439. "ntor-onion-key AMxvhaQ1Qg7jBJFoyHuPRgETvLbFmJ194hExV24FuAI=\n"
  440. "family $D8CFEA0D996F5D1473D2063C041B7910DB23981E\n"
  441. "id rsa1024 d0VVZC/cHh1P3y4MMbfKlQHFycc\n"
  442. /* Good 8: This one has the ntor-onion-key without terminating =. That's
  443. * allowed. */
  444. "onion-key\n"
  445. "-----BEGIN RSA PUBLIC KEY-----\n"
  446. "MIGJAoGBAL438YfjrJE2SPqkkXeQwICygu8KNO54Juj6sjqk5hgsiazIWMOBgbaX\n"
  447. "LIRqPNGaiSq01xSqwjwCBCfwZYT/nSdDBqj1h9aoR8rnjxZjyQ+m3rWpdDqeCDMx\n"
  448. "I3NgZ5w4bNX4poRb42lrV6NmQiFdjzpqszVbv5Lpn2CSKu32CwKVAgMBAAE=\n"
  449. "-----END RSA PUBLIC KEY-----\n"
  450. "ntor-onion-key UKL6Dnj2KwYsFlkCvOkXVatxvOPB4MaxqwPQQgZMTwI\n"
  451. "id rsa1024 FPIXc6k++JnKCtSKWUxaR6oXEKs\n"
  452. /* Good 9: Another totally normal one.*/
  453. "onion-key\n"
  454. "-----BEGIN RSA PUBLIC KEY-----\n"
  455. "MIGJAoGBANNGIKRd8PFNXkJ2JPV1ohDMFNbJwKbwybeieaQFjtU9KWedHCbr+QD4\n"
  456. "B6zNY5ysguNjHNnlq2f6D09+uhnfDBON8tAz0mPQH/6JqnOXm+EiUn+8bN0E8Nke\n"
  457. "/i3GEgDeaxJJMNQcpsJvmmSmKFOlYy9Fy7ejAjTGqtAnqOte7BnTAgMBAAE=\n"
  458. "-----END RSA PUBLIC KEY-----\n"
  459. "ntor-onion-key gUsq3e5iYgsQQvyxINtLzBpHxmIt5rtuFlEbKfI4gFk=\n"
  460. "id rsa1024 jv+LdatDzsMfEW6pLBeL/5uzwCc\n"
  461. /* Bad 2: RSA key has bad exponent of 3. */
  462. "onion-key\n"
  463. "-----BEGIN RSA PUBLIC KEY-----\n"
  464. "MIGHAoGBAMMTWtvPxYnUNJ5Y7B+XENcpxzPoGstrdiUszCBS+/42xvluLJ+JDSdR\n"
  465. "qJaMD6ax8vKAeLS5C6O17MNdG2VldlPRbtgl41MXsOoUqEJ+nY9e3WG9Snjp47xC\n"
  466. "zmWIfeduXSavIsb3a43/MLIz/9qO0TkgAAiuQr79JlwKhLdzCqTLAgED\n"
  467. "-----END RSA PUBLIC KEY-----\n"
  468. "ntor-onion-key NkRB4wTUFogiVp5jYmjGORe2ffb/y5Kk8Itw8jdzMjA=\n"
  469. "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
  470. "id rsa1024 fKvYjP7TAjCC1FzYee5bYAwYkoDg\n"
  471. /* Bad 3: Bogus annotation */
  472. "@last-listed with strange aeons\n"
  473. "onion-key\n"
  474. "-----BEGIN RSA PUBLIC KEY-----\n"
  475. "MIGJAoGBALcRBFNCZtpd2TFJysU77/fJMFzKisRQEBOtDGtTZ2Bg4aEGosssa0Id\n"
  476. "YtUagRLYle08QVGvGB+EHBI5qf6Ah2yPH7k5QiN2a3Sq+nyh85dXKPazBGBBbM+C\n"
  477. "DOfDauV02CAnADNMLJEf1voY3oBVvYyIsmHxn5i1R19ZYIiR8NX5AgMBAAE=\n"
  478. "-----END RSA PUBLIC KEY-----\n"
  479. "ntor-onion-key m4xcFXMWMjCvZDXq8FT3XmS0EHYseGOeu+fV+6FYDlk=\n"
  480. "p accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544\n"
  481. "id rsa1024 SSbfNE9vmaiwRKH+eqNAkiKQhds\n"
  482. /* Good 10: Normal, with added ipv6 address and added other address */
  483. "onion-key\n"
  484. "-----BEGIN RSA PUBLIC KEY-----\n"
  485. "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
  486. "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
  487. "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
  488. "-----END RSA PUBLIC KEY-----\n"
  489. "a [::1:2:3:4]:9090\n"
  490. "a 18.0.0.1:9999\n"
  491. "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n"
  492. "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
  493. "p6 allow 80\n"
  494. ;
  495. /** More tests for parsing different kinds of microdescriptors, and getting
  496. * invalid digests trackd from them. */
  497. static void
  498. test_md_parse(void *arg)
  499. {
  500. (void) arg;
  501. char *mem_op_hex_tmp = NULL;
  502. smartlist_t *invalid = smartlist_new();
  503. smartlist_t *mds = microdescs_parse_from_string(MD_PARSE_TEST_DATA,
  504. NULL, 1, SAVED_NOWHERE,
  505. invalid);
  506. tt_int_op(smartlist_len(mds), ==, 11);
  507. tt_int_op(smartlist_len(invalid), ==, 4);
  508. test_memeq_hex(smartlist_get(invalid,0),
  509. "5d76bf1c6614e885614a1e0ad074e1ab"
  510. "4ea14655ebeefb1736a71b5ed8a15a51");
  511. test_memeq_hex(smartlist_get(invalid,1),
  512. "2fde0ee3343669c2444cd9d53cbd39c6"
  513. "a7d1fc0513513e840ca7f6e68864b36c");
  514. test_memeq_hex(smartlist_get(invalid,2),
  515. "20d1576c5ab11bbcff0dedb1db4a3cfc"
  516. "c8bc8dd839d8cbfef92d00a1a7d7b294");
  517. test_memeq_hex(smartlist_get(invalid,3),
  518. "074770f394c73dbde7b44412e9692add"
  519. "691a478d4727f9804b77646c95420a96");
  520. /* Spot-check the valid ones. */
  521. const microdesc_t *md = smartlist_get(mds, 5);
  522. test_memeq_hex(md->digest,
  523. "54bb6d733ddeb375d2456c79ae103961"
  524. "da0cae29620375ac4cf13d54da4d92b3");
  525. tt_int_op(md->last_listed, ==, 0);
  526. tt_int_op(md->saved_location, ==, SAVED_NOWHERE);
  527. tt_int_op(md->no_save, ==, 0);
  528. tt_uint_op(md->held_in_map, ==, 0);
  529. tt_uint_op(md->held_by_nodes, ==, 0);
  530. tt_assert(md->onion_curve25519_pkey);
  531. md = smartlist_get(mds, 6);
  532. test_memeq_hex(md->digest,
  533. "53f740bd222ab37f19f604b1d3759aa6"
  534. "5eff1fbce9ac254bd0fa50d4af9b1bae");
  535. tt_assert(! md->exit_policy);
  536. md = smartlist_get(mds, 8);
  537. test_memeq_hex(md->digest,
  538. "a0a155562d8093d8fd0feb7b93b7226e"
  539. "17f056c2142aab7a4ea8c5867a0376d5");
  540. tt_assert(md->onion_curve25519_pkey);
  541. md = smartlist_get(mds, 10);
  542. test_memeq_hex(md->digest,
  543. "409ebd87d23925a2732bd467a92813c9"
  544. "21ca378fcb9ca193d354c51550b6d5e9");
  545. tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
  546. tt_int_op(md->ipv6_orport, ==, 9090);
  547. done:
  548. SMARTLIST_FOREACH(mds, microdesc_t *, md, microdesc_free(md));
  549. smartlist_free(mds);
  550. SMARTLIST_FOREACH(invalid, char *, cp, tor_free(cp));
  551. smartlist_free(invalid);
  552. tor_free(mem_op_hex_tmp);
  553. }
  554. struct testcase_t microdesc_tests[] = {
  555. { "cache", test_md_cache, TT_FORK, NULL, NULL },
  556. { "broken_cache", test_md_cache_broken, TT_FORK, NULL, NULL },
  557. { "generate", test_md_generate, 0, NULL, NULL },
  558. { "parse", test_md_parse, 0, NULL, NULL },
  559. END_OF_TESTCASES
  560. };