test_extorport.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /* Copyright (c) 2013-2018, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define CONNECTION_PRIVATE
  4. #define EXT_ORPORT_PRIVATE
  5. #define MAIN_PRIVATE
  6. #include "or/or.h"
  7. #include "lib/container/buffers.h"
  8. #include "or/connection.h"
  9. #include "or/connection_or.h"
  10. #include "or/config.h"
  11. #include "or/control.h"
  12. #include "lib/crypt_ops/crypto_rand.h"
  13. #include "or/ext_orport.h"
  14. #include "or/main.h"
  15. #include "or/or_connection_st.h"
  16. #include "test/test.h"
  17. /* Test connection_or_remove_from_ext_or_id_map and
  18. * connection_or_set_ext_or_identifier */
  19. static void
  20. test_ext_or_id_map(void *arg)
  21. {
  22. or_connection_t *c1 = NULL, *c2 = NULL, *c3 = NULL;
  23. char *idp = NULL, *idp2 = NULL;
  24. (void)arg;
  25. /* pre-initialization */
  26. tt_ptr_op(NULL, OP_EQ,
  27. connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));
  28. c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  29. c2 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  30. c3 = or_connection_new(CONN_TYPE_OR, AF_INET);
  31. tt_ptr_op(c1->ext_or_conn_id, OP_NE, NULL);
  32. tt_ptr_op(c2->ext_or_conn_id, OP_NE, NULL);
  33. tt_ptr_op(c3->ext_or_conn_id, OP_EQ, NULL);
  34. tt_ptr_op(c1, OP_EQ, connection_or_get_by_ext_or_id(c1->ext_or_conn_id));
  35. tt_ptr_op(c2, OP_EQ, connection_or_get_by_ext_or_id(c2->ext_or_conn_id));
  36. tt_ptr_op(NULL, OP_EQ,
  37. connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));
  38. idp = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
  39. /* Give c2 a new ID. */
  40. connection_or_set_ext_or_identifier(c2);
  41. tt_mem_op(idp, OP_NE, c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
  42. idp2 = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
  43. tt_assert(!tor_digest_is_zero(idp2));
  44. tt_ptr_op(NULL, OP_EQ, connection_or_get_by_ext_or_id(idp));
  45. tt_ptr_op(c2, OP_EQ, connection_or_get_by_ext_or_id(idp2));
  46. /* Now remove it. */
  47. connection_or_remove_from_ext_or_id_map(c2);
  48. tt_ptr_op(NULL, OP_EQ, connection_or_get_by_ext_or_id(idp));
  49. tt_ptr_op(NULL, OP_EQ, connection_or_get_by_ext_or_id(idp2));
  50. done:
  51. if (c1)
  52. connection_free_minimal(TO_CONN(c1));
  53. if (c2)
  54. connection_free_minimal(TO_CONN(c2));
  55. if (c3)
  56. connection_free_minimal(TO_CONN(c3));
  57. tor_free(idp);
  58. tor_free(idp2);
  59. connection_or_clear_ext_or_id_map();
  60. }
  61. /* Simple connection_write_to_buf_impl_ replacement that unconditionally
  62. * writes to outbuf. */
  63. static void
  64. connection_write_to_buf_impl_replacement(const char *string, size_t len,
  65. connection_t *conn, int compressed)
  66. {
  67. (void) compressed;
  68. tor_assert(string);
  69. tor_assert(conn);
  70. buf_add(conn->outbuf, string, len);
  71. }
  72. static char *
  73. buf_get_contents(buf_t *buf, size_t *sz_out)
  74. {
  75. char *out;
  76. *sz_out = buf_datalen(buf);
  77. if (*sz_out >= ULONG_MAX)
  78. return NULL; /* C'mon, really? */
  79. out = tor_malloc(*sz_out + 1);
  80. if (buf_get_bytes(buf, out, (unsigned long)*sz_out) != 0) {
  81. tor_free(out);
  82. return NULL;
  83. }
  84. out[*sz_out] = '\0'; /* Hopefully gratuitous. */
  85. return out;
  86. }
  87. static void
  88. test_ext_or_write_command(void *arg)
  89. {
  90. or_connection_t *c1;
  91. char *cp = NULL;
  92. char *buf = NULL;
  93. size_t sz;
  94. (void) arg;
  95. MOCK(connection_write_to_buf_impl_,
  96. connection_write_to_buf_impl_replacement);
  97. c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  98. tt_assert(c1);
  99. /* Length too long */
  100. tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 100, "X", 100000),
  101. OP_LT, 0);
  102. /* Empty command */
  103. tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99, NULL, 0),
  104. OP_EQ, 0);
  105. cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
  106. tt_int_op(sz, OP_EQ, 4);
  107. tt_mem_op(cp, OP_EQ, "\x00\x99\x00\x00", 4);
  108. tor_free(cp);
  109. /* Medium command. */
  110. tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0x99,
  111. "Wai\0Hello", 9), OP_EQ, 0);
  112. cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
  113. tt_int_op(sz, OP_EQ, 13);
  114. tt_mem_op(cp, OP_EQ, "\x00\x99\x00\x09Wai\x00Hello", 13);
  115. tor_free(cp);
  116. /* Long command */
  117. buf = tor_malloc(65535);
  118. memset(buf, 'x', 65535);
  119. tt_int_op(connection_write_ext_or_command(TO_CONN(c1), 0xf00d,
  120. buf, 65535), OP_EQ, 0);
  121. cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
  122. tt_int_op(sz, OP_EQ, 65539);
  123. tt_mem_op(cp, OP_EQ, "\xf0\x0d\xff\xff", 4);
  124. tt_mem_op(cp+4, OP_EQ, buf, 65535);
  125. tor_free(cp);
  126. done:
  127. if (c1)
  128. connection_free_minimal(TO_CONN(c1));
  129. tor_free(cp);
  130. tor_free(buf);
  131. UNMOCK(connection_write_to_buf_impl_);
  132. }
  133. static int
  134. write_bytes_to_file_fail(const char *fname, const char *str, size_t len,
  135. int bin)
  136. {
  137. (void) fname;
  138. (void) str;
  139. (void) len;
  140. (void) bin;
  141. return -1;
  142. }
  143. static void
  144. test_ext_or_init_auth(void *arg)
  145. {
  146. or_options_t *options = get_options_mutable();
  147. const char *fn;
  148. char *cp = NULL;
  149. struct stat st;
  150. char cookie0[32];
  151. (void)arg;
  152. /* Check default filename location */
  153. tor_free(options->DataDirectory);
  154. options->DataDirectory = tor_strdup("foo");
  155. cp = get_ext_or_auth_cookie_file_name();
  156. tt_str_op(cp, OP_EQ, "foo"PATH_SEPARATOR"extended_orport_auth_cookie");
  157. tor_free(cp);
  158. /* Shouldn't be initialized already, or our tests will be a bit
  159. * meaningless */
  160. ext_or_auth_cookie = tor_malloc_zero(32);
  161. tt_assert(tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
  162. /* Now make sure we use a temporary file */
  163. fn = get_fname("ext_cookie_file");
  164. options->ExtORPortCookieAuthFile = tor_strdup(fn);
  165. cp = get_ext_or_auth_cookie_file_name();
  166. tt_str_op(cp, OP_EQ, fn);
  167. tor_free(cp);
  168. /* Test the initialization function with a broken
  169. write_bytes_to_file(). See if the problem is handled properly. */
  170. MOCK(write_bytes_to_file, write_bytes_to_file_fail);
  171. tt_int_op(-1, OP_EQ, init_ext_or_cookie_authentication(1));
  172. tt_int_op(ext_or_auth_cookie_is_set, OP_EQ, 0);
  173. UNMOCK(write_bytes_to_file);
  174. /* Now do the actual initialization. */
  175. tt_int_op(0, OP_EQ, init_ext_or_cookie_authentication(1));
  176. tt_int_op(ext_or_auth_cookie_is_set, OP_EQ, 1);
  177. cp = read_file_to_str(fn, RFTS_BIN, &st);
  178. tt_ptr_op(cp, OP_NE, NULL);
  179. tt_u64_op((uint64_t)st.st_size, OP_EQ, 64);
  180. tt_mem_op(cp,OP_EQ, "! Extended ORPort Auth Cookie !\x0a", 32);
  181. tt_mem_op(cp+32,OP_EQ, ext_or_auth_cookie, 32);
  182. memcpy(cookie0, ext_or_auth_cookie, 32);
  183. tt_assert(!tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
  184. /* Operation should be idempotent. */
  185. tt_int_op(0, OP_EQ, init_ext_or_cookie_authentication(1));
  186. tt_mem_op(cookie0,OP_EQ, ext_or_auth_cookie, 32);
  187. done:
  188. tor_free(cp);
  189. ext_orport_free_all();
  190. }
  191. static void
  192. test_ext_or_cookie_auth(void *arg)
  193. {
  194. char *reply=NULL, *reply2=NULL, *client_hash=NULL, *client_hash2=NULL;
  195. size_t reply_len=0;
  196. char hmac1[32], hmac2[32];
  197. const char client_nonce[32] =
  198. "Who is the third who walks alway";
  199. char server_hash_input[] =
  200. "ExtORPort authentication server-to-client hash"
  201. "Who is the third who walks alway"
  202. "................................";
  203. char client_hash_input[] =
  204. "ExtORPort authentication client-to-server hash"
  205. "Who is the third who walks alway"
  206. "................................";
  207. (void)arg;
  208. tt_int_op(strlen(client_hash_input), OP_EQ, 46+32+32);
  209. tt_int_op(strlen(server_hash_input), OP_EQ, 46+32+32);
  210. ext_or_auth_cookie = tor_malloc_zero(32);
  211. memcpy(ext_or_auth_cookie, "s beside you? When I count, ther", 32);
  212. ext_or_auth_cookie_is_set = 1;
  213. /* For this authentication, the client sends 32 random bytes (ClientNonce)
  214. * The server replies with 32 byte ServerHash and 32 byte ServerNonce,
  215. * where ServerHash is:
  216. * HMAC-SHA256(CookieString,
  217. * "ExtORPort authentication server-to-client hash" | ClientNonce |
  218. * ServerNonce)"
  219. * The client must reply with 32-byte ClientHash, which we compute as:
  220. * ClientHash is computed as:
  221. * HMAC-SHA256(CookieString,
  222. * "ExtORPort authentication client-to-server hash" | ClientNonce |
  223. * ServerNonce)
  224. */
  225. /* Wrong length */
  226. tt_int_op(-1, OP_EQ,
  227. handle_client_auth_nonce(client_nonce, 33, &client_hash, &reply,
  228. &reply_len));
  229. tt_int_op(-1, OP_EQ,
  230. handle_client_auth_nonce(client_nonce, 31, &client_hash, &reply,
  231. &reply_len));
  232. /* Now let's try this for real! */
  233. tt_int_op(0, OP_EQ,
  234. handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
  235. &reply_len));
  236. tt_int_op(reply_len, OP_EQ, 64);
  237. tt_ptr_op(reply, OP_NE, NULL);
  238. tt_ptr_op(client_hash, OP_NE, NULL);
  239. /* Fill in the server nonce into the hash inputs... */
  240. memcpy(server_hash_input+46+32, reply+32, 32);
  241. memcpy(client_hash_input+46+32, reply+32, 32);
  242. /* Check the HMACs are correct... */
  243. crypto_hmac_sha256(hmac1, (char*)ext_or_auth_cookie, 32, server_hash_input,
  244. 46+32+32);
  245. crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
  246. 46+32+32);
  247. tt_mem_op(hmac1,OP_EQ, reply, 32);
  248. tt_mem_op(hmac2,OP_EQ, client_hash, 32);
  249. /* Now do it again and make sure that the results are *different* */
  250. tt_int_op(0, OP_EQ,
  251. handle_client_auth_nonce(client_nonce, 32, &client_hash2, &reply2,
  252. &reply_len));
  253. tt_mem_op(reply2,OP_NE, reply, reply_len);
  254. tt_mem_op(client_hash2,OP_NE, client_hash, 32);
  255. /* But that this one checks out too. */
  256. memcpy(server_hash_input+46+32, reply2+32, 32);
  257. memcpy(client_hash_input+46+32, reply2+32, 32);
  258. /* Check the HMACs are correct... */
  259. crypto_hmac_sha256(hmac1, (char*)ext_or_auth_cookie, 32, server_hash_input,
  260. 46+32+32);
  261. crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
  262. 46+32+32);
  263. tt_mem_op(hmac1,OP_EQ, reply2, 32);
  264. tt_mem_op(hmac2,OP_EQ, client_hash2, 32);
  265. done:
  266. tor_free(reply);
  267. tor_free(client_hash);
  268. tor_free(reply2);
  269. tor_free(client_hash2);
  270. }
  271. static void
  272. crypto_rand_return_tse_str(char *to, size_t n)
  273. {
  274. if (n != 32) {
  275. TT_FAIL(("Asked for %d bytes, not 32", (int)n));
  276. return;
  277. }
  278. memcpy(to, "te road There is always another ", 32);
  279. }
  280. static void
  281. test_ext_or_cookie_auth_testvec(void *arg)
  282. {
  283. char *reply=NULL, *client_hash=NULL;
  284. size_t reply_len;
  285. char *mem_op_hex_tmp=NULL;
  286. const char client_nonce[] = "But when I look ahead up the whi";
  287. (void)arg;
  288. ext_or_auth_cookie = tor_malloc_zero(32);
  289. memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
  290. ext_or_auth_cookie_is_set = 1;
  291. MOCK(crypto_rand, crypto_rand_return_tse_str);
  292. tt_int_op(0, OP_EQ,
  293. handle_client_auth_nonce(client_nonce, 32, &client_hash, &reply,
  294. &reply_len));
  295. tt_ptr_op(reply, OP_NE, NULL );
  296. tt_uint_op(reply_len, OP_EQ, 64);
  297. tt_mem_op(reply+32,OP_EQ, "te road There is always another ", 32);
  298. /* HMACSHA256("Gliding wrapt in a brown mantle,"
  299. * "ExtORPort authentication server-to-client hash"
  300. * "But when I look ahead up the write road There is always another ");
  301. */
  302. test_memeq_hex(reply,
  303. "ec80ed6e546d3b36fdfc22fe1315416b"
  304. "029f1ade7610d910878b62eeb7403821");
  305. /* HMACSHA256("Gliding wrapt in a brown mantle,"
  306. * "ExtORPort authentication client-to-server hash"
  307. * "But when I look ahead up the write road There is always another ");
  308. * (Both values computed using Python CLI.)
  309. */
  310. test_memeq_hex(client_hash,
  311. "ab391732dd2ed968cd40c087d1b1f25b"
  312. "33b3cd77ff79bd80c2074bbf438119a2");
  313. done:
  314. UNMOCK(crypto_rand);
  315. tor_free(reply);
  316. tor_free(client_hash);
  317. tor_free(mem_op_hex_tmp);
  318. }
  319. static void
  320. ignore_bootstrap_problem(const char *warn, int reason,
  321. or_connection_t *conn)
  322. {
  323. (void)warn;
  324. (void)reason;
  325. (void)conn;
  326. }
  327. static int is_reading = 1;
  328. static int handshake_start_called = 0;
  329. static void
  330. note_read_stopped(connection_t *conn)
  331. {
  332. (void)conn;
  333. is_reading=0;
  334. }
  335. static void
  336. note_read_started(connection_t *conn)
  337. {
  338. (void)conn;
  339. is_reading=1;
  340. }
  341. static int
  342. handshake_start(or_connection_t *conn, int receiving)
  343. {
  344. if (!conn || !receiving)
  345. TT_FAIL(("Bad arguments to handshake_start"));
  346. handshake_start_called = 1;
  347. return 0;
  348. }
  349. #define WRITE(s,n) \
  350. do { \
  351. buf_add(TO_CONN(conn)->inbuf, (s), (n)); \
  352. } while (0)
  353. #define CONTAINS(s,n) \
  354. do { \
  355. tt_int_op((n), OP_LE, sizeof(b)); \
  356. tt_int_op(buf_datalen(TO_CONN(conn)->outbuf), OP_EQ, (n)); \
  357. if ((n)) { \
  358. buf_get_bytes(TO_CONN(conn)->outbuf, b, (n)); \
  359. tt_mem_op(b, OP_EQ, (s), (n)); \
  360. } \
  361. } while (0)
  362. /* Helper: Do a successful Extended ORPort authentication handshake. */
  363. static void
  364. do_ext_or_handshake(or_connection_t *conn)
  365. {
  366. char b[256];
  367. tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn));
  368. CONTAINS("\x01\x00", 2);
  369. WRITE("\x01", 1);
  370. WRITE("But when I look ahead up the whi", 32);
  371. MOCK(crypto_rand, crypto_rand_return_tse_str);
  372. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  373. UNMOCK(crypto_rand);
  374. tt_int_op(TO_CONN(conn)->state, OP_EQ,
  375. EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_HASH);
  376. CONTAINS("\xec\x80\xed\x6e\x54\x6d\x3b\x36\xfd\xfc\x22\xfe\x13\x15\x41\x6b"
  377. "\x02\x9f\x1a\xde\x76\x10\xd9\x10\x87\x8b\x62\xee\xb7\x40\x38\x21"
  378. "te road There is always another ", 64);
  379. /* Send the right response this time. */
  380. WRITE("\xab\x39\x17\x32\xdd\x2e\xd9\x68\xcd\x40\xc0\x87\xd1\xb1\xf2\x5b"
  381. "\x33\xb3\xcd\x77\xff\x79\xbd\x80\xc2\x07\x4b\xbf\x43\x81\x19\xa2",
  382. 32);
  383. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  384. CONTAINS("\x01", 1);
  385. tt_assert(! TO_CONN(conn)->marked_for_close);
  386. tt_int_op(TO_CONN(conn)->state, OP_EQ, EXT_OR_CONN_STATE_OPEN);
  387. done: ;
  388. }
  389. static void
  390. test_ext_or_handshake(void *arg)
  391. {
  392. or_connection_t *conn=NULL;
  393. char b[256];
  394. (void) arg;
  395. MOCK(connection_write_to_buf_impl_,
  396. connection_write_to_buf_impl_replacement);
  397. /* Use same authenticators as for test_ext_or_cookie_auth_testvec */
  398. ext_or_auth_cookie = tor_malloc_zero(32);
  399. memcpy(ext_or_auth_cookie, "Gliding wrapt in a brown mantle," , 32);
  400. ext_or_auth_cookie_is_set = 1;
  401. init_connection_lists();
  402. conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  403. tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn));
  404. /* The server starts by telling us about the one supported authtype. */
  405. CONTAINS("\x01\x00", 2);
  406. /* Say the client hasn't responded yet. */
  407. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  408. /* Let's say the client replies badly. */
  409. WRITE("\x99", 1);
  410. tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
  411. CONTAINS("", 0);
  412. tt_assert(TO_CONN(conn)->marked_for_close);
  413. close_closeable_connections();
  414. conn = NULL;
  415. /* Okay, try again. */
  416. conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  417. tt_int_op(0, OP_EQ, connection_ext_or_start_auth(conn));
  418. CONTAINS("\x01\x00", 2);
  419. /* Let's say the client replies sensibly this time. "Yes, AUTHTYPE_COOKIE
  420. * sounds delicious. Let's have some of that!" */
  421. WRITE("\x01", 1);
  422. /* Let's say that the client also sends part of a nonce. */
  423. WRITE("But when I look ", 16);
  424. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  425. CONTAINS("", 0);
  426. tt_int_op(TO_CONN(conn)->state, OP_EQ,
  427. EXT_OR_CONN_STATE_AUTH_WAIT_CLIENT_NONCE);
  428. /* Pump it again. Nothing should happen. */
  429. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  430. /* send the rest of the nonce. */
  431. WRITE("ahead up the whi", 16);
  432. MOCK(crypto_rand, crypto_rand_return_tse_str);
  433. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  434. UNMOCK(crypto_rand);
  435. /* We should get the right reply from the server. */
  436. CONTAINS("\xec\x80\xed\x6e\x54\x6d\x3b\x36\xfd\xfc\x22\xfe\x13\x15\x41\x6b"
  437. "\x02\x9f\x1a\xde\x76\x10\xd9\x10\x87\x8b\x62\xee\xb7\x40\x38\x21"
  438. "te road There is always another ", 64);
  439. /* Send the wrong response. */
  440. WRITE("not with a bang but a whimper...", 32);
  441. MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
  442. tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
  443. CONTAINS("\x00", 1);
  444. tt_assert(TO_CONN(conn)->marked_for_close);
  445. /* XXXX Hold-open-until-flushed. */
  446. close_closeable_connections();
  447. conn = NULL;
  448. UNMOCK(control_event_bootstrap_prob_or);
  449. MOCK(connection_start_reading, note_read_started);
  450. MOCK(connection_stop_reading, note_read_stopped);
  451. MOCK(connection_tls_start_handshake, handshake_start);
  452. /* Okay, this time let's succeed. */
  453. conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  454. do_ext_or_handshake(conn);
  455. /* Now let's run through some messages. */
  456. /* First let's send some junk and make sure it's ignored. */
  457. WRITE("\xff\xf0\x00\x03""ABC", 7);
  458. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  459. CONTAINS("", 0);
  460. /* Now let's send a USERADDR command. */
  461. WRITE("\x00\x01\x00\x0c""1.2.3.4:5678", 16);
  462. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  463. tt_int_op(TO_CONN(conn)->port, OP_EQ, 5678);
  464. tt_int_op(tor_addr_to_ipv4h(&TO_CONN(conn)->addr), OP_EQ, 0x01020304);
  465. /* Now let's send a TRANSPORT command. */
  466. WRITE("\x00\x02\x00\x07""rfc1149", 11);
  467. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  468. tt_ptr_op(NULL, OP_NE, conn->ext_or_transport);
  469. tt_str_op("rfc1149", OP_EQ, conn->ext_or_transport);
  470. tt_int_op(is_reading,OP_EQ,1);
  471. tt_int_op(TO_CONN(conn)->state, OP_EQ, EXT_OR_CONN_STATE_OPEN);
  472. /* DONE */
  473. WRITE("\x00\x00\x00\x00", 4);
  474. tt_int_op(0, OP_EQ, connection_ext_or_process_inbuf(conn));
  475. tt_int_op(TO_CONN(conn)->state, OP_EQ, EXT_OR_CONN_STATE_FLUSHING);
  476. tt_int_op(is_reading,OP_EQ,0);
  477. CONTAINS("\x10\x00\x00\x00", 4);
  478. tt_int_op(handshake_start_called,OP_EQ,0);
  479. tt_int_op(0, OP_EQ, connection_ext_or_finished_flushing(conn));
  480. tt_int_op(is_reading,OP_EQ,1);
  481. tt_int_op(handshake_start_called,OP_EQ,1);
  482. tt_int_op(TO_CONN(conn)->type, OP_EQ, CONN_TYPE_OR);
  483. tt_int_op(TO_CONN(conn)->state, OP_EQ, 0);
  484. close_closeable_connections();
  485. conn = NULL;
  486. /* Okay, this time let's succeed the handshake but fail the USERADDR
  487. command. */
  488. conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  489. do_ext_or_handshake(conn);
  490. /* USERADDR command with an extra NUL byte */
  491. WRITE("\x00\x01\x00\x0d""1.2.3.4:5678\x00", 17);
  492. MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
  493. tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
  494. CONTAINS("", 0);
  495. tt_assert(TO_CONN(conn)->marked_for_close);
  496. close_closeable_connections();
  497. conn = NULL;
  498. UNMOCK(control_event_bootstrap_prob_or);
  499. /* Now fail the TRANSPORT command. */
  500. conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  501. do_ext_or_handshake(conn);
  502. /* TRANSPORT command with an extra NUL byte */
  503. WRITE("\x00\x02\x00\x08""rfc1149\x00", 12);
  504. MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
  505. tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
  506. CONTAINS("", 0);
  507. tt_assert(TO_CONN(conn)->marked_for_close);
  508. close_closeable_connections();
  509. conn = NULL;
  510. UNMOCK(control_event_bootstrap_prob_or);
  511. /* Now fail the TRANSPORT command. */
  512. conn = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  513. do_ext_or_handshake(conn);
  514. /* TRANSPORT command with transport name with symbols (not a
  515. C-identifier) */
  516. WRITE("\x00\x02\x00\x07""rf*1149", 11);
  517. MOCK(control_event_bootstrap_prob_or, ignore_bootstrap_problem);
  518. tt_int_op(-1, OP_EQ, connection_ext_or_process_inbuf(conn));
  519. CONTAINS("", 0);
  520. tt_assert(TO_CONN(conn)->marked_for_close);
  521. close_closeable_connections();
  522. conn = NULL;
  523. UNMOCK(control_event_bootstrap_prob_or);
  524. done:
  525. UNMOCK(connection_write_to_buf_impl_);
  526. UNMOCK(crypto_rand);
  527. if (conn)
  528. connection_free_minimal(TO_CONN(conn));
  529. #undef CONTAINS
  530. #undef WRITE
  531. }
  532. struct testcase_t extorport_tests[] = {
  533. { "id_map", test_ext_or_id_map, TT_FORK, NULL, NULL },
  534. { "write_command", test_ext_or_write_command, TT_FORK, NULL, NULL },
  535. { "init_auth", test_ext_or_init_auth, TT_FORK, NULL, NULL },
  536. { "cookie_auth", test_ext_or_cookie_auth, TT_FORK, NULL, NULL },
  537. { "cookie_auth_testvec", test_ext_or_cookie_auth_testvec, TT_FORK,
  538. NULL, NULL },
  539. { "handshake", test_ext_or_handshake, TT_FORK, NULL, NULL },
  540. END_OF_TESTCASES
  541. };