Line data Source code
1 : /* Copyright (c) 2015-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : #include "orconfig.h"
5 :
6 : #define CONNECTION_PRIVATE
7 : #define MAINLOOP_PRIVATE
8 : #define CONNECTION_OR_PRIVATE
9 :
10 : #include "core/or/or.h"
11 : #include "test/test.h"
12 :
13 : #include "app/config/config.h"
14 : #include "app/config/or_options_st.h"
15 : #include "core/mainloop/connection.h"
16 : #include "core/or/connection_edge.h"
17 : #include "feature/hs/hs_common.h"
18 : #include "core/mainloop/mainloop.h"
19 : #include "feature/nodelist/microdesc.h"
20 : #include "feature/nodelist/nodelist.h"
21 : #include "feature/nodelist/networkstatus.h"
22 : #include "feature/dircommon/directory.h"
23 : #include "core/or/connection_or.h"
24 : #include "lib/net/resolve.h"
25 :
26 : #include "test/test_connection.h"
27 : #include "test/test_helpers.h"
28 :
29 : #include "feature/dircommon/dir_connection_st.h"
30 : #include "core/or/entry_connection_st.h"
31 : #include "feature/nodelist/node_st.h"
32 : #include "core/or/or_connection_st.h"
33 : #include "feature/nodelist/routerinfo_st.h"
34 : #include "core/or/socks_request_st.h"
35 :
36 : static void * test_conn_get_basic_setup(const struct testcase_t *tc);
37 : static int test_conn_get_basic_teardown(const struct testcase_t *tc,
38 : void *arg);
39 :
40 : static void * test_conn_get_rsrc_setup(const struct testcase_t *tc);
41 : static int test_conn_get_rsrc_teardown(const struct testcase_t *tc,
42 : void *arg);
43 :
44 : /* Arbitrary choice - IPv4 Directory Connection to localhost */
45 : #define TEST_CONN_TYPE (CONN_TYPE_DIR)
46 : /* We assume every machine has IPv4 localhost, is that ok? */
47 : #define TEST_CONN_ADDRESS "127.0.0.1"
48 : #define TEST_CONN_PORT (12345)
49 : #define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345"
50 : #define TEST_CONN_FAMILY (AF_INET)
51 : #define TEST_CONN_STATE (DIR_CONN_STATE_MIN_)
52 : #define TEST_CONN_ADDRESS_2 "127.0.0.2"
53 :
54 : #define TEST_CONN_BASIC_PURPOSE (DIR_PURPOSE_MIN_)
55 :
56 : #define TEST_CONN_REND_ADDR "cfs3rltphxxvabci"
57 : #define TEST_CONN_REND_PURPOSE (DIR_PURPOSE_FETCH_RENDDESC_V2)
58 : #define TEST_CONN_REND_PURPOSE_SUCCESSFUL (DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2)
59 : #define TEST_CONN_REND_TYPE_2 (CONN_TYPE_AP)
60 : #define TEST_CONN_REND_ADDR_2 "icbavxxhptlr3sfc"
61 :
62 : #define TEST_CONN_RSRC (networkstatus_get_flavor_name(FLAV_MICRODESC))
63 : #define TEST_CONN_RSRC_PURPOSE (DIR_PURPOSE_FETCH_CONSENSUS)
64 : #define TEST_CONN_RSRC_STATE_SUCCESSFUL (DIR_CONN_STATE_CLIENT_FINISHED)
65 : #define TEST_CONN_RSRC_2 (networkstatus_get_flavor_name(FLAV_NS))
66 :
67 : #define TEST_CONN_DL_STATE (DIR_CONN_STATE_CLIENT_READING)
68 :
69 : /* see AP_CONN_STATE_IS_UNATTACHED() */
70 : #define TEST_CONN_UNATTACHED_STATE (AP_CONN_STATE_CIRCUIT_WAIT)
71 : #define TEST_CONN_ATTACHED_STATE (AP_CONN_STATE_CONNECT_WAIT)
72 :
73 : void
74 25 : test_conn_lookup_addr_helper(const char *address, int family, tor_addr_t *addr)
75 : {
76 25 : int rv = 0;
77 :
78 25 : tt_assert(addr);
79 :
80 25 : rv = tor_addr_lookup(address, family, addr);
81 : /* XXXX - should we retry on transient failure? */
82 25 : tt_int_op(rv, OP_EQ, 0);
83 25 : tt_assert(tor_addr_is_loopback(addr));
84 25 : tt_assert(tor_addr_is_v4(addr));
85 :
86 : return;
87 :
88 0 : done:
89 0 : tor_addr_make_null(addr, TEST_CONN_FAMILY);
90 : }
91 :
92 : static void *
93 1 : test_conn_get_basic_setup(const struct testcase_t *tc)
94 : {
95 1 : (void)tc;
96 1 : return test_conn_get_connection(TEST_CONN_STATE, TEST_CONN_TYPE,
97 : TEST_CONN_BASIC_PURPOSE);
98 : }
99 :
100 : static int
101 8 : test_conn_get_basic_teardown(const struct testcase_t *tc, void *arg)
102 : {
103 8 : (void)tc;
104 8 : connection_t *conn = arg;
105 :
106 8 : tt_assert(conn);
107 8 : assert_connection_ok(conn, time(NULL));
108 :
109 : /* teardown the connection as fast as possible */
110 8 : if (conn->linked_conn) {
111 6 : assert_connection_ok(conn->linked_conn, time(NULL));
112 :
113 : /* We didn't call tor_libevent_initialize(), so event_base was NULL,
114 : * so we can't rely on connection_unregister_events() use of event_del().
115 : */
116 6 : if (conn->linked_conn->read_event) {
117 6 : tor_free(conn->linked_conn->read_event);
118 6 : conn->linked_conn->read_event = NULL;
119 : }
120 6 : if (conn->linked_conn->write_event) {
121 6 : tor_free(conn->linked_conn->write_event);
122 6 : conn->linked_conn->write_event = NULL;
123 : }
124 :
125 6 : if (!conn->linked_conn->marked_for_close) {
126 6 : connection_close_immediate(conn->linked_conn);
127 6 : if (CONN_IS_EDGE(conn->linked_conn)) {
128 : /* Suppress warnings about all the stuff we didn't do */
129 4 : TO_EDGE_CONN(conn->linked_conn)->edge_has_sent_end = 1;
130 4 : TO_EDGE_CONN(conn->linked_conn)->end_reason =
131 : END_STREAM_REASON_INTERNAL;
132 4 : if (conn->linked_conn->type == CONN_TYPE_AP) {
133 4 : TO_ENTRY_CONN(conn->linked_conn)->socks_request->has_finished = 1;
134 : }
135 : }
136 6 : connection_mark_for_close(conn->linked_conn);
137 : }
138 :
139 6 : close_closeable_connections();
140 : }
141 :
142 : /* We didn't set the events up properly, so we can't use event_del() in
143 : * close_closeable_connections() > connection_free()
144 : * > connection_unregister_events() */
145 8 : if (conn->read_event) {
146 8 : tor_free(conn->read_event);
147 8 : conn->read_event = NULL;
148 : }
149 8 : if (conn->write_event) {
150 8 : tor_free(conn->write_event);
151 8 : conn->write_event = NULL;
152 : }
153 :
154 8 : if (!conn->marked_for_close) {
155 8 : connection_close_immediate(conn);
156 8 : if (CONN_IS_EDGE(conn)) {
157 : /* Suppress warnings about all the stuff we didn't do */
158 2 : TO_EDGE_CONN(conn)->edge_has_sent_end = 1;
159 2 : TO_EDGE_CONN(conn)->end_reason = END_STREAM_REASON_INTERNAL;
160 2 : if (conn->type == CONN_TYPE_AP) {
161 2 : TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
162 : }
163 : }
164 8 : connection_mark_for_close(conn);
165 : }
166 :
167 8 : close_closeable_connections();
168 :
169 : /* The unit test will fail if we return 0 */
170 8 : return 1;
171 :
172 : /* When conn == NULL, we can't cleanup anything */
173 0 : done:
174 0 : return 0;
175 : }
176 :
177 : static dir_connection_t *
178 9 : test_conn_download_status_add_a_connection(const char *resource)
179 : {
180 9 : dir_connection_t *conn = DOWNCAST(dir_connection_t,
181 : test_conn_get_connection(
182 : TEST_CONN_STATE,
183 : TEST_CONN_TYPE,
184 : TEST_CONN_RSRC_PURPOSE));
185 :
186 9 : tt_assert(conn);
187 9 : assert_connection_ok(&conn->base_, time(NULL));
188 :
189 : /* Replace the existing resource with the one we want */
190 9 : if (resource) {
191 9 : if (conn->requested_resource) {
192 0 : tor_free(conn->requested_resource);
193 : }
194 9 : conn->requested_resource = tor_strdup(resource);
195 9 : assert_connection_ok(&conn->base_, time(NULL));
196 : }
197 :
198 : return conn;
199 :
200 0 : done:
201 0 : test_conn_get_rsrc_teardown(NULL, conn);
202 0 : return NULL;
203 : }
204 :
205 : static void *
206 1 : test_conn_get_rsrc_setup(const struct testcase_t *tc)
207 : {
208 1 : (void)tc;
209 1 : return test_conn_download_status_add_a_connection(TEST_CONN_RSRC);
210 : }
211 :
212 : static int
213 7 : test_conn_get_rsrc_teardown(const struct testcase_t *tc, void *arg)
214 : {
215 7 : int rv = 0;
216 :
217 7 : connection_t *conn = (connection_t *)arg;
218 7 : tt_assert(conn);
219 7 : assert_connection_ok(conn, time(NULL));
220 :
221 7 : if (conn->type == CONN_TYPE_DIR) {
222 5 : dir_connection_t *dir_conn = DOWNCAST(dir_connection_t, arg);
223 :
224 5 : tt_assert(dir_conn);
225 5 : assert_connection_ok(&dir_conn->base_, time(NULL));
226 :
227 : /* avoid a last-ditch attempt to refetch the consensus */
228 5 : dir_conn->base_.state = TEST_CONN_RSRC_STATE_SUCCESSFUL;
229 5 : assert_connection_ok(&dir_conn->base_, time(NULL));
230 : }
231 :
232 : /* connection_free_() cleans up requested_resource */
233 7 : rv = test_conn_get_basic_teardown(tc, conn);
234 :
235 7 : done:
236 7 : return rv;
237 : }
238 :
239 : static void *
240 2 : test_conn_download_status_setup(const struct testcase_t *tc)
241 : {
242 2 : return (void*)tc;
243 : }
244 :
245 : static int
246 2 : test_conn_download_status_teardown(const struct testcase_t *tc, void *arg)
247 : {
248 2 : (void)arg;
249 2 : int rv = 0;
250 :
251 : /* Ignore arg, and just loop through the connection array */
252 16 : SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
253 14 : if (conn) {
254 6 : assert_connection_ok(conn, time(NULL));
255 :
256 : /* connection_free_() cleans up requested_resource */
257 6 : rv = test_conn_get_rsrc_teardown(tc, conn);
258 6 : tt_int_op(rv, OP_EQ, 1);
259 : }
260 14 : } SMARTLIST_FOREACH_END(conn);
261 :
262 2 : done:
263 2 : return rv;
264 : }
265 :
266 : static void *
267 2 : test_conn_proxy_connect_setup(const struct testcase_t *tc)
268 : {
269 2 : return test_conn_get_proxy_or_connection(*(unsigned int *)tc->setup_data);
270 : }
271 :
272 : static int
273 2 : test_conn_proxy_connect_teardown(const struct testcase_t *tc, void *arg)
274 : {
275 2 : (void)tc;
276 2 : or_connection_t *conn = arg;
277 :
278 2 : tt_assert(conn);
279 2 : assert_connection_ok(&conn->base_, time(NULL));
280 :
281 2 : done:
282 2 : return 1;
283 : }
284 :
285 : /* Like connection_ap_make_link(), but does much less */
286 : static connection_t *
287 6 : test_conn_get_linked_connection(connection_t *l_conn, uint8_t state)
288 : {
289 6 : tt_assert(l_conn);
290 6 : assert_connection_ok(l_conn, time(NULL));
291 :
292 : /* AP connections don't seem to have purposes */
293 6 : connection_t *conn = test_conn_get_connection(state, CONN_TYPE_AP,
294 : 0);
295 :
296 6 : tt_assert(conn);
297 6 : assert_connection_ok(conn, time(NULL));
298 :
299 6 : conn->linked = 1;
300 6 : l_conn->linked = 1;
301 6 : conn->linked_conn = l_conn;
302 6 : l_conn->linked_conn = conn;
303 : /* we never opened a real socket, so we can just overwrite it */
304 6 : conn->s = TOR_INVALID_SOCKET;
305 6 : l_conn->s = TOR_INVALID_SOCKET;
306 :
307 6 : assert_connection_ok(conn, time(NULL));
308 6 : assert_connection_ok(l_conn, time(NULL));
309 :
310 6 : return conn;
311 :
312 0 : done:
313 0 : test_conn_download_status_teardown(NULL, NULL);
314 0 : return NULL;
315 : }
316 :
317 : static struct testcase_setup_t test_conn_get_basic_st = {
318 : test_conn_get_basic_setup, test_conn_get_basic_teardown
319 : };
320 :
321 : static struct testcase_setup_t test_conn_get_rsrc_st = {
322 : test_conn_get_rsrc_setup, test_conn_get_rsrc_teardown
323 : };
324 :
325 : static struct testcase_setup_t test_conn_download_status_st = {
326 : test_conn_download_status_setup, test_conn_download_status_teardown
327 : };
328 :
329 : static struct testcase_setup_t test_conn_proxy_connect_st = {
330 : test_conn_proxy_connect_setup, test_conn_proxy_connect_teardown
331 : };
332 :
333 : static void
334 1 : test_conn_get_basic(void *arg)
335 : {
336 1 : connection_t *conn = (connection_t*)arg;
337 1 : tor_addr_t addr, addr2;
338 :
339 1 : tt_assert(conn);
340 1 : assert_connection_ok(conn, time(NULL));
341 :
342 1 : test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY, &addr);
343 1 : tt_assert(!tor_addr_is_null(&addr));
344 1 : test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY, &addr2);
345 1 : tt_assert(!tor_addr_is_null(&addr2));
346 :
347 : /* Check that we get this connection back when we search for it by
348 : * its attributes, but get NULL when we supply a different value. */
349 :
350 1 : tt_assert(connection_get_by_global_id(conn->global_identifier) == conn);
351 1 : tt_ptr_op(connection_get_by_global_id(!conn->global_identifier), OP_EQ,
352 : NULL);
353 :
354 1 : tt_assert(connection_get_by_type(conn->type) == conn);
355 1 : tt_assert(connection_get_by_type(TEST_CONN_TYPE) == conn);
356 1 : tt_ptr_op(connection_get_by_type(!conn->type), OP_EQ, NULL);
357 1 : tt_ptr_op(connection_get_by_type(!TEST_CONN_TYPE), OP_EQ, NULL);
358 :
359 1 : tt_assert(connection_get_by_type_state(conn->type, conn->state)
360 : == conn);
361 1 : tt_assert(connection_get_by_type_state(TEST_CONN_TYPE, TEST_CONN_STATE)
362 : == conn);
363 1 : tt_assert(connection_get_by_type_state(!conn->type, !conn->state)
364 : == NULL);
365 1 : tt_assert(connection_get_by_type_state(!TEST_CONN_TYPE, !TEST_CONN_STATE)
366 : == NULL);
367 :
368 : /* Match on the connection fields themselves */
369 1 : tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
370 : &conn->addr,
371 : conn->port,
372 : conn->purpose)
373 : == conn);
374 : /* Match on the original inputs to the connection */
375 1 : tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE,
376 : &conn->addr,
377 : conn->port,
378 : conn->purpose)
379 : == conn);
380 1 : tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
381 : &addr,
382 : conn->port,
383 : conn->purpose)
384 : == conn);
385 1 : tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
386 : &conn->addr,
387 : TEST_CONN_PORT,
388 : conn->purpose)
389 : == conn);
390 1 : tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
391 : &conn->addr,
392 : conn->port,
393 : TEST_CONN_BASIC_PURPOSE)
394 : == conn);
395 1 : tt_assert(connection_get_by_type_addr_port_purpose(TEST_CONN_TYPE,
396 : &addr,
397 : TEST_CONN_PORT,
398 : TEST_CONN_BASIC_PURPOSE)
399 : == conn);
400 : /* Then try each of the not-matching combinations */
401 1 : tt_assert(connection_get_by_type_addr_port_purpose(!conn->type,
402 : &conn->addr,
403 : conn->port,
404 : conn->purpose)
405 : == NULL);
406 1 : tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
407 : &addr2,
408 : conn->port,
409 : conn->purpose)
410 : == NULL);
411 1 : tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
412 : &conn->addr,
413 : !conn->port,
414 : conn->purpose)
415 : == NULL);
416 1 : tt_assert(connection_get_by_type_addr_port_purpose(conn->type,
417 : &conn->addr,
418 : conn->port,
419 : !conn->purpose)
420 : == NULL);
421 : /* Then try everything not-matching */
422 1 : tt_assert(connection_get_by_type_addr_port_purpose(!conn->type,
423 : &addr2,
424 : !conn->port,
425 : !conn->purpose)
426 : == NULL);
427 1 : tt_assert(connection_get_by_type_addr_port_purpose(!TEST_CONN_TYPE,
428 : &addr2,
429 : !TEST_CONN_PORT,
430 : !TEST_CONN_BASIC_PURPOSE)
431 : == NULL);
432 :
433 1 : done:
434 1 : ;
435 1 : }
436 :
437 : #define sl_is_conn_assert(sl_input, conn) \
438 : do { \
439 : the_sl = (sl_input); \
440 : tt_int_op(smartlist_len((the_sl)), OP_EQ, 1); \
441 : tt_assert(smartlist_get((the_sl), 0) == (conn)); \
442 : smartlist_free(the_sl); the_sl = NULL; \
443 : } while (0)
444 :
445 : #define sl_no_conn_assert(sl_input) \
446 : do { \
447 : the_sl = (sl_input); \
448 : tt_int_op(smartlist_len((the_sl)), OP_EQ, 0); \
449 : smartlist_free(the_sl); the_sl = NULL; \
450 : } while (0)
451 :
452 : static void
453 1 : test_conn_get_rsrc(void *arg)
454 : {
455 1 : dir_connection_t *conn = DOWNCAST(dir_connection_t, arg);
456 1 : smartlist_t *the_sl = NULL;
457 1 : tt_assert(conn);
458 1 : assert_connection_ok(&conn->base_, time(NULL));
459 :
460 1 : sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
461 : conn->base_.purpose,
462 : conn->requested_resource),
463 : conn);
464 1 : sl_is_conn_assert(connection_dir_list_by_purpose_and_resource(
465 : TEST_CONN_RSRC_PURPOSE,
466 : TEST_CONN_RSRC),
467 : conn);
468 1 : sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
469 : !conn->base_.purpose,
470 : ""));
471 1 : sl_no_conn_assert(connection_dir_list_by_purpose_and_resource(
472 : !TEST_CONN_RSRC_PURPOSE,
473 : TEST_CONN_RSRC_2));
474 :
475 1 : sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
476 : conn->base_.purpose,
477 : conn->requested_resource,
478 : conn->base_.state),
479 : conn);
480 1 : sl_is_conn_assert(connection_dir_list_by_purpose_resource_and_state(
481 : TEST_CONN_RSRC_PURPOSE,
482 : TEST_CONN_RSRC,
483 : TEST_CONN_STATE),
484 : conn);
485 1 : sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
486 : !conn->base_.purpose,
487 : "",
488 : !conn->base_.state));
489 1 : sl_no_conn_assert(connection_dir_list_by_purpose_resource_and_state(
490 : !TEST_CONN_RSRC_PURPOSE,
491 : TEST_CONN_RSRC_2,
492 : !TEST_CONN_STATE));
493 :
494 1 : tt_int_op(connection_dir_count_by_purpose_and_resource(
495 : conn->base_.purpose, conn->requested_resource),
496 : OP_EQ, 1);
497 1 : tt_int_op(connection_dir_count_by_purpose_and_resource(
498 : TEST_CONN_RSRC_PURPOSE, TEST_CONN_RSRC),
499 : OP_EQ, 1);
500 1 : tt_int_op(connection_dir_count_by_purpose_and_resource(
501 : !conn->base_.purpose, ""),
502 : OP_EQ, 0);
503 1 : tt_int_op(connection_dir_count_by_purpose_and_resource(
504 : !TEST_CONN_RSRC_PURPOSE, TEST_CONN_RSRC_2),
505 : OP_EQ, 0);
506 :
507 1 : tt_int_op(connection_dir_count_by_purpose_resource_and_state(
508 : conn->base_.purpose, conn->requested_resource,
509 : conn->base_.state),
510 : OP_EQ, 1);
511 1 : tt_int_op(connection_dir_count_by_purpose_resource_and_state(
512 : TEST_CONN_RSRC_PURPOSE, TEST_CONN_RSRC, TEST_CONN_STATE),
513 : OP_EQ, 1);
514 1 : tt_int_op(connection_dir_count_by_purpose_resource_and_state(
515 : !conn->base_.purpose, "", !conn->base_.state),
516 : OP_EQ, 0);
517 1 : tt_int_op(connection_dir_count_by_purpose_resource_and_state(
518 : !TEST_CONN_RSRC_PURPOSE, TEST_CONN_RSRC_2, !TEST_CONN_STATE),
519 : OP_EQ, 0);
520 :
521 1 : done:
522 1 : smartlist_free(the_sl);
523 1 : }
524 :
525 : static void
526 2 : test_conn_download_status(void *arg)
527 : {
528 2 : dir_connection_t *conn = NULL;
529 2 : dir_connection_t *conn2 = NULL;
530 2 : dir_connection_t *conn4 = NULL;
531 2 : connection_t *ap_conn = NULL;
532 :
533 2 : const struct testcase_t *tc = arg;
534 4 : consensus_flavor_t usable_flavor =
535 2 : networkstatus_parse_flavor_name((const char*) tc->setup_data);
536 :
537 : /* The "other flavor" trick only works if there are two flavors */
538 2 : tor_assert(N_CONSENSUS_FLAVORS == 2);
539 2 : consensus_flavor_t other_flavor = ((usable_flavor == FLAV_NS)
540 : ? FLAV_MICRODESC
541 2 : : FLAV_NS);
542 2 : const char *res = networkstatus_get_flavor_name(usable_flavor);
543 2 : const char *other_res = networkstatus_get_flavor_name(other_flavor);
544 :
545 : /* no connections */
546 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0);
547 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
548 : 0);
549 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
550 : TEST_CONN_RSRC_PURPOSE, res),
551 : OP_EQ, 0);
552 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
553 : TEST_CONN_RSRC_PURPOSE, other_res),
554 : OP_EQ, 0);
555 :
556 : /* one connection, not downloading */
557 2 : conn = test_conn_download_status_add_a_connection(res);
558 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0);
559 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
560 : 0);
561 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
562 : TEST_CONN_RSRC_PURPOSE, res),
563 : OP_EQ, 1);
564 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
565 : TEST_CONN_RSRC_PURPOSE, other_res),
566 : OP_EQ, 0);
567 :
568 : /* one connection, downloading but not linked (not possible on a client,
569 : * but possible on a relay) */
570 2 : conn->base_.state = TEST_CONN_DL_STATE;
571 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0);
572 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
573 : 0);
574 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
575 : TEST_CONN_RSRC_PURPOSE, res),
576 : OP_EQ, 1);
577 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
578 : TEST_CONN_RSRC_PURPOSE, other_res),
579 : OP_EQ, 0);
580 :
581 : /* one connection, downloading and linked, but not yet attached */
582 2 : ap_conn = test_conn_get_linked_connection(TO_CONN(conn),
583 : TEST_CONN_UNATTACHED_STATE);
584 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0);
585 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
586 : 0);
587 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
588 : TEST_CONN_RSRC_PURPOSE, res),
589 : OP_EQ, 1);
590 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
591 : TEST_CONN_RSRC_PURPOSE, other_res),
592 : OP_EQ, 0);
593 :
594 : /* one connection, downloading and linked and attached */
595 2 : ap_conn->state = TEST_CONN_ATTACHED_STATE;
596 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1);
597 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
598 : 0);
599 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
600 : TEST_CONN_RSRC_PURPOSE, res),
601 : OP_EQ, 1);
602 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
603 : TEST_CONN_RSRC_PURPOSE, other_res),
604 : OP_EQ, 0);
605 :
606 : /* one connection, linked and attached but not downloading */
607 2 : conn->base_.state = TEST_CONN_STATE;
608 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0);
609 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
610 : 0);
611 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
612 : TEST_CONN_RSRC_PURPOSE, res),
613 : OP_EQ, 1);
614 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
615 : TEST_CONN_RSRC_PURPOSE, other_res),
616 : OP_EQ, 0);
617 :
618 : /* two connections, both not downloading */
619 2 : conn2 = test_conn_download_status_add_a_connection(res);
620 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0);
621 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
622 : 0);
623 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
624 : TEST_CONN_RSRC_PURPOSE, res),
625 : OP_EQ, 2);
626 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
627 : TEST_CONN_RSRC_PURPOSE, other_res),
628 : OP_EQ, 0);
629 :
630 : /* two connections, one downloading */
631 2 : conn->base_.state = TEST_CONN_DL_STATE;
632 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1);
633 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
634 : 0);
635 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
636 : TEST_CONN_RSRC_PURPOSE, res),
637 : OP_EQ, 2);
638 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
639 : TEST_CONN_RSRC_PURPOSE, other_res),
640 : OP_EQ, 0);
641 2 : conn->base_.state = TEST_CONN_STATE;
642 :
643 : /* more connections, all not downloading */
644 : /* ignore the return value, it's free'd using the connection list */
645 2 : (void)test_conn_download_status_add_a_connection(res);
646 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 0);
647 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
648 : 0);
649 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
650 : TEST_CONN_RSRC_PURPOSE, res),
651 : OP_EQ, 3);
652 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
653 : TEST_CONN_RSRC_PURPOSE, other_res),
654 : OP_EQ, 0);
655 :
656 : /* more connections, one downloading */
657 2 : conn->base_.state = TEST_CONN_DL_STATE;
658 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1);
659 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
660 : 0);
661 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
662 : TEST_CONN_RSRC_PURPOSE, res),
663 : OP_EQ, 3);
664 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
665 : TEST_CONN_RSRC_PURPOSE, other_res),
666 : OP_EQ, 0);
667 :
668 : /* more connections, two downloading (should never happen, but needs
669 : * to be tested for completeness) */
670 2 : conn2->base_.state = TEST_CONN_DL_STATE;
671 : /* ignore the return value, it's free'd using the connection list */
672 2 : (void)test_conn_get_linked_connection(TO_CONN(conn2),
673 : TEST_CONN_ATTACHED_STATE);
674 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1);
675 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
676 : 0);
677 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
678 : TEST_CONN_RSRC_PURPOSE, res),
679 : OP_EQ, 3);
680 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
681 : TEST_CONN_RSRC_PURPOSE, other_res),
682 : OP_EQ, 0);
683 2 : conn->base_.state = TEST_CONN_STATE;
684 :
685 : /* more connections, a different one downloading */
686 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1);
687 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
688 : 0);
689 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
690 : TEST_CONN_RSRC_PURPOSE, res),
691 : OP_EQ, 3);
692 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
693 : TEST_CONN_RSRC_PURPOSE, other_res),
694 : OP_EQ, 0);
695 :
696 : /* a connection for the other flavor (could happen if a client is set to
697 : * cache directory documents), one preferred flavor downloading
698 : */
699 2 : conn4 = test_conn_download_status_add_a_connection(other_res);
700 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1);
701 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
702 : 0);
703 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
704 : TEST_CONN_RSRC_PURPOSE, res),
705 : OP_EQ, 3);
706 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
707 : TEST_CONN_RSRC_PURPOSE, other_res),
708 : OP_EQ, 1);
709 :
710 : /* a connection for the other flavor (could happen if a client is set to
711 : * cache directory documents), both flavors downloading
712 : */
713 2 : conn4->base_.state = TEST_CONN_DL_STATE;
714 : /* ignore the return value, it's free'd using the connection list */
715 2 : (void)test_conn_get_linked_connection(TO_CONN(conn4),
716 : TEST_CONN_ATTACHED_STATE);
717 2 : tt_int_op(networkstatus_consensus_is_already_downloading(res), OP_EQ, 1);
718 2 : tt_int_op(networkstatus_consensus_is_already_downloading(other_res), OP_EQ,
719 : 1);
720 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
721 : TEST_CONN_RSRC_PURPOSE, res),
722 : OP_EQ, 3);
723 2 : tt_int_op(connection_dir_count_by_purpose_and_resource(
724 : TEST_CONN_RSRC_PURPOSE, other_res),
725 : OP_EQ, 1);
726 :
727 2 : done:
728 2 : /* the teardown function removes all the connections in the global list*/;
729 2 : }
730 :
731 : static void
732 1 : test_conn_https_proxy_connect(void *arg)
733 : {
734 1 : size_t sz;
735 1 : char *buf = NULL;
736 1 : or_connection_t *conn = arg;
737 :
738 1 : MOCK(connection_or_change_state, mock_connection_or_change_state);
739 :
740 1 : tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_HTTPS_WANT_CONNECT_OK);
741 :
742 1 : buf = buf_get_contents(conn->base_.outbuf, &sz);
743 1 : tt_str_op(buf, OP_EQ, "CONNECT 127.0.0.1:12345 HTTP/1.0\r\n\r\n");
744 :
745 1 : done:
746 1 : UNMOCK(connection_or_change_state);
747 1 : tor_free(buf);
748 1 : }
749 :
750 : static int handshake_start_called = 0;
751 :
752 : static int
753 1 : handshake_start(or_connection_t *conn, int receiving)
754 : {
755 1 : (void)receiving;
756 :
757 1 : tor_assert(conn);
758 :
759 1 : handshake_start_called = 1;
760 1 : return 0;
761 : }
762 :
763 : static void
764 1 : test_conn_haproxy_proxy_connect(void *arg)
765 : {
766 1 : size_t sz;
767 1 : char *buf = NULL;
768 1 : or_connection_t *conn = arg;
769 :
770 1 : MOCK(connection_or_change_state, mock_connection_or_change_state);
771 1 : MOCK(connection_tls_start_handshake, handshake_start);
772 :
773 1 : tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_HAPROXY_WAIT_FOR_FLUSH);
774 :
775 1 : buf = buf_get_contents(conn->base_.outbuf, &sz);
776 1 : tt_str_op(buf, OP_EQ, "PROXY TCP4 0.0.0.0 127.0.0.1 0 12345\r\n");
777 :
778 1 : connection_or_finished_flushing(conn);
779 :
780 1 : tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_CONNECTED);
781 1 : tt_int_op(handshake_start_called, OP_EQ, 1);
782 :
783 1 : done:
784 1 : UNMOCK(connection_or_change_state);
785 1 : UNMOCK(connection_tls_start_handshake);
786 1 : tor_free(buf);
787 1 : }
788 :
789 : static node_t test_node;
790 :
791 : static node_t *
792 0 : mock_node_get_mutable_by_id(const char *digest)
793 : {
794 0 : (void) digest;
795 0 : static routerinfo_t node_ri;
796 0 : memset(&node_ri, 0, sizeof(node_ri));
797 :
798 0 : test_node.ri = &node_ri;
799 0 : memset(test_node.identity, 'c', sizeof(test_node.identity));
800 :
801 0 : tor_addr_parse(&node_ri.ipv4_addr, "18.0.0.1");
802 0 : node_ri.ipv4_orport = 1;
803 :
804 0 : return &test_node;
805 : }
806 :
807 : static const node_t *
808 0 : mock_node_get_by_id(const char *digest)
809 : {
810 0 : (void) digest;
811 0 : memset(test_node.identity, 'c', sizeof(test_node.identity));
812 0 : return &test_node;
813 : }
814 :
815 : /* Test whether we correctly track failed connections between relays. */
816 : static void
817 1 : test_failed_orconn_tracker(void *arg)
818 : {
819 1 : (void) arg;
820 :
821 1 : int can_connect;
822 1 : time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
823 1 : (void) now;
824 :
825 1 : update_approx_time(now);
826 :
827 : /* Prepare the OR connection that will be used in this test */
828 1 : or_connection_t or_conn;
829 1 : tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.canonical_orport.addr,
830 : "18.0.0.1"));
831 1 : tt_int_op(AF_INET,OP_EQ, tor_addr_parse(&or_conn.base_.addr, "18.0.0.1"));
832 1 : or_conn.base_.port = 1;
833 1 : memset(or_conn.identity_digest, 'c', sizeof(or_conn.identity_digest));
834 :
835 : /* Check whether we can connect with an empty failure cache:
836 : * this should succeed */
837 1 : can_connect = should_connect_to_relay(&or_conn);
838 1 : tt_int_op(can_connect, OP_EQ, 1);
839 :
840 : /* Now add the destination to the failure cache */
841 1 : note_or_connect_failed(&or_conn);
842 :
843 : /* Check again: now it shouldn't connect */
844 1 : can_connect = should_connect_to_relay(&or_conn);
845 1 : tt_int_op(can_connect, OP_EQ, 0);
846 :
847 : /* Move time forward and check again: the cache should have been cleared and
848 : * now it should connect */
849 1 : now += 3600;
850 1 : update_approx_time(now);
851 1 : can_connect = should_connect_to_relay(&or_conn);
852 1 : tt_int_op(can_connect, OP_EQ, 1);
853 :
854 : /* Now mock the node_get_*by_id() functions to start using the node subsystem
855 : * optimization. */
856 1 : MOCK(node_get_by_id, mock_node_get_by_id);
857 1 : MOCK(node_get_mutable_by_id, mock_node_get_mutable_by_id);
858 :
859 : /* Since we just started using the node subsystem it will allow connections
860 : * now */
861 1 : can_connect = should_connect_to_relay(&or_conn);
862 1 : tt_int_op(can_connect, OP_EQ, 1);
863 :
864 : /* Mark it as failed */
865 1 : note_or_connect_failed(&or_conn);
866 :
867 : /* Check that it shouldn't connect now */
868 1 : can_connect = should_connect_to_relay(&or_conn);
869 1 : tt_int_op(can_connect, OP_EQ, 0);
870 :
871 : /* Move time forward and check again: now it should connect */
872 1 : now += 3600;
873 1 : update_approx_time(now);
874 1 : can_connect = should_connect_to_relay(&or_conn);
875 1 : tt_int_op(can_connect, OP_EQ, 1);
876 :
877 1 : done:
878 1 : ;
879 1 : }
880 :
881 : static void
882 1 : test_conn_describe(void *arg)
883 : {
884 1 : (void)arg;
885 1 : or_options_t *options = get_options_mutable();
886 1 : options->SafeLogging_ = SAFELOG_SCRUB_ALL;
887 :
888 : // Let's start with a listener connection since they're simple.
889 1 : connection_t *conn = connection_new(CONN_TYPE_OR_LISTENER, AF_INET);
890 1 : tor_addr_parse(&conn->addr, "44.22.11.11");
891 1 : conn->port = 80;
892 1 : tt_str_op(connection_describe(conn), OP_EQ,
893 : "OR listener connection (ready) on 44.22.11.11:80");
894 : // If the address is unspec, we should still work.
895 1 : tor_addr_make_unspec(&conn->addr);
896 1 : tt_str_op(connection_describe(conn), OP_EQ,
897 : "OR listener connection (ready) on <unset>:80");
898 : // Try making the address null.
899 1 : tor_addr_make_null(&conn->addr, AF_INET);
900 1 : tt_str_op(connection_describe(conn), OP_EQ,
901 : "OR listener connection (ready) on 0.0.0.0:80");
902 : // What if the address is uninitialized? (This can happen if we log about the
903 : // connection before we set the address.)
904 1 : memset(&conn->addr, 0, sizeof(conn->addr));
905 1 : tt_str_op(connection_describe(conn), OP_EQ,
906 : "OR listener connection (ready) on <unset>:80");
907 1 : connection_free_minimal(conn);
908 :
909 : // Try a unix socket.
910 1 : conn = connection_new(CONN_TYPE_CONTROL_LISTENER, AF_UNIX);
911 1 : conn->address = tor_strdup("/a/path/that/could/exist");
912 1 : tt_str_op(connection_describe(conn), OP_EQ,
913 : "Control listener connection (ready) on /a/path/that/could/exist");
914 1 : connection_free_minimal(conn);
915 :
916 : // Try an IPv6 address.
917 1 : conn = connection_new(CONN_TYPE_AP_LISTENER, AF_INET6);
918 1 : tor_addr_parse(&conn->addr, "ff00::3");
919 1 : conn->port = 9050;
920 1 : tt_str_op(connection_describe(conn), OP_EQ,
921 : "Socks listener connection (ready) on [ff00::3]:9050");
922 1 : connection_free_minimal(conn);
923 :
924 : // Now let's mess with exit connections. They have some special issues.
925 1 : options->SafeLogging_ = SAFELOG_SCRUB_NONE;
926 1 : conn = connection_new(CONN_TYPE_EXIT, AF_INET);
927 : // If address and state are unset, we should say SOMETHING.
928 1 : tt_str_op(connection_describe(conn), OP_EQ,
929 : "Exit connection (uninitialized) to <unset> (DNS lookup pending)");
930 : // Now suppose that the address is set but we haven't resolved the hostname.
931 1 : conn->port = 443;
932 1 : conn->address = tor_strdup("www.torproject.org");
933 1 : conn->state = EXIT_CONN_STATE_RESOLVING;
934 1 : tt_str_op(connection_describe(conn), OP_EQ,
935 : "Exit connection (waiting for dest info) to "
936 : "www.torproject.org:443 (DNS lookup pending)");
937 : // Now give it a hostname!
938 1 : tor_addr_parse(&conn->addr, "192.168.8.8");
939 1 : conn->state = EXIT_CONN_STATE_OPEN;
940 1 : tt_str_op(connection_describe(conn), OP_EQ,
941 : "Exit connection (open) to 192.168.8.8:443");
942 : // But what if safelogging is on?
943 1 : options->SafeLogging_ = SAFELOG_SCRUB_RELAY;
944 1 : tt_str_op(connection_describe(conn), OP_EQ,
945 : "Exit connection (open) to [scrubbed]");
946 1 : connection_free_minimal(conn);
947 :
948 : // Now at last we look at OR addresses, which are complicated.
949 1 : conn = connection_new(CONN_TYPE_OR, AF_INET6);
950 1 : conn->state = OR_CONN_STATE_OPEN;
951 1 : conn->port = 8080;
952 1 : tor_addr_parse(&conn->addr, "[ffff:3333:1111::2]");
953 : // This should get scrubbed, since the lack of a set ID means we might be
954 : // talking to a client.
955 1 : tt_str_op(connection_describe(conn), OP_EQ,
956 : "OR connection (open) with [scrubbed]");
957 : // But now suppose we aren't safelogging? We'll get the address then.
958 1 : options->SafeLogging_ = SAFELOG_SCRUB_NONE;
959 1 : tt_str_op(connection_describe(conn), OP_EQ,
960 : "OR connection (open) with [ffff:3333:1111::2]:8080");
961 : // Suppose we have an ID, so we know it isn't a client.
962 1 : TO_OR_CONN(conn)->identity_digest[3] = 7;
963 1 : options->SafeLogging_ = SAFELOG_SCRUB_RELAY; // back to safelogging.
964 1 : tt_str_op(connection_describe(conn), OP_EQ,
965 : "OR connection (open) with [ffff:3333:1111::2]:8080 "
966 : "ID=<none> RSA_ID=0000000700000000000000000000000000000000");
967 : // Add a 'canonical address' that is the same as the one we have.
968 1 : tor_addr_parse(&TO_OR_CONN(conn)->canonical_orport.addr,
969 : "[ffff:3333:1111::2]");
970 1 : TO_OR_CONN(conn)->canonical_orport.port = 8080;
971 1 : tt_str_op(connection_describe(conn), OP_EQ,
972 : "OR connection (open) with [ffff:3333:1111::2]:8080 "
973 : "ID=<none> RSA_ID=0000000700000000000000000000000000000000");
974 : // Add a different 'canonical address'
975 1 : tor_addr_parse(&TO_OR_CONN(conn)->canonical_orport.addr,
976 : "[ffff:3333:1111::8]");
977 1 : tt_str_op(connection_describe(conn), OP_EQ,
978 : "OR connection (open) with [ffff:3333:1111::2]:8080 "
979 : "ID=<none> RSA_ID=0000000700000000000000000000000000000000 "
980 : "canonical_addr=[ffff:3333:1111::8]:8080");
981 :
982 : // Clear identity_digest so that free_minimal won't complain.
983 1 : memset(TO_OR_CONN(conn)->identity_digest, 0, DIGEST_LEN);
984 :
985 1 : done:
986 1 : connection_free_minimal(conn);
987 1 : }
988 :
989 : #ifndef COCCI
990 : #define CONNECTION_TESTCASE(name, fork, setup) \
991 : { #name, test_conn_##name, fork, &setup, NULL }
992 :
993 : #define STR(x) #x
994 : /* where arg is an expression (constant, variable, compound expression) */
995 : #define CONNECTION_TESTCASE_ARG(name, extra, fork, setup, arg) \
996 : { STR(name)"/"extra, \
997 : test_conn_##name, \
998 : (fork), \
999 : &(setup), \
1000 : (void *)(arg) }
1001 : #endif /* !defined(COCCI) */
1002 :
1003 : static const unsigned int PROXY_CONNECT_ARG = PROXY_CONNECT;
1004 : static const unsigned int PROXY_HAPROXY_ARG = PROXY_HAPROXY;
1005 :
1006 : struct testcase_t connection_tests[] = {
1007 : CONNECTION_TESTCASE(get_basic, TT_FORK, test_conn_get_basic_st),
1008 : CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st),
1009 :
1010 : CONNECTION_TESTCASE_ARG(download_status, "microdesc", TT_FORK,
1011 : test_conn_download_status_st, "microdesc"),
1012 : CONNECTION_TESTCASE_ARG(download_status, "ns", TT_FORK,
1013 : test_conn_download_status_st, "ns"),
1014 :
1015 : CONNECTION_TESTCASE_ARG(https_proxy_connect, "https", TT_FORK,
1016 : test_conn_proxy_connect_st, &PROXY_CONNECT_ARG),
1017 : CONNECTION_TESTCASE_ARG(haproxy_proxy_connect, "haproxy", TT_FORK,
1018 : test_conn_proxy_connect_st, &PROXY_HAPROXY_ARG),
1019 :
1020 : //CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
1021 : { "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL },
1022 : { "describe", test_conn_describe, TT_FORK, NULL, NULL },
1023 : END_OF_TESTCASES
1024 : };
|