test_extorport.c 20 KB

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