test_cell_formats.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /* Copyright (c) 2001-2004, Roger Dingledine.
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2012, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #include "orconfig.h"
  6. #define CONNECTION_EDGE_PRIVATE
  7. #define RELAY_PRIVATE
  8. #include "or.h"
  9. #include "connection_edge.h"
  10. #include "relay.h"
  11. #include "test.h"
  12. #include <stdlib.h>
  13. #include <string.h>
  14. static void
  15. test_cfmt_relay_header(void *arg)
  16. {
  17. relay_header_t rh;
  18. const uint8_t hdr_1[RELAY_HEADER_SIZE] =
  19. "\x03" "\x00\x00" "\x21\x22" "ABCD" "\x01\x03";
  20. uint8_t hdr_out[RELAY_HEADER_SIZE];
  21. (void)arg;
  22. tt_int_op(sizeof(hdr_1), ==, RELAY_HEADER_SIZE);
  23. relay_header_unpack(&rh, hdr_1);
  24. tt_int_op(rh.command, ==, 3);
  25. tt_int_op(rh.recognized, ==, 0);
  26. tt_int_op(rh.stream_id, ==, 0x2122);
  27. test_mem_op(rh.integrity, ==, "ABCD", 4);
  28. tt_int_op(rh.length, ==, 0x103);
  29. relay_header_pack(hdr_out, &rh);
  30. test_mem_op(hdr_out, ==, hdr_1, RELAY_HEADER_SIZE);
  31. done:
  32. ;
  33. }
  34. static void
  35. make_relay_cell(cell_t *out, uint8_t command,
  36. const void *body, size_t bodylen)
  37. {
  38. relay_header_t rh;
  39. memset(&rh, 0, sizeof(rh));
  40. rh.stream_id = 5;
  41. rh.command = command;
  42. rh.length = bodylen;
  43. out->command = CELL_RELAY;
  44. out->circ_id = 10;
  45. relay_header_pack(out->payload, &rh);
  46. memcpy(out->payload + RELAY_HEADER_SIZE, body, bodylen);
  47. }
  48. static void
  49. test_cfmt_begin_cells(void *arg)
  50. {
  51. cell_t cell;
  52. begin_cell_t bcell;
  53. uint8_t end_reason;
  54. (void)arg;
  55. /* Try begindir. */
  56. memset(&bcell, 0x7f, sizeof(bcell));
  57. make_relay_cell(&cell, RELAY_COMMAND_BEGIN_DIR, "", 0);
  58. tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  59. tt_ptr_op(NULL, ==, bcell.address);
  60. tt_int_op(0, ==, bcell.flags);
  61. tt_int_op(0, ==, bcell.port);
  62. tt_int_op(5, ==, bcell.stream_id);
  63. tt_int_op(1, ==, bcell.is_begindir);
  64. /* A Begindir with extra stuff. */
  65. memset(&bcell, 0x7f, sizeof(bcell));
  66. make_relay_cell(&cell, RELAY_COMMAND_BEGIN_DIR, "12345", 5);
  67. tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  68. tt_ptr_op(NULL, ==, bcell.address);
  69. tt_int_op(0, ==, bcell.flags);
  70. tt_int_op(0, ==, bcell.port);
  71. tt_int_op(5, ==, bcell.stream_id);
  72. tt_int_op(1, ==, bcell.is_begindir);
  73. /* A short but valid begin cell */
  74. memset(&bcell, 0x7f, sizeof(bcell));
  75. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:9", 6);
  76. tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  77. tt_str_op("a.b", ==, bcell.address);
  78. tt_int_op(0, ==, bcell.flags);
  79. tt_int_op(9, ==, bcell.port);
  80. tt_int_op(5, ==, bcell.stream_id);
  81. tt_int_op(0, ==, bcell.is_begindir);
  82. tor_free(bcell.address);
  83. /* A significantly loner begin cell */
  84. memset(&bcell, 0x7f, sizeof(bcell));
  85. {
  86. const char c[] = "here-is-a-nice-long.hostname.com:65535";
  87. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, strlen(c)+1);
  88. }
  89. tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  90. tt_str_op("here-is-a-nice-long.hostname.com", ==, bcell.address);
  91. tt_int_op(0, ==, bcell.flags);
  92. tt_int_op(65535, ==, bcell.port);
  93. tt_int_op(5, ==, bcell.stream_id);
  94. tt_int_op(0, ==, bcell.is_begindir);
  95. tor_free(bcell.address);
  96. /* An IPv4 begin cell. */
  97. memset(&bcell, 0x7f, sizeof(bcell));
  98. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "18.9.22.169:80", 15);
  99. tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  100. tt_str_op("18.9.22.169", ==, bcell.address);
  101. tt_int_op(0, ==, bcell.flags);
  102. tt_int_op(80, ==, bcell.port);
  103. tt_int_op(5, ==, bcell.stream_id);
  104. tt_int_op(0, ==, bcell.is_begindir);
  105. tor_free(bcell.address);
  106. /* An IPv6 begin cell. Let's make sure we handle colons*/
  107. memset(&bcell, 0x7f, sizeof(bcell));
  108. make_relay_cell(&cell, RELAY_COMMAND_BEGIN,
  109. "[2620::6b0:b:1a1a:0:26e5:480e]:80", 34);
  110. tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  111. tt_str_op("[2620::6b0:b:1a1a:0:26e5:480e]", ==, bcell.address);
  112. tt_int_op(0, ==, bcell.flags);
  113. tt_int_op(80, ==, bcell.port);
  114. tt_int_op(5, ==, bcell.stream_id);
  115. tt_int_op(0, ==, bcell.is_begindir);
  116. tor_free(bcell.address);
  117. /* a begin cell with extra junk but not enough for flags. */
  118. memset(&bcell, 0x7f, sizeof(bcell));
  119. {
  120. const char c[] = "another.example.com:80\x00\x01\x02";
  121. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1);
  122. }
  123. tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  124. tt_str_op("another.example.com", ==, bcell.address);
  125. tt_int_op(0, ==, bcell.flags);
  126. tt_int_op(80, ==, bcell.port);
  127. tt_int_op(5, ==, bcell.stream_id);
  128. tt_int_op(0, ==, bcell.is_begindir);
  129. tor_free(bcell.address);
  130. /* a begin cell with flags. */
  131. memset(&bcell, 0x7f, sizeof(bcell));
  132. {
  133. const char c[] = "another.example.com:443\x00\x01\x02\x03\x04";
  134. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1);
  135. }
  136. tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  137. tt_str_op("another.example.com", ==, bcell.address);
  138. tt_int_op(0x1020304, ==, bcell.flags);
  139. tt_int_op(443, ==, bcell.port);
  140. tt_int_op(5, ==, bcell.stream_id);
  141. tt_int_op(0, ==, bcell.is_begindir);
  142. tor_free(bcell.address);
  143. /* a begin cell with flags and even more cruft after that. */
  144. memset(&bcell, 0x7f, sizeof(bcell));
  145. {
  146. const char c[] = "a-further.example.com:22\x00\xee\xaa\x00\xffHi mom";
  147. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1);
  148. }
  149. tt_int_op(0, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  150. tt_str_op("a-further.example.com", ==, bcell.address);
  151. tt_int_op(0xeeaa00ff, ==, bcell.flags);
  152. tt_int_op(22, ==, bcell.port);
  153. tt_int_op(5, ==, bcell.stream_id);
  154. tt_int_op(0, ==, bcell.is_begindir);
  155. tor_free(bcell.address);
  156. /* bad begin cell: impossible length. */
  157. memset(&bcell, 0x7f, sizeof(bcell));
  158. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 7);
  159. cell.payload[9] = 0x01; /* Set length to 510 */
  160. cell.payload[10] = 0xfe;
  161. {
  162. relay_header_t rh;
  163. relay_header_unpack(&rh, cell.payload);
  164. tt_int_op(rh.length, ==, 510);
  165. }
  166. tt_int_op(-2, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  167. /* Bad begin cell: no body. */
  168. memset(&bcell, 0x7f, sizeof(bcell));
  169. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "", 0);
  170. tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  171. /* bad begin cell: no body. */
  172. memset(&bcell, 0x7f, sizeof(bcell));
  173. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "", 0);
  174. tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  175. /* bad begin cell: no colon */
  176. memset(&bcell, 0x7f, sizeof(bcell));
  177. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b", 4);
  178. tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  179. /* bad begin cell: no ports */
  180. memset(&bcell, 0x7f, sizeof(bcell));
  181. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:", 5);
  182. tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  183. /* bad begin cell: bad port */
  184. memset(&bcell, 0x7f, sizeof(bcell));
  185. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:xyz", 8);
  186. tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  187. memset(&bcell, 0x7f, sizeof(bcell));
  188. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:100000", 11);
  189. tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  190. /* bad begin cell: no nul */
  191. memset(&bcell, 0x7f, sizeof(bcell));
  192. make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 6);
  193. tt_int_op(-1, ==, begin_cell_parse(&cell, &bcell, &end_reason));
  194. done:
  195. tor_free(bcell.address);
  196. }
  197. static void
  198. test_cfmt_connected_cells(void *arg)
  199. {
  200. relay_header_t rh;
  201. cell_t cell;
  202. tor_addr_t addr;
  203. int ttl, r;
  204. (void)arg;
  205. /* Let's try an oldschool one with nothing in it. */
  206. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "", 0);
  207. relay_header_unpack(&rh, cell.payload);
  208. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  209. tt_int_op(r, ==, 0);
  210. tt_int_op(tor_addr_family(&addr), ==, AF_UNSPEC);
  211. tt_int_op(ttl, ==, -1);
  212. /* A slightly less oldschool one: only an IPv4 address */
  213. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x20\x30\x40\x50", 4);
  214. relay_header_unpack(&rh, cell.payload);
  215. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  216. tt_int_op(r, ==, 0);
  217. tt_int_op(tor_addr_family(&addr), ==, AF_INET);
  218. tt_str_op(fmt_addr(&addr), ==, "32.48.64.80");
  219. tt_int_op(ttl, ==, -1);
  220. /* Bogus but understandable: truncated TTL */
  221. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x11\x12\x13\x14\x15", 5);
  222. relay_header_unpack(&rh, cell.payload);
  223. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  224. tt_int_op(r, ==, 0);
  225. tt_int_op(tor_addr_family(&addr), ==, AF_INET);
  226. tt_str_op(fmt_addr(&addr), ==, "17.18.19.20");
  227. tt_int_op(ttl, ==, -1);
  228. /* Regular IPv4 one: address and TTL */
  229. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
  230. "\x02\x03\x04\x05\x00\x00\x0e\x10", 8);
  231. relay_header_unpack(&rh, cell.payload);
  232. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  233. tt_int_op(r, ==, 0);
  234. tt_int_op(tor_addr_family(&addr), ==, AF_INET);
  235. tt_str_op(fmt_addr(&addr), ==, "2.3.4.5");
  236. tt_int_op(ttl, ==, 3600);
  237. /* IPv4 with too-big TTL */
  238. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
  239. "\x02\x03\x04\x05\xf0\x00\x00\x00", 8);
  240. relay_header_unpack(&rh, cell.payload);
  241. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  242. tt_int_op(r, ==, 0);
  243. tt_int_op(tor_addr_family(&addr), ==, AF_INET);
  244. tt_str_op(fmt_addr(&addr), ==, "2.3.4.5");
  245. tt_int_op(ttl, ==, -1);
  246. /* IPv6 (ttl is mandatory) */
  247. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
  248. "\x00\x00\x00\x00\x06"
  249. "\x26\x07\xf8\xb0\x40\x0c\x0c\x02"
  250. "\x00\x00\x00\x00\x00\x00\x00\x68"
  251. "\x00\x00\x02\x58", 25);
  252. relay_header_unpack(&rh, cell.payload);
  253. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  254. tt_int_op(r, ==, 0);
  255. tt_int_op(tor_addr_family(&addr), ==, AF_INET6);
  256. tt_str_op(fmt_addr(&addr), ==, "2607:f8b0:400c:c02::68");
  257. tt_int_op(ttl, ==, 600);
  258. /* IPv6 (ttl too big) */
  259. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
  260. "\x00\x00\x00\x00\x06"
  261. "\x26\x07\xf8\xb0\x40\x0c\x0c\x02"
  262. "\x00\x00\x00\x00\x00\x00\x00\x68"
  263. "\x90\x00\x02\x58", 25);
  264. relay_header_unpack(&rh, cell.payload);
  265. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  266. tt_int_op(r, ==, 0);
  267. tt_int_op(tor_addr_family(&addr), ==, AF_INET6);
  268. tt_str_op(fmt_addr(&addr), ==, "2607:f8b0:400c:c02::68");
  269. tt_int_op(ttl, ==, -1);
  270. /* Bogus size: 3. */
  271. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
  272. "\x00\x01\x02", 3);
  273. relay_header_unpack(&rh, cell.payload);
  274. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  275. tt_int_op(r, ==, -1);
  276. /* Bogus family: 7. */
  277. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
  278. "\x00\x00\x00\x00\x07"
  279. "\x26\x07\xf8\xb0\x40\x0c\x0c\x02"
  280. "\x00\x00\x00\x00\x00\x00\x00\x68"
  281. "\x90\x00\x02\x58", 25);
  282. relay_header_unpack(&rh, cell.payload);
  283. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  284. tt_int_op(r, ==, -1);
  285. /* Truncated IPv6. */
  286. make_relay_cell(&cell, RELAY_COMMAND_CONNECTED,
  287. "\x00\x00\x00\x00\x06"
  288. "\x26\x07\xf8\xb0\x40\x0c\x0c\x02"
  289. "\x00\x00\x00\x00\x00\x00\x00\x68"
  290. "\x00\x00\x02", 24);
  291. relay_header_unpack(&rh, cell.payload);
  292. r = connected_cell_parse(&rh, &cell, &addr, &ttl);
  293. tt_int_op(r, ==, -1);
  294. done:
  295. ;
  296. }
  297. #define TEST(name, flags) \
  298. { #name, test_cfmt_ ## name, flags, 0, NULL }
  299. struct testcase_t cell_format_tests[] = {
  300. TEST(relay_header, 0),
  301. TEST(begin_cells, 0),
  302. TEST(connected_cells, 0),
  303. END_OF_TESTCASES
  304. };