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