test_extorport.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /* Copyright (c) 2013, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define CONNECTION_PRIVATE
  4. #define EXT_ORPORT_PRIVATE
  5. #include "or.h"
  6. #include "buffers.h"
  7. #include "connection.h"
  8. #include "ext_orport.h"
  9. #include "test.h"
  10. /* Test connection_or_remove_from_ext_or_id_map and
  11. * connection_or_set_ext_or_identifier */
  12. static void
  13. test_ext_or_id_map(void *arg)
  14. {
  15. or_connection_t *c1 = NULL, *c2 = NULL, *c3 = NULL;
  16. char *idp = NULL, *idp2 = NULL;
  17. (void)arg;
  18. /* pre-initialization */
  19. tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));
  20. c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  21. c2 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  22. c3 = or_connection_new(CONN_TYPE_OR, AF_INET);
  23. tt_ptr_op(c1->ext_or_conn_id, !=, NULL);
  24. tt_ptr_op(c2->ext_or_conn_id, !=, NULL);
  25. tt_ptr_op(c3->ext_or_conn_id, ==, NULL);
  26. tt_ptr_op(c1, ==, connection_or_get_by_ext_or_id(c1->ext_or_conn_id));
  27. tt_ptr_op(c2, ==, connection_or_get_by_ext_or_id(c2->ext_or_conn_id));
  28. tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));
  29. idp = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
  30. /* Give c2 a new ID. */
  31. connection_or_set_ext_or_identifier(c2);
  32. test_mem_op(idp, !=, c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
  33. idp2 = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
  34. tt_assert(!tor_digest_is_zero(idp2));
  35. tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id(idp));
  36. tt_ptr_op(c2, ==, connection_or_get_by_ext_or_id(idp2));
  37. /* Now remove it. */
  38. connection_or_remove_from_ext_or_id_map(c2);
  39. tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id(idp));
  40. tt_ptr_op(NULL, ==, connection_or_get_by_ext_or_id(idp2));
  41. done:
  42. if (c1)
  43. connection_free_(TO_CONN(c1));
  44. if (c2)
  45. connection_free_(TO_CONN(c2));
  46. if (c3)
  47. connection_free_(TO_CONN(c3));
  48. tor_free(idp);
  49. tor_free(idp2);
  50. connection_or_clear_ext_or_id_map();
  51. }
  52. /* Simple connection_write_to_buf_impl_ replacement that unconditionally
  53. * writes to outbuf. */
  54. static void
  55. connection_write_to_buf_impl_replacement(const char *string, size_t len,
  56. connection_t *conn, int zlib)
  57. {
  58. (void) zlib;
  59. tor_assert(string);
  60. tor_assert(conn);
  61. write_to_buf(string, len, conn->outbuf);
  62. }
  63. static char *
  64. buf_get_contents(buf_t *buf, size_t *sz_out)
  65. {
  66. char *out;
  67. *sz_out = buf_datalen(buf);
  68. if (*sz_out >= ULONG_MAX)
  69. return NULL; /* C'mon, really? */
  70. out = tor_malloc(*sz_out + 1);
  71. if (fetch_from_buf(out, (unsigned long)*sz_out, buf) != 0) {
  72. tor_free(out);
  73. return NULL;
  74. }
  75. out[*sz_out] = '\0'; /* Hopefully gratuitous. */
  76. return out;
  77. }
  78. static void
  79. test_ext_or_write_command(void *arg)
  80. {
  81. or_connection_t *c1;
  82. char *cp = NULL;
  83. char *buf = NULL;
  84. size_t sz;
  85. (void) arg;
  86. MOCK(connection_write_to_buf_impl_,
  87. connection_write_to_buf_impl_replacement);
  88. c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  89. tt_assert(c1);
  90. /* Length too long */
  91. tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 100, "X", 100000),
  92. <, 0);
  93. /* Empty command */
  94. tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99, NULL, 0),
  95. ==, 0);
  96. cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
  97. tt_int_op(sz, ==, 4);
  98. test_mem_op(cp, ==, "\x00\x99\x00\x00", 4);
  99. tor_free(cp);
  100. /* Medium command. */
  101. tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99,
  102. "Wai\0Hello", 9), ==, 0);
  103. cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
  104. tt_int_op(sz, ==, 13);
  105. test_mem_op(cp, ==, "\x00\x99\x00\x09Wai\x00Hello", 13);
  106. tor_free(cp);
  107. /* Long command */
  108. buf = tor_malloc(65535);
  109. memset(buf, 'x', 65535);
  110. tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0xf00d,
  111. buf, 65535), ==, 0);
  112. cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
  113. tt_int_op(sz, ==, 65539);
  114. test_mem_op(cp, ==, "\xf0\x0d\xff\xff", 4);
  115. test_mem_op(cp+4, ==, buf, 65535);
  116. tor_free(cp);
  117. done:
  118. if (c1)
  119. connection_free_(TO_CONN(c1));
  120. tor_free(cp);
  121. tor_free(buf);
  122. UNMOCK(connection_write_to_buf_impl_);
  123. }
  124. static void
  125. test_ext_or_cookie_auth(void *arg)
  126. {
  127. char *reply=NULL, *reply2=NULL, *client_hash=NULL, *client_hash2=NULL;
  128. size_t reply_len=0;
  129. char hmac1[32], hmac2[32];
  130. const char client_nonce[32] =
  131. "Who is the third who walks alway";
  132. char server_hash_input[] =
  133. "ExtORPort authentication server-to-client hash"
  134. "Who is the third who walks alway"
  135. "................................";
  136. char client_hash_input[] =
  137. "ExtORPort authentication client-to-server hash"
  138. "Who is the third who walks alway"
  139. "................................";
  140. (void)arg;
  141. tt_int_op(strlen(client_hash_input), ==, 46+32+32);
  142. tt_int_op(strlen(server_hash_input), ==, 46+32+32);
  143. memcpy(ext_or_auth_cookie, "s beside you? When I count, ther", 32);
  144. ext_or_auth_cookie_is_set = 1;
  145. /* For this authentication, the client sends 32 random bytes (ClientNonce)
  146. * The server replies with 32 byte ServerHash and 32 byte ServerNonce,
  147. * where ServerHash is:
  148. * HMAC-SHA256(CookieString,
  149. * "ExtORPort authentication server-to-client hash" | ClientNonce |
  150. * ServerNonce)"
  151. * The client must reply with 32-byte ClientHash, which we compute as:
  152. * ClientHash is computed as:
  153. * HMAC-SHA256(CookieString,
  154. * "ExtORPort authentication client-to-server hash" | ClientNonce |
  155. * ServerNonce)
  156. */
  157. /* Wrong length */
  158. tt_int_op(-1, ==,
  159. handle_client_auth_nonce(client_nonce, 33, &client_hash, &reply,
  160. &reply_len));
  161. tt_int_op(-1, ==,
  162. handle_client_auth_nonce(client_nonce, 31, &client_hash, &reply,
  163. &reply_len));
  164. /* Now let's try this for real! */
  165. tt_int_op(0, ==,
  166. handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
  167. &reply_len));
  168. tt_int_op(reply_len, ==, 64);
  169. tt_ptr_op(reply, !=, NULL);
  170. tt_ptr_op(client_hash, !=, NULL);
  171. /* Fill in the server nonce into the hash inputs... */
  172. memcpy(server_hash_input+46+32, reply+32, 32);
  173. memcpy(client_hash_input+46+32, reply+32, 32);
  174. /* Check the HMACs are correct... */
  175. crypto_hmac_sha256(hmac1, ext_or_auth_cookie, 32, server_hash_input,
  176. 46+32+32);
  177. crypto_hmac_sha256(hmac2, ext_or_auth_cookie, 32, client_hash_input,
  178. 46+32+32);
  179. test_memeq(hmac1, reply, 32);
  180. test_memeq(hmac2, client_hash, 32);
  181. /* Now do it again and make sure that the results are *different* */
  182. tt_int_op(0, ==,
  183. handle_client_auth_nonce(client_nonce, 32, &client_hash2, &reply2,
  184. &reply_len));
  185. test_memneq(reply2, reply, reply_len);
  186. test_memneq(client_hash2, client_hash, 32);
  187. /* But that this one checks out too. */
  188. memcpy(server_hash_input+46+32, reply2+32, 32);
  189. memcpy(client_hash_input+46+32, reply2+32, 32);
  190. /* Check the HMACs are correct... */
  191. crypto_hmac_sha256(hmac1, ext_or_auth_cookie, 32, server_hash_input,
  192. 46+32+32);
  193. crypto_hmac_sha256(hmac2, ext_or_auth_cookie, 32, client_hash_input,
  194. 46+32+32);
  195. test_memeq(hmac1, reply2, 32);
  196. test_memeq(hmac2, client_hash2, 32);
  197. done:
  198. tor_free(reply);
  199. tor_free(client_hash);
  200. tor_free(reply2);
  201. tor_free(client_hash2);
  202. }
  203. static int
  204. crypto_rand_return_tse_str(char *to, size_t n)
  205. {
  206. if (n != 32) {
  207. TT_FAIL(("Asked for %d bytes, not 32", (int)n));
  208. return -1;
  209. }
  210. memcpy(to, "te road There is always another ", 32);
  211. return 0;
  212. }
  213. static void
  214. test_ext_or_cookie_auth_testvec(void *arg)
  215. {
  216. char *reply=NULL, *client_hash=NULL;
  217. size_t reply_len;
  218. char *mem_op_hex_tmp=NULL;
  219. const char client_nonce[] = "But when I look ahead up the whi";
  220. (void)arg;
  221. memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
  222. ext_or_auth_cookie_is_set = 1;
  223. MOCK(crypto_rand, crypto_rand_return_tse_str);
  224. tt_int_op(0, ==,
  225. handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
  226. &reply_len));
  227. tt_ptr_op(reply, !=, NULL );
  228. tt_ptr_op(reply_len, ==, 64);
  229. test_memeq(reply+32, "te road There is always another ", 32);
  230. /* HMACSHA256("Gliding wrapt in a brown mantle,"
  231. * "ExtORPort authentication server-to-client hash"
  232. * "But when I look ahead up the write road There is always another ");
  233. */
  234. test_memeq_hex(reply,
  235. "ec80ed6e546d3b36fdfc22fe1315416b"
  236. "029f1ade7610d910878b62eeb7403821");
  237. /* HMACSHA256("Gliding wrapt in a brown mantle,"
  238. * "ExtORPort authentication client-to-server hash"
  239. * "But when I look ahead up the write road There is always another ");
  240. * (Both values computed using Python CLI.)
  241. */
  242. test_memeq_hex(client_hash,
  243. "ab391732dd2ed968cd40c087d1b1f25b"
  244. "33b3cd77ff79bd80c2074bbf438119a2");
  245. done:
  246. UNMOCK(crypto_rand);
  247. tor_free(reply);
  248. tor_free(client_hash);
  249. tor_free(mem_op_hex_tmp);
  250. }
  251. struct testcase_t extorport_tests[] = {
  252. { "id_map", test_ext_or_id_map, TT_FORK, NULL, NULL },
  253. { "write_command", test_ext_or_write_command, TT_FORK, NULL, NULL },
  254. { "cookie_auth", test_ext_or_cookie_auth, TT_FORK, NULL, NULL },
  255. { "cookie_auth_testvec", test_ext_or_cookie_auth_testvec, TT_FORK,
  256. NULL, NULL },
  257. END_OF_TESTCASES
  258. };