test_hs_common.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* Copyright (c) 2017, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file test_hs_common.c
  5. * \brief Test hidden service common functionalities.
  6. */
  7. #define HS_COMMON_PRIVATE
  8. #define HS_SERVICE_PRIVATE
  9. #include "test.h"
  10. #include "test_helpers.h"
  11. #include "log_test_helpers.h"
  12. #include "hs_test_helpers.h"
  13. #include "hs_common.h"
  14. #include "hs_service.h"
  15. #include "config.h"
  16. /** Test the validation of HS v3 addresses */
  17. static void
  18. test_validate_address(void *arg)
  19. {
  20. int ret;
  21. (void) arg;
  22. /* Address too short and too long. */
  23. setup_full_capture_of_logs(LOG_WARN);
  24. ret = hs_address_is_valid("blah");
  25. tt_int_op(ret, OP_EQ, 0);
  26. expect_log_msg_containing("has an invalid length");
  27. teardown_capture_of_logs();
  28. setup_full_capture_of_logs(LOG_WARN);
  29. ret = hs_address_is_valid(
  30. "p3xnclpu4mu22dwaurjtsybyqk4xfjmcfz6z62yl24uwmhjatiwnlnadb");
  31. tt_int_op(ret, OP_EQ, 0);
  32. expect_log_msg_containing("has an invalid length");
  33. teardown_capture_of_logs();
  34. /* Invalid checksum (taken from prop224) */
  35. setup_full_capture_of_logs(LOG_WARN);
  36. ret = hs_address_is_valid(
  37. "l5satjgud6gucryazcyvyvhuxhr74u6ygigiuyixe3a6ysis67ororad");
  38. tt_int_op(ret, OP_EQ, 0);
  39. expect_log_msg_containing("invalid checksum");
  40. teardown_capture_of_logs();
  41. setup_full_capture_of_logs(LOG_WARN);
  42. ret = hs_address_is_valid(
  43. "btojiu7nu5y5iwut64eufevogqdw4wmqzugnoluw232r4t3ecsfv37ad");
  44. tt_int_op(ret, OP_EQ, 0);
  45. expect_log_msg_containing("invalid checksum");
  46. teardown_capture_of_logs();
  47. /* Non base32 decodable string. */
  48. setup_full_capture_of_logs(LOG_WARN);
  49. ret = hs_address_is_valid(
  50. "????????????????????????????????????????????????????????");
  51. tt_int_op(ret, OP_EQ, 0);
  52. expect_log_msg_containing("can't be decoded");
  53. teardown_capture_of_logs();
  54. /* Valid address. */
  55. ret = hs_address_is_valid(
  56. "p3xnclpu4mu22dwaurjtsybyqk4xfjmcfz6z62yl24uwmhjatiwnlnad");
  57. tt_int_op(ret, OP_EQ, 1);
  58. done:
  59. ;
  60. }
  61. static int
  62. mock_write_str_to_file(const char *path, const char *str, int bin)
  63. {
  64. (void)bin;
  65. tt_str_op(path, OP_EQ, "/double/five/squared");
  66. tt_str_op(str, OP_EQ,
  67. "ijbeeqscijbeeqscijbeeqscijbeeqscijbeeqscijbeeqscijbezhid.onion\n");
  68. done:
  69. return 0;
  70. }
  71. /** Test building HS v3 onion addresses */
  72. static void
  73. test_build_address(void *arg)
  74. {
  75. int ret;
  76. char onion_addr[HS_SERVICE_ADDR_LEN_BASE32 + 1];
  77. ed25519_public_key_t pubkey;
  78. hs_service_t *service = NULL;
  79. (void) arg;
  80. MOCK(write_str_to_file, mock_write_str_to_file);
  81. /* The following has been created with hs_build_address.py script that
  82. * follows proposal 224 specification to build an onion address. */
  83. static const char *test_addr =
  84. "ijbeeqscijbeeqscijbeeqscijbeeqscijbeeqscijbeeqscijbezhid";
  85. /* Let's try to build the same onion address that the script can do. Key is
  86. * a long set of very random \x42 :). */
  87. memset(&pubkey, '\x42', sizeof(pubkey));
  88. hs_build_address(&pubkey, HS_VERSION_THREE, onion_addr);
  89. tt_str_op(test_addr, OP_EQ, onion_addr);
  90. /* Validate that address. */
  91. ret = hs_address_is_valid(onion_addr);
  92. tt_int_op(ret, OP_EQ, 1);
  93. service = tor_malloc_zero(sizeof(hs_service_t));
  94. memcpy(service->onion_address, onion_addr, sizeof(service->onion_address));
  95. tor_asprintf(&service->config.directory_path, "/double/five");
  96. ret = write_address_to_file(service, "squared");
  97. tt_int_op(ret, OP_EQ, 0);
  98. done:
  99. hs_service_free(service);
  100. }
  101. /** Test that our HS time period calculation functions work properly */
  102. static void
  103. test_time_period(void *arg)
  104. {
  105. (void) arg;
  106. uint64_t tn;
  107. int retval;
  108. time_t fake_time;
  109. /* Let's do the example in prop224 section [TIME-PERIODS] */
  110. retval = parse_rfc1123_time("Wed, 13 Apr 2016 11:00:00 UTC",
  111. &fake_time);
  112. tt_int_op(retval, ==, 0);
  113. /* Check that the time period number is right */
  114. tn = hs_get_time_period_num(fake_time);
  115. tt_u64_op(tn, ==, 16903);
  116. /* Increase current time to 11:59:59 UTC and check that the time period
  117. number is still the same */
  118. fake_time += 3599;
  119. tn = hs_get_time_period_num(fake_time);
  120. tt_u64_op(tn, ==, 16903);
  121. /* Now take time to 12:00:00 UTC and check that the time period rotated */
  122. fake_time += 1;
  123. tn = hs_get_time_period_num(fake_time);
  124. tt_u64_op(tn, ==, 16904);
  125. /* Now also check our hs_get_next_time_period_num() function */
  126. tn = hs_get_next_time_period_num(fake_time);
  127. tt_u64_op(tn, ==, 16905);
  128. done:
  129. ;
  130. }
  131. /** Test that we can correctly find the start time of the next time period */
  132. static void
  133. test_start_time_of_next_time_period(void *arg)
  134. {
  135. (void) arg;
  136. int retval;
  137. time_t fake_time;
  138. char tbuf[ISO_TIME_LEN + 1];
  139. time_t next_tp_start_time;
  140. /* Do some basic tests */
  141. retval = parse_rfc1123_time("Wed, 13 Apr 2016 11:00:00 UTC",
  142. &fake_time);
  143. tt_int_op(retval, ==, 0);
  144. next_tp_start_time = hs_get_start_time_of_next_time_period(fake_time);
  145. /* Compare it with the correct result */
  146. format_iso_time(tbuf, next_tp_start_time);
  147. tt_str_op("2016-04-13 12:00:00", OP_EQ, tbuf);
  148. /* Another test with an edge-case time (start of TP) */
  149. retval = parse_rfc1123_time("Wed, 13 Apr 2016 12:00:00 UTC",
  150. &fake_time);
  151. tt_int_op(retval, ==, 0);
  152. next_tp_start_time = hs_get_start_time_of_next_time_period(fake_time);
  153. format_iso_time(tbuf, next_tp_start_time);
  154. tt_str_op("2016-04-14 12:00:00", OP_EQ, tbuf);
  155. {
  156. /* Now pretend we are on a testing network and alter the voting schedule to
  157. be every 10 seconds. This means that a time period has length 10*24
  158. seconds (4 minutes). It also means that we apply a rotational offset of
  159. 120 seconds to the time period, so that it starts at 00:02:00 instead of
  160. 00:00:00. */
  161. or_options_t *options = get_options_mutable();
  162. options->TestingTorNetwork = 1;
  163. options->V3AuthVotingInterval = 10;
  164. options->TestingV3AuthInitialVotingInterval = 10;
  165. retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:00:00 UTC",
  166. &fake_time);
  167. tt_int_op(retval, ==, 0);
  168. next_tp_start_time = hs_get_start_time_of_next_time_period(fake_time);
  169. /* Compare it with the correct result */
  170. format_iso_time(tbuf, next_tp_start_time);
  171. tt_str_op("2016-04-13 00:02:00", OP_EQ, tbuf);
  172. retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:02:00 UTC",
  173. &fake_time);
  174. tt_int_op(retval, ==, 0);
  175. next_tp_start_time = hs_get_start_time_of_next_time_period(fake_time);
  176. /* Compare it with the correct result */
  177. format_iso_time(tbuf, next_tp_start_time);
  178. tt_str_op("2016-04-13 00:06:00", OP_EQ, tbuf);
  179. }
  180. done:
  181. ;
  182. }
  183. /** Test that our HS overlap period functions work properly. */
  184. static void
  185. test_desc_overlap_period(void *arg)
  186. {
  187. (void) arg;
  188. int retval;
  189. time_t now = time(NULL);
  190. networkstatus_t *dummy_consensus = NULL;
  191. /* First try with a consensus just inside the overlap period */
  192. dummy_consensus = tor_malloc_zero(sizeof(networkstatus_t));
  193. retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:00:00 UTC",
  194. &dummy_consensus->valid_after);
  195. tt_int_op(retval, ==, 0);
  196. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  197. tt_int_op(retval, ==, 1);
  198. /* Now increase the valid_after so that it goes to 11:00:00 UTC. Overlap
  199. period is still active. */
  200. dummy_consensus->valid_after += 3600*11;
  201. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  202. tt_int_op(retval, ==, 1);
  203. /* Now increase the valid_after so that it goes to 11:59:59 UTC. Overlap
  204. period is still active. */
  205. dummy_consensus->valid_after += 3599;
  206. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  207. tt_int_op(retval, ==, 1);
  208. /* Now increase the valid_after so that it drifts to noon, and check that
  209. overlap mode is not active anymore. */
  210. dummy_consensus->valid_after += 1;
  211. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  212. tt_int_op(retval, ==, 0);
  213. /* Check that overlap mode is also inactive at 23:59:59 UTC */
  214. retval = parse_rfc1123_time("Wed, 13 Apr 2016 23:59:59 UTC",
  215. &dummy_consensus->valid_after);
  216. tt_int_op(retval, ==, 0);
  217. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  218. tt_int_op(retval, ==, 0);
  219. done:
  220. tor_free(dummy_consensus);
  221. }
  222. /* Test the overlap period functions on a testnet with altered voting
  223. * schedule */
  224. static void
  225. test_desc_overlap_period_testnet(void *arg)
  226. {
  227. int retval;
  228. time_t now = approx_time();
  229. networkstatus_t *dummy_consensus = NULL;
  230. or_options_t *options = get_options_mutable();
  231. (void) arg;
  232. /* Set the testnet option and a 10-second voting interval */
  233. options->TestingTorNetwork = 1;
  234. options->V3AuthVotingInterval = 10;
  235. options->TestingV3AuthInitialVotingInterval = 10;
  236. dummy_consensus = tor_malloc_zero(sizeof(networkstatus_t));
  237. /* A 10-second voting interval means that the lengths of an SRV run and of a
  238. * time period are both 10*24 seconds (4 minutes). The SRV gets published at
  239. * 00:00:00 and the TP starts at 00:02:00 (rotation offset: 2 mins). Those
  240. * two minutes between SRV publish and TP start is the overlap period
  241. * window. Let's test it: */
  242. retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:00:00 UTC",
  243. &dummy_consensus->valid_after);
  244. tt_int_op(retval, ==, 0);
  245. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  246. tt_int_op(retval, ==, 1);
  247. retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:01:59 UTC",
  248. &dummy_consensus->valid_after);
  249. tt_int_op(retval, ==, 0);
  250. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  251. tt_int_op(retval, ==, 1);
  252. retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:02:00 UTC",
  253. &dummy_consensus->valid_after);
  254. tt_int_op(retval, ==, 0);
  255. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  256. tt_int_op(retval, ==, 0);
  257. retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:04:00 UTC",
  258. &dummy_consensus->valid_after);
  259. tt_int_op(retval, ==, 0);
  260. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  261. tt_int_op(retval, ==, 1);
  262. retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:05:59 UTC",
  263. &dummy_consensus->valid_after);
  264. tt_int_op(retval, ==, 0);
  265. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  266. tt_int_op(retval, ==, 1);
  267. retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:06:00 UTC",
  268. &dummy_consensus->valid_after);
  269. tt_int_op(retval, ==, 0);
  270. retval = hs_overlap_mode_is_active(dummy_consensus, now);
  271. tt_int_op(retval, ==, 0);
  272. done:
  273. tor_free(dummy_consensus);
  274. }
  275. struct testcase_t hs_common_tests[] = {
  276. { "build_address", test_build_address, TT_FORK,
  277. NULL, NULL },
  278. { "validate_address", test_validate_address, TT_FORK,
  279. NULL, NULL },
  280. { "time_period", test_time_period, TT_FORK,
  281. NULL, NULL },
  282. { "start_time_of_next_time_period", test_start_time_of_next_time_period,
  283. TT_FORK, NULL, NULL },
  284. { "desc_overlap_period", test_desc_overlap_period, TT_FORK,
  285. NULL, NULL },
  286. { "desc_overlap_period_testnet", test_desc_overlap_period_testnet, TT_FORK,
  287. NULL, NULL },
  288. END_OF_TESTCASES
  289. };