test_channeltls.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /* Copyright (c) 2014-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "orconfig.h"
  4. #include <math.h>
  5. #define TOR_CHANNEL_INTERNAL_
  6. #include "core/or/or.h"
  7. #include "lib/net/address.h"
  8. #include "lib/container/buffers.h"
  9. #include "core/or/channel.h"
  10. #include "core/or/channeltls.h"
  11. #include "core/mainloop/connection.h"
  12. #include "core/or/connection_or.h"
  13. #include "app/config/config.h"
  14. /* For init/free stuff */
  15. #include "core/or/scheduler.h"
  16. #include "lib/tls/tortls.h"
  17. #include "core/or/or_connection_st.h"
  18. /* Test suite stuff */
  19. #include "test/test.h"
  20. #include "test/fakechans.h"
  21. /* The channeltls unit tests */
  22. static void test_channeltls_create(void *arg);
  23. static void test_channeltls_num_bytes_queued(void *arg);
  24. static void test_channeltls_overhead_estimate(void *arg);
  25. /* Mocks used by channeltls unit tests */
  26. static size_t tlschan_buf_datalen_mock(const buf_t *buf);
  27. static or_connection_t * tlschan_connection_or_connect_mock(
  28. const tor_addr_t *addr,
  29. uint16_t port,
  30. const char *digest,
  31. const ed25519_public_key_t *ed_id,
  32. channel_tls_t *tlschan);
  33. static int tlschan_is_local_addr_mock(const tor_addr_t *addr);
  34. /* Fake close method */
  35. static void tlschan_fake_close_method(channel_t *chan);
  36. /* Flags controlling behavior of channeltls unit test mocks */
  37. static int tlschan_local = 0;
  38. static const buf_t * tlschan_buf_datalen_mock_target = NULL;
  39. static size_t tlschan_buf_datalen_mock_size = 0;
  40. /* Thing to cast to fake tor_tls_t * to appease assert_connection_ok() */
  41. static int fake_tortls = 0; /* Bleh... */
  42. static void
  43. test_channeltls_create(void *arg)
  44. {
  45. tor_addr_t test_addr;
  46. channel_t *ch = NULL;
  47. const char test_digest[DIGEST_LEN] = {
  48. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
  49. 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
  50. (void)arg;
  51. /* Set up a fake address to fake-connect to */
  52. test_addr.family = AF_INET;
  53. test_addr.addr.in_addr.s_addr = htonl(0x01020304);
  54. /* For this test we always want the address to be treated as non-local */
  55. tlschan_local = 0;
  56. /* Install is_local_addr() mock */
  57. MOCK(is_local_addr, tlschan_is_local_addr_mock);
  58. /* Install mock for connection_or_connect() */
  59. MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
  60. /* Try connecting */
  61. ch = channel_tls_connect(&test_addr, 567, test_digest, NULL);
  62. tt_ptr_op(ch, OP_NE, NULL);
  63. done:
  64. if (ch) {
  65. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  66. /*
  67. * Use fake close method that doesn't try to do too much to fake
  68. * orconn
  69. */
  70. ch->close = tlschan_fake_close_method;
  71. channel_mark_for_close(ch);
  72. free_fake_channel(ch);
  73. UNMOCK(scheduler_release_channel);
  74. }
  75. UNMOCK(connection_or_connect);
  76. UNMOCK(is_local_addr);
  77. return;
  78. }
  79. static void
  80. test_channeltls_num_bytes_queued(void *arg)
  81. {
  82. tor_addr_t test_addr;
  83. channel_t *ch = NULL;
  84. const char test_digest[DIGEST_LEN] = {
  85. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
  86. 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
  87. channel_tls_t *tlschan = NULL;
  88. size_t len;
  89. int fake_outbuf = 0, n;
  90. (void)arg;
  91. /* Set up a fake address to fake-connect to */
  92. test_addr.family = AF_INET;
  93. test_addr.addr.in_addr.s_addr = htonl(0x01020304);
  94. /* For this test we always want the address to be treated as non-local */
  95. tlschan_local = 0;
  96. /* Install is_local_addr() mock */
  97. MOCK(is_local_addr, tlschan_is_local_addr_mock);
  98. /* Install mock for connection_or_connect() */
  99. MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
  100. /* Try connecting */
  101. ch = channel_tls_connect(&test_addr, 567, test_digest, NULL);
  102. tt_ptr_op(ch, OP_NE, NULL);
  103. /*
  104. * Next, we have to test ch->num_bytes_queued, which is
  105. * channel_tls_num_bytes_queued_method. We can't mock
  106. * connection_get_outbuf_len() directly because it's static inline
  107. * in connection.h, but we can mock buf_datalen().
  108. */
  109. tt_assert(ch->num_bytes_queued != NULL);
  110. tlschan = BASE_CHAN_TO_TLS(ch);
  111. tt_ptr_op(tlschan, OP_NE, NULL);
  112. if (TO_CONN(tlschan->conn)->outbuf == NULL) {
  113. /* We need an outbuf to make sure buf_datalen() gets called */
  114. fake_outbuf = 1;
  115. TO_CONN(tlschan->conn)->outbuf = buf_new();
  116. }
  117. tlschan_buf_datalen_mock_target = TO_CONN(tlschan->conn)->outbuf;
  118. tlschan_buf_datalen_mock_size = 1024;
  119. MOCK(buf_datalen, tlschan_buf_datalen_mock);
  120. len = ch->num_bytes_queued(ch);
  121. tt_int_op(len, OP_EQ, tlschan_buf_datalen_mock_size);
  122. /*
  123. * We also cover num_cells_writeable here; since wide_circ_ids = 0 on
  124. * the fake tlschans, cell_network_size returns 512, and so with
  125. * tlschan_buf_datalen_mock_size == 1024, we should be able to write
  126. * ceil((OR_CONN_HIGHWATER - 1024) / 512) = ceil(OR_CONN_HIGHWATER / 512)
  127. * - 2 cells.
  128. */
  129. n = ch->num_cells_writeable(ch);
  130. tt_int_op(n, OP_EQ, CEIL_DIV(OR_CONN_HIGHWATER, 512) - 2);
  131. UNMOCK(buf_datalen);
  132. tlschan_buf_datalen_mock_target = NULL;
  133. tlschan_buf_datalen_mock_size = 0;
  134. if (fake_outbuf) {
  135. buf_free(TO_CONN(tlschan->conn)->outbuf);
  136. TO_CONN(tlschan->conn)->outbuf = NULL;
  137. }
  138. done:
  139. if (ch) {
  140. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  141. /*
  142. * Use fake close method that doesn't try to do too much to fake
  143. * orconn
  144. */
  145. ch->close = tlschan_fake_close_method;
  146. channel_mark_for_close(ch);
  147. free_fake_channel(ch);
  148. UNMOCK(scheduler_release_channel);
  149. }
  150. UNMOCK(connection_or_connect);
  151. UNMOCK(is_local_addr);
  152. return;
  153. }
  154. static void
  155. test_channeltls_overhead_estimate(void *arg)
  156. {
  157. tor_addr_t test_addr;
  158. channel_t *ch = NULL;
  159. const char test_digest[DIGEST_LEN] = {
  160. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
  161. 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
  162. double r;
  163. channel_tls_t *tlschan = NULL;
  164. (void)arg;
  165. /* Set up a fake address to fake-connect to */
  166. test_addr.family = AF_INET;
  167. test_addr.addr.in_addr.s_addr = htonl(0x01020304);
  168. /* For this test we always want the address to be treated as non-local */
  169. tlschan_local = 0;
  170. /* Install is_local_addr() mock */
  171. MOCK(is_local_addr, tlschan_is_local_addr_mock);
  172. /* Install mock for connection_or_connect() */
  173. MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
  174. /* Try connecting */
  175. ch = channel_tls_connect(&test_addr, 567, test_digest, NULL);
  176. tt_ptr_op(ch, OP_NE, NULL);
  177. /* First case: silly low ratios should get clamped to 1.0 */
  178. tlschan = BASE_CHAN_TO_TLS(ch);
  179. tt_ptr_op(tlschan, OP_NE, NULL);
  180. tlschan->conn->bytes_xmitted = 128;
  181. tlschan->conn->bytes_xmitted_by_tls = 64;
  182. r = ch->get_overhead_estimate(ch);
  183. tt_assert(fabs(r - 1.0) < 1E-12);
  184. tlschan->conn->bytes_xmitted_by_tls = 127;
  185. r = ch->get_overhead_estimate(ch);
  186. tt_assert(fabs(r - 1.0) < 1E-12);
  187. /* Now middle of the range */
  188. tlschan->conn->bytes_xmitted_by_tls = 192;
  189. r = ch->get_overhead_estimate(ch);
  190. tt_assert(fabs(r - 1.5) < 1E-12);
  191. /* Now above the 2.0 clamp */
  192. tlschan->conn->bytes_xmitted_by_tls = 257;
  193. r = ch->get_overhead_estimate(ch);
  194. tt_assert(fabs(r - 2.0) < 1E-12);
  195. tlschan->conn->bytes_xmitted_by_tls = 512;
  196. r = ch->get_overhead_estimate(ch);
  197. tt_assert(fabs(r - 2.0) < 1E-12);
  198. done:
  199. if (ch) {
  200. MOCK(scheduler_release_channel, scheduler_release_channel_mock);
  201. /*
  202. * Use fake close method that doesn't try to do too much to fake
  203. * orconn
  204. */
  205. ch->close = tlschan_fake_close_method;
  206. channel_mark_for_close(ch);
  207. free_fake_channel(ch);
  208. UNMOCK(scheduler_release_channel);
  209. }
  210. UNMOCK(connection_or_connect);
  211. UNMOCK(is_local_addr);
  212. return;
  213. }
  214. static size_t
  215. tlschan_buf_datalen_mock(const buf_t *buf)
  216. {
  217. if (buf != NULL && buf == tlschan_buf_datalen_mock_target) {
  218. return tlschan_buf_datalen_mock_size;
  219. } else {
  220. return buf_datalen__real(buf);
  221. }
  222. }
  223. static or_connection_t *
  224. tlschan_connection_or_connect_mock(const tor_addr_t *addr,
  225. uint16_t port,
  226. const char *digest,
  227. const ed25519_public_key_t *ed_id,
  228. channel_tls_t *tlschan)
  229. {
  230. or_connection_t *result = NULL;
  231. (void) ed_id; // XXXX Not yet used.
  232. tt_ptr_op(addr, OP_NE, NULL);
  233. tt_uint_op(port, OP_NE, 0);
  234. tt_ptr_op(digest, OP_NE, NULL);
  235. tt_ptr_op(tlschan, OP_NE, NULL);
  236. /* Make a fake orconn */
  237. result = tor_malloc_zero(sizeof(*result));
  238. result->base_.magic = OR_CONNECTION_MAGIC;
  239. result->base_.state = OR_CONN_STATE_OPEN;
  240. result->base_.type = CONN_TYPE_OR;
  241. result->base_.socket_family = addr->family;
  242. result->base_.address = tor_strdup("<fake>");
  243. memcpy(&(result->base_.addr), addr, sizeof(tor_addr_t));
  244. result->base_.port = port;
  245. memcpy(result->identity_digest, digest, DIGEST_LEN);
  246. result->chan = tlschan;
  247. memcpy(&(result->real_addr), addr, sizeof(tor_addr_t));
  248. result->tls = (tor_tls_t *)((void *)(&fake_tortls));
  249. done:
  250. return result;
  251. }
  252. static void
  253. tlschan_fake_close_method(channel_t *chan)
  254. {
  255. channel_tls_t *tlschan = NULL;
  256. tt_ptr_op(chan, OP_NE, NULL);
  257. tt_int_op(chan->magic, OP_EQ, TLS_CHAN_MAGIC);
  258. tlschan = BASE_CHAN_TO_TLS(chan);
  259. tt_ptr_op(tlschan, OP_NE, NULL);
  260. /* Just free the fake orconn */
  261. tor_free(tlschan->conn->base_.address);
  262. tor_free(tlschan->conn);
  263. channel_closed(chan);
  264. done:
  265. return;
  266. }
  267. static int
  268. tlschan_is_local_addr_mock(const tor_addr_t *addr)
  269. {
  270. tt_ptr_op(addr, OP_NE, NULL);
  271. done:
  272. return tlschan_local;
  273. }
  274. struct testcase_t channeltls_tests[] = {
  275. { "create", test_channeltls_create, TT_FORK, NULL, NULL },
  276. { "num_bytes_queued", test_channeltls_num_bytes_queued,
  277. TT_FORK, NULL, NULL },
  278. { "overhead_estimate", test_channeltls_overhead_estimate,
  279. TT_FORK, NULL, NULL },
  280. END_OF_TESTCASES
  281. };