test_proto_misc.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /* Copyright (c) 2017-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file test_proto_misc.c
  5. * \brief Test our smaller buffer-based protocol functions
  6. */
  7. #include "core/or/or.h"
  8. #include "test/test.h"
  9. #include "lib/buf/buffers.h"
  10. #include "core/or/connection_or.h"
  11. #include "feature/relay/ext_orport.h"
  12. #include "core/proto/proto_cell.h"
  13. #include "core/proto/proto_control0.h"
  14. #include "core/proto/proto_ext_or.h"
  15. #include "core/or/var_cell_st.h"
  16. static void
  17. test_proto_var_cell(void *arg)
  18. {
  19. (void)arg;
  20. char *mem_op_hex_tmp = NULL;
  21. char tmp[1024];
  22. buf_t *buf = NULL;
  23. var_cell_t *cell = NULL;
  24. buf = buf_new();
  25. memset(tmp, 0xf0, sizeof(tmp));
  26. /* Short little commands will make us say "no cell yet." */
  27. tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  28. tt_ptr_op(cell, OP_EQ, NULL);
  29. buf_add(buf, "\x01\x02\x02\0x2", 4);
  30. tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  31. /* An incomplete fixed-length cell makes us say "no cell yet". */
  32. buf_add(buf, "\x03", 1);
  33. tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  34. /* A complete fixed length-cell makes us say "not a variable-length cell" */
  35. buf_add(buf, tmp, 509);
  36. tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  37. buf_clear(buf);
  38. /* An incomplete versions cell is a variable-length cell that isn't ready
  39. * yet. */
  40. buf_add(buf,
  41. "\x01\x02\x03\x04" /* circid */
  42. "\x07" /* VERSIONS */
  43. "\x00\x04" /* 4 bytes long */
  44. "\x00" /* incomplete */, 8);
  45. tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  46. tt_ptr_op(cell, OP_EQ, NULL);
  47. /* Complete it, and it's a variable-length cell. Leave a byte on the end for
  48. * fun. */
  49. buf_add(buf, "\x09\x00\x25\ff", 4);
  50. tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  51. tt_ptr_op(cell, OP_NE, NULL);
  52. tt_int_op(cell->command, OP_EQ, CELL_VERSIONS);
  53. tt_uint_op(cell->circ_id, OP_EQ, 0x01020304);
  54. tt_int_op(cell->payload_len, OP_EQ, 4);
  55. test_mem_op_hex(cell->payload, OP_EQ, "00090025");
  56. var_cell_free(cell);
  57. cell = NULL;
  58. tt_int_op(buf_datalen(buf), OP_EQ, 1);
  59. buf_clear(buf);
  60. /* In link protocol 3 and earlier, circid fields were two bytes long. Let's
  61. * ensure that gets handled correctly. */
  62. buf_add(buf,
  63. "\x23\x45\x81\x00\x06" /* command 81; 6 bytes long */
  64. "coraje", 11);
  65. tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 3));
  66. tt_ptr_op(cell, OP_NE, NULL);
  67. tt_int_op(cell->command, OP_EQ, 129);
  68. tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
  69. tt_int_op(cell->payload_len, OP_EQ, 6);
  70. tt_mem_op(cell->payload, OP_EQ, "coraje", 6);
  71. var_cell_free(cell);
  72. cell = NULL;
  73. tt_int_op(buf_datalen(buf), OP_EQ, 0);
  74. /* In link protocol 2, only VERSIONS cells counted as variable-length */
  75. buf_add(buf,
  76. "\x23\x45\x81\x00\x06"
  77. "coraje", 11); /* As above */
  78. tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
  79. buf_clear(buf);
  80. buf_add(buf,
  81. "\x23\x45\x07\x00\x06"
  82. "futuro", 11);
  83. tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
  84. tt_ptr_op(cell, OP_NE, NULL);
  85. tt_int_op(cell->command, OP_EQ, 7);
  86. tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
  87. tt_int_op(cell->payload_len, OP_EQ, 6);
  88. tt_mem_op(cell->payload, OP_EQ, "futuro", 6);
  89. var_cell_free(cell);
  90. cell = NULL;
  91. done:
  92. buf_free(buf);
  93. var_cell_free(cell);
  94. tor_free(mem_op_hex_tmp);
  95. }
  96. static void
  97. test_proto_control0(void *arg)
  98. {
  99. (void)arg;
  100. buf_t *buf = buf_new();
  101. /* The only remaining function for the v0 control protocol is the function
  102. that detects whether the user has stumbled across an old controller
  103. that's using it. The format was:
  104. u16 length;
  105. u16 command;
  106. u8 body[length];
  107. */
  108. /* Empty buffer -- nothing to do. */
  109. tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf));
  110. /* 3 chars in buf -- can't tell */
  111. buf_add(buf, "AUT", 3);
  112. tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf));
  113. /* command in buf -- easy to tell */
  114. buf_add(buf, "HENTICATE ", 10);
  115. tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf));
  116. /* Control0 command header in buf: make sure we detect it. */
  117. buf_clear(buf);
  118. buf_add(buf, "\x09\x05" "\x00\x05" "blah", 8);
  119. tt_int_op(1, OP_EQ, peek_buf_has_control0_command(buf));
  120. done:
  121. buf_free(buf);
  122. }
  123. static void
  124. test_proto_ext_or_cmd(void *arg)
  125. {
  126. ext_or_cmd_t *cmd = NULL;
  127. buf_t *buf = buf_new();
  128. char *tmp = NULL;
  129. (void) arg;
  130. /* Empty -- should give "not there. */
  131. tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  132. tt_ptr_op(NULL, OP_EQ, cmd);
  133. /* Three bytes: shouldn't work. */
  134. buf_add(buf, "\x00\x20\x00", 3);
  135. tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  136. tt_ptr_op(NULL, OP_EQ, cmd);
  137. tt_int_op(3, OP_EQ, buf_datalen(buf));
  138. /* 0020 0000: That's a nil command. It should work. */
  139. buf_add(buf, "\x00", 1);
  140. tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  141. tt_ptr_op(NULL, OP_NE, cmd);
  142. tt_int_op(0x20, OP_EQ, cmd->cmd);
  143. tt_int_op(0, OP_EQ, cmd->len);
  144. tt_int_op(0, OP_EQ, buf_datalen(buf));
  145. ext_or_cmd_free(cmd);
  146. cmd = NULL;
  147. /* Now try a length-6 command with one byte missing. */
  148. buf_add(buf, "\x10\x21\x00\x06""abcde", 9);
  149. tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  150. tt_ptr_op(NULL, OP_EQ, cmd);
  151. buf_add(buf, "f", 1);
  152. tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  153. tt_ptr_op(NULL, OP_NE, cmd);
  154. tt_int_op(0x1021, OP_EQ, cmd->cmd);
  155. tt_int_op(6, OP_EQ, cmd->len);
  156. tt_mem_op("abcdef", OP_EQ, cmd->body, 6);
  157. tt_int_op(0, OP_EQ, buf_datalen(buf));
  158. ext_or_cmd_free(cmd);
  159. cmd = NULL;
  160. /* Now try a length-10 command with 4 extra bytes. */
  161. buf_add(buf, "\xff\xff\x00\x0aloremipsum\x10\x00\xff\xff", 18);
  162. tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  163. tt_ptr_op(NULL, OP_NE, cmd);
  164. tt_int_op(0xffff, OP_EQ, cmd->cmd);
  165. tt_int_op(10, OP_EQ, cmd->len);
  166. tt_mem_op("loremipsum", OP_EQ, cmd->body, 10);
  167. tt_int_op(4, OP_EQ, buf_datalen(buf));
  168. ext_or_cmd_free(cmd);
  169. cmd = NULL;
  170. /* Finally, let's try a maximum-length command. We already have the header
  171. * waiting. */
  172. tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  173. tmp = tor_malloc_zero(65535);
  174. buf_add(buf, tmp, 65535);
  175. tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
  176. tt_ptr_op(NULL, OP_NE, cmd);
  177. tt_int_op(0x1000, OP_EQ, cmd->cmd);
  178. tt_int_op(0xffff, OP_EQ, cmd->len);
  179. tt_mem_op(tmp, OP_EQ, cmd->body, 65535);
  180. tt_int_op(0, OP_EQ, buf_datalen(buf));
  181. ext_or_cmd_free(cmd);
  182. cmd = NULL;
  183. done:
  184. ext_or_cmd_free(cmd);
  185. buf_free(buf);
  186. tor_free(tmp);
  187. }
  188. static void
  189. test_proto_line(void *arg)
  190. {
  191. (void)arg;
  192. char tmp[60];
  193. buf_t *buf = buf_new();
  194. #define S(str) str, sizeof(str)-1
  195. const struct {
  196. const char *input;
  197. size_t input_len;
  198. size_t line_len;
  199. const char *output;
  200. int returnval;
  201. } cases[] = {
  202. { S("Hello world"), 0, NULL, 0 },
  203. { S("Hello world\n"), 12, "Hello world\n", 1 },
  204. { S("Hello world\nMore"), 12, "Hello world\n", 1 },
  205. { S("\n oh hello world\nMore"), 1, "\n", 1 },
  206. { S("Hello worpd\n\nMore"), 12, "Hello worpd\n", 1 },
  207. { S("------------------------------------------------------------\n"), 0,
  208. NULL, -1 },
  209. };
  210. unsigned i;
  211. for (i = 0; i < ARRAY_LENGTH(cases); ++i) {
  212. buf_add(buf, cases[i].input, cases[i].input_len);
  213. memset(tmp, 0xfe, sizeof(tmp));
  214. size_t sz = sizeof(tmp);
  215. int rv = buf_get_line(buf, tmp, &sz);
  216. tt_int_op(rv, OP_EQ, cases[i].returnval);
  217. if (rv == 1) {
  218. tt_int_op(sz, OP_LT, sizeof(tmp));
  219. tt_mem_op(cases[i].output, OP_EQ, tmp, sz+1);
  220. tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len - strlen(tmp));
  221. tt_int_op(sz, OP_EQ, cases[i].line_len);
  222. } else {
  223. tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len);
  224. // tt_int_op(sz, OP_EQ, sizeof(tmp));
  225. }
  226. buf_clear(buf);
  227. }
  228. done:
  229. buf_free(buf);
  230. }
  231. struct testcase_t proto_misc_tests[] = {
  232. { "var_cell", test_proto_var_cell, 0, NULL, NULL },
  233. { "control0", test_proto_control0, 0, NULL, NULL },
  234. { "ext_or_cmd", test_proto_ext_or_cmd, TT_FORK, NULL, NULL },
  235. { "line", test_proto_line, 0, NULL, NULL },
  236. END_OF_TESTCASES
  237. };