123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- /* Copyright (c) 2018, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- /**
- * \file test_bridges.c
- * \brief Unittests for code in src/or/bridges.c
- **/
- #define TOR_BRIDGES_PRIVATE
- #define PT_PRIVATE /* Only needed for the mock_* items below */
- #include <stdbool.h>
- #include "or.h"
- #include "address.h"
- #include "bridges.h"
- #include "config.h"
- #include "container.h"
- #include "transports.h"
- #include "util.h"
- /* Test suite stuff */
- #include "test.h"
- /**
- * A mocked transport_t, constructed via mock_transport_get_by_name().
- */
- static transport_t *mock_transport = NULL;
- /**
- * Mock transport_get_by_name() to simply return a transport_t for the
- * transport name that was input to it.
- */
- static transport_t *
- mock_transport_get_by_name(const char *name)
- {
- tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
- uint16_t port = 9999;
- int socksv = 9;
- char *args = tor_strdup("foo=bar");
- if (!mock_transport) {
- tor_addr_parse(addr, "99.99.99.99");
- mock_transport = transport_new(addr, port, name, socksv, args);
- }
- tor_free(addr);
- tor_free(args);
- return mock_transport;
- }
- #undef PT_PRIVATE /* defined(PT_PRIVATE) */
- /**
- * Test helper: Add a variety of bridges to our global bridgelist.
- */
- static void
- helper_add_bridges_to_bridgelist(void *arg)
- {
- /* Note: the two bridges which do not have specified fingerprints will be
- * internally stored as both having the same fingerprint of all-zero bytes.
- */
- (void)arg;
- char *bridge0 = tor_strdup("6.6.6.6:6666");
- char *bridge1 = tor_strdup("6.6.6.7:6667 "
- "A10C4F666D27364036B562823E5830BC448E046A");
- char *bridge2 = tor_strdup("obfs4 198.245.60.51:443 "
- "752CF7825B3B9EA6A98C83AC41F7099D67007EA5 "
- "cert=xpmQtKUqQ/6v5X7ijgYE/f03+l2/EuQ1dexjyUhh16wQlu/"
- "cpXUGalmhDIlhuiQPNEKmKw iat-mode=0");
- char *bridge3 = tor_strdup("banana 5.5.5.5:5555 "
- "9D6AE1BD4FDF39721CE908966E79E16F9BFCCF2F");
- char *bridge4 = tor_strdup("obfs4 1.2.3.4:1234 "
- "foo=abcdefghijklmnopqrstuvwxyz");
- char *bridge5 = tor_strdup("apple 4.4.4.4:4444 "
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
- "foo=abcdefghijklmnopqrstuvwxyz");
- mark_bridge_list();
- #define ADD_BRIDGE(bridge) \
- bridge_line_t *bridge_line_ ##bridge = parse_bridge_line(bridge); \
- if (!bridge_line_ ##bridge) { \
- printf("Unparseable bridge line: '%s'", #bridge); \
- } else { \
- bridge_add_from_config(bridge_line_ ##bridge); \
- } \
- tor_free(bridge);
- ADD_BRIDGE(bridge0);
- ADD_BRIDGE(bridge1);
- ADD_BRIDGE(bridge2);
- ADD_BRIDGE(bridge3);
- ADD_BRIDGE(bridge4);
- ADD_BRIDGE(bridge5);
- #undef ADD_BRIDGES
- sweep_bridge_list();
- }
- /**
- * Make sure our test helper works too.
- */
- static void
- test_bridges_helper_func_add_bridges_to_bridgelist(void *arg)
- {
- helper_add_bridges_to_bridgelist(arg);
- tt_finished();
- done:
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling bridge_list_get() should create a new bridgelist if we
- * didn't have one before.
- */
- static void
- test_bridges_bridge_list_get_creates_new_bridgelist(void *arg)
- {
- const smartlist_t *bridgelist = bridge_list_get();
- (void)arg;
- tt_ptr_op(bridgelist, OP_NE, NULL);
- done:
- return;
- }
- /**
- * Calling clear_bridge_list() should remove all bridges from the bridgelist.
- */
- static void
- test_bridges_clear_bridge_list(void *arg)
- {
- const smartlist_t *bridgelist;
- const smartlist_t *bridgelist_after;
- const bridge_info_t *bridge;
- const bridge_info_t *bridge_after;
- helper_add_bridges_to_bridgelist(arg);
- bridgelist = bridge_list_get();
- tt_ptr_op(bridgelist, OP_NE, NULL);
- bridge = smartlist_get(bridgelist, 0);
- tt_ptr_op(bridge, OP_NE, NULL);
- clear_bridge_list();
- bridgelist_after = bridge_list_get();
- tt_ptr_op(bridgelist_after, OP_NE, NULL);
- bridge_after = smartlist_get(bridgelist, 0);
- // There now shouldn't be a first bridge
- tt_ptr_op(bridge_after, OP_EQ, NULL);
- done:
- return;
- }
- /**
- * Calling bridge_get_addrport() should give me the address and port
- * of the bridge. In this case, we sort the smartlist of bridges on
- * fingerprints and choose the first one.
- */
- static void
- test_bridges_bridge_get_addrport(void *arg)
- {
- smartlist_t *bridgelist;
- const bridge_info_t *bridge;
- const tor_addr_port_t *addrport;
- helper_add_bridges_to_bridgelist(arg);
- bridgelist = (smartlist_t*)bridge_list_get();
- tt_ptr_op(bridgelist, OP_NE, NULL);
- // This should be the bridge at 6.6.6.6:6666 with fingerprint
- // 0000000000000000000000000000000000000000
- bridge = smartlist_get(bridgelist, 0);
- tt_ptr_op(bridge, OP_NE, NULL);
- addrport = bridge_get_addr_port(bridge);
- tt_int_op(addrport->port, OP_EQ, 6666);
- done:
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling get_configured_bridge_by_orports_digest() with two
- * configured bridge orports and an invalid digest should return the
- * bridge of the first addrport in the list.
- */
- static void
- test_bridges_get_configured_bridge_by_orports_digest(void *arg)
- {
- smartlist_t *orports = NULL;
- const smartlist_t *bridgelist;
- const bridge_info_t *bridge1;
- const bridge_info_t *bridge2;
- const bridge_info_t *ret;
- tor_addr_port_t *addrport1;
- tor_addr_port_t *addrport2;
- const char *digest;
- helper_add_bridges_to_bridgelist(arg);
- bridgelist = bridge_list_get();
- tt_ptr_op(bridgelist, OP_NE, NULL);
- // This should be the bridge at 6.6.6.6:6666 with fingerprint
- // 0000000000000000000000000000000000000000
- bridge1 = smartlist_get(bridgelist, 0);
- tt_ptr_op(bridge1, OP_NE, NULL);
- // This should be the bridge at 6.6.6.7:6667 with fingerprint
- // A10C4F666D27364036B562823E5830BC448E046A
- bridge2 = smartlist_get(bridgelist, 1);
- tt_ptr_op(bridge2, OP_NE, NULL);
- addrport1 = (tor_addr_port_t*)bridge_get_addr_port(bridge1);
- tt_int_op(addrport1->port, OP_EQ, 6666);
- addrport2 = (tor_addr_port_t*)bridge_get_addr_port(bridge2);
- tt_int_op(addrport2->port, OP_EQ, 6667);
- orports = smartlist_new();
- smartlist_add(orports, addrport1);
- smartlist_add(orports, addrport2);
- digest = "zzzzzzzzzzzzzzzz";
- ret = get_configured_bridge_by_orports_digest(digest, orports);
- tt_ptr_op(ret, OP_NE, NULL);
- tt_assert(tor_addr_port_eq(addrport1, bridge_get_addr_port(ret)));
- done:
- smartlist_free(orports);
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling get_configured_bridge_by_addr_port_digest() with a digest that we do
- * have and an addr:port pair we don't should return the bridge for that
- * digest.
- */
- static void
- test_bridges_get_configured_bridge_by_addr_port_digest_digest_only(void *arg)
- {
- char digest[DIGEST_LEN];
- bridge_info_t *bridge;
- const char fingerprint[HEX_DIGEST_LEN] =
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
- tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
- char ret_addr[16];
- uint16_t port = 11111;
- int ret;
- helper_add_bridges_to_bridgelist(arg);
- // We don't actually have a bridge with this addr:port pair
- base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
- ret = tor_addr_parse(addr, "111.111.111.111");
- tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
- bridge = get_configured_bridge_by_addr_port_digest(addr, port, digest);
- tt_ptr_op(bridge, OP_NE, NULL);
- tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
- tt_str_op("4.4.4.4", OP_EQ, ret_addr);
- done:
- tor_free(addr);
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling get_configured_bridge_by_addr_port_digest() with only an
- * addr:port (i.e. digest set to NULL) should return the bridge for
- * that digest when there is such a bridge.
- */
- static void
- test_bridges_get_configured_bridge_by_addr_port_digest_address_only(void *arg)
- {
- bridge_info_t *bridge;
- tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
- char ret_addr[16];
- uint16_t port = 6666;
- int ret;
- helper_add_bridges_to_bridgelist(arg);
- ret = tor_addr_parse(addr, "6.6.6.6");
- tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
- bridge = get_configured_bridge_by_addr_port_digest(addr, port, NULL);
- tt_ptr_op(bridge, OP_NE, NULL);
- tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
- tt_str_op("6.6.6.6", OP_EQ, ret_addr);
- done:
- tor_free(addr);
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that
- * we do have, and an addr:port pair we don't have, should return NULL.
- */
- static void
- test_bridges_get_configured_bridge_by_exact_addr_port_digest_donly(void *arg)
- {
- char digest[DIGEST_LEN];
- bridge_info_t *bridge;
- const char fingerprint[HEX_DIGEST_LEN] =
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
- tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
- uint16_t port = 11111;
- int ret;
- helper_add_bridges_to_bridgelist(arg);
- // We don't actually have a bridge with this addr:port pair
- base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
- ret = tor_addr_parse(addr, "111.111.111.111");
- tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
- bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest);
- tt_ptr_op(bridge, OP_EQ, NULL);
- done:
- tor_free(addr);
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling get_configured_bridge_by_exact_addr_port_digest() with a digest that
- * we do have, and an addr:port pair we do have, should return the bridge.
- */
- static void
- test_bridges_get_configured_bridge_by_exact_addr_port_digest_both(void *arg)
- {
- char digest[DIGEST_LEN];
- bridge_info_t *bridge;
- const char fingerprint[HEX_DIGEST_LEN] =
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
- tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
- uint16_t port = 4444;
- char ret_addr[16];
- int ret;
- helper_add_bridges_to_bridgelist(arg);
- base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
- ret = tor_addr_parse(addr, "4.4.4.4");
- tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
- bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, digest);
- tt_ptr_op(bridge, OP_NE, NULL);
- tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
- tt_str_op("4.4.4.4", OP_EQ, ret_addr);
- done:
- tor_free(addr);
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling get_configured_bridge_by_exact_addr_port_digest() with no digest,
- * and an addr:port pair we do have, should return the bridge.
- */
- static void
- test_bridges_get_configured_bridge_by_exact_addr_port_digest_aonly(void *arg)
- {
- bridge_info_t *bridge;
- tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
- uint16_t port = 4444;
- char ret_addr[16];
- int ret;
- helper_add_bridges_to_bridgelist(arg);
- ret = tor_addr_parse(addr, "4.4.4.4");
- tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
- bridge = get_configured_bridge_by_exact_addr_port_digest(addr, port, NULL);
- tt_ptr_op(bridge, OP_NE, NULL);
- tor_addr_to_str(ret_addr, &bridge_get_addr_port(bridge)->addr, 16, 0);
- tt_str_op("4.4.4.4", OP_EQ, ret_addr);
- done:
- tor_free(addr);
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling find_bridge_by_digest() when we have a bridge with a known
- * identity digest should return the bridge's information.
- */
- static void
- test_bridges_find_bridge_by_digest_known(void *arg)
- {
- char digest1[DIGEST_LEN];
- bridge_info_t *bridge;
- const char fingerprint[HEX_DIGEST_LEN] =
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
- helper_add_bridges_to_bridgelist(arg);
- base16_decode(digest1, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN);
- bridge = find_bridge_by_digest(digest1);
- tt_ptr_op(bridge, OP_NE, NULL);
- /* We have to call bridge_get_rsa_id_digest() here because the bridge_info_t
- * struct is opaquely defined in bridges.h. */
- const uint8_t *digest2 = bridge_get_rsa_id_digest(bridge);
- tt_mem_op((char*)digest2, OP_EQ, digest1, DIGEST_LEN);
- done:
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling find_bridge_by_digest() when we do NOT have a bridge with that
- * identity digest should return NULL.
- */
- static void
- test_bridges_find_bridge_by_digest_unknown(void *arg)
- {
- const char *fingerprint = "cccccccccccccccccccccccccccccccccccccccc";
- bridge_info_t *bridge;
- helper_add_bridges_to_bridgelist(arg);
- bridge = find_bridge_by_digest(fingerprint);
- tt_ptr_op(bridge, OP_EQ, NULL);
- done:
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling bridge_resolve_conflicts() with an identical bridge to one we've
- * already configure should mark the pre-configured bridge for removal.
- */
- static void
- test_bridges_bridge_resolve_conflicts(void *arg)
- {
- tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
- uint16_t port = 4444;
- const char *digest = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
- const char *transport = "apple";
- int ret;
- helper_add_bridges_to_bridgelist(arg);
- ret = tor_addr_parse(addr, "4.4.4.4");
- tt_int_op(ret, OP_EQ, 2); // it returns the address family on success
- bridge_resolve_conflicts((const tor_addr_t*)addr, port, digest, transport);
- /* The bridge should now be marked for removal, and removed when we sweep the
- * bridge_list */
- sweep_bridge_list();
- ret = addr_is_a_configured_bridge((const tor_addr_t*)addr, port, digest);
- tt_int_op(ret, OP_EQ, 0);
- done:
- tor_free(addr);
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling transport_is_needed() with a transport we do need ("obfs4") and a
- * bogus transport that we don't need should return 1 and 0, respectively.
- */
- static void
- test_bridges_transport_is_needed(void *arg)
- {
- int ret;
- helper_add_bridges_to_bridgelist(arg);
- ret = transport_is_needed("obfs4");
- tt_int_op(ret, OP_EQ, 1);
- ret = transport_is_needed("apowefjaoewpaief");
- tt_int_op(ret, OP_EQ, 0);
- done:
- mark_bridge_list();
- sweep_bridge_list();
- }
- /**
- * Calling get_transport_by_bridge_addrport() with the address and port of a
- * configured bridge which uses a pluggable transport when there is no global
- * transport_list should return -1 and the transport_t should be NULL.
- */
- static void
- test_bridges_get_transport_by_bridge_addrport_no_ptlist(void *arg)
- {
- transport_t *transport = NULL;
- tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
- uint16_t port = 1234;
- int ret;
- helper_add_bridges_to_bridgelist(arg);
- ret = tor_addr_parse(addr, "1.2.3.4");
- tt_int_op(ret, OP_EQ, 2); // it returns the address family on success?
- /* This will fail because the global transport_list has nothing in it, and so
- * transport_get_by_name() has nothing to return, even the the bridge *did*
- * say it had an obfs4 transport.
- */
- ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port,
- (const transport_t**)&transport);
- tt_int_op(ret, OP_EQ, -1); // returns -1 on failure
- tt_ptr_op(transport, OP_EQ, NULL);
- done:
- tor_free(addr);
- mark_bridge_list();
- sweep_bridge_list();
- }
- #define PT_PRIVATE
- /**
- * Calling get_transport_by_bridge_addrport() with the address and port of a
- * configured bridge which uses a pluggable transport should return 0 and set
- * appropriate transport_t.
- */
- static void
- test_bridges_get_transport_by_bridge_addrport(void *arg)
- {
- transport_t *transport = NULL;
- tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t));
- uint16_t port = 1234;
- int ret;
- helper_add_bridges_to_bridgelist(arg);
- mark_transport_list(); // Also initialise our transport_list
- ret = tor_addr_parse(addr, "1.2.3.4");
- tt_int_op(ret, OP_EQ, 2); // it returns the address family on success?
- /* After we mock transport_get_by_name() to return a bogus transport_t with
- * the name it was asked for, the call should succeed.
- */
- MOCK(transport_get_by_name, mock_transport_get_by_name);
- ret = get_transport_by_bridge_addrport((const tor_addr_t*)addr, port,
- (const transport_t**)&transport);
- tt_int_op(ret, OP_EQ, 0); // returns 0 on success
- tt_ptr_op(transport, OP_NE, NULL);
- tt_str_op(transport->name, OP_EQ, "obfs4");
- done:
- UNMOCK(transport_get_by_name);
- tor_free(addr);
- transport_free(transport);
- mark_bridge_list();
- sweep_bridge_list();
- }
- #undef PT_PRIVATE /* defined(PT_PRIVATE) */
- #define B_TEST(name, flags) \
- { #name, test_bridges_ ##name, (flags), NULL, NULL }
- struct testcase_t bridges_tests[] = {
- B_TEST(helper_func_add_bridges_to_bridgelist, 0),
- B_TEST(bridge_list_get_creates_new_bridgelist, 0),
- B_TEST(clear_bridge_list, 0),
- B_TEST(bridge_get_addrport, 0),
- B_TEST(get_configured_bridge_by_orports_digest, 0),
- B_TEST(get_configured_bridge_by_addr_port_digest_digest_only, 0),
- B_TEST(get_configured_bridge_by_addr_port_digest_address_only, 0),
- B_TEST(get_configured_bridge_by_exact_addr_port_digest_donly, 0),
- B_TEST(get_configured_bridge_by_exact_addr_port_digest_both, 0),
- B_TEST(get_configured_bridge_by_exact_addr_port_digest_aonly, 0),
- B_TEST(find_bridge_by_digest_known, 0),
- B_TEST(find_bridge_by_digest_unknown, 0),
- B_TEST(bridge_resolve_conflicts, 0),
- B_TEST(get_transport_by_bridge_addrport_no_ptlist, 0),
- B_TEST(get_transport_by_bridge_addrport, 0),
- B_TEST(transport_is_needed, 0),
- END_OF_TESTCASES
- };
|