123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593 |
- /* Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2013, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- #include "orconfig.h"
- #define CONFIG_PRIVATE
- #include "or.h"
- #include "addressmap.h"
- #include "config.h"
- #include "confparse.h"
- #include "connection_edge.h"
- #include "test.h"
- #include "util.h"
- #include "address.h"
- static void
- test_config_addressmap(void *arg)
- {
- char buf[1024];
- char address[256];
- time_t expires = TIME_MAX;
- (void)arg;
- strlcpy(buf, "MapAddress .invalidwildcard.com *.torserver.exit\n" // invalid
- "MapAddress *invalidasterisk.com *.torserver.exit\n" // invalid
- "MapAddress *.google.com *.torserver.exit\n"
- "MapAddress *.yahoo.com *.google.com.torserver.exit\n"
- "MapAddress *.cn.com www.cnn.com\n"
- "MapAddress *.cnn.com www.cnn.com\n"
- "MapAddress ex.com www.cnn.com\n"
- "MapAddress ey.com *.cnn.com\n"
- "MapAddress www.torproject.org 1.1.1.1\n"
- "MapAddress other.torproject.org "
- "this.torproject.org.otherserver.exit\n"
- "MapAddress test.torproject.org 2.2.2.2\n"
- "MapAddress www.google.com 3.3.3.3\n"
- "MapAddress www.example.org 4.4.4.4\n"
- "MapAddress 4.4.4.4 7.7.7.7\n"
- "MapAddress 4.4.4.4 5.5.5.5\n"
- "MapAddress www.infiniteloop.org 6.6.6.6\n"
- "MapAddress 6.6.6.6 www.infiniteloop.org\n"
- , sizeof(buf));
- config_get_lines(buf, &(get_options_mutable()->AddressMap), 0);
- config_register_addressmaps(get_options());
- /* Use old interface for now, so we don't need to rewrite the unit tests */
- #define addressmap_rewrite(a,s,eo,ao) \
- addressmap_rewrite((a),(s),AMR_FLAG_USE_IPV4_DNS|AMR_FLAG_USE_IPV6_DNS, \
- (eo),(ao))
- /* MapAddress .invalidwildcard.com .torserver.exit - no match */
- strlcpy(address, "www.invalidwildcard.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
- /* MapAddress *invalidasterisk.com .torserver.exit - no match */
- strlcpy(address, "www.invalidasterisk.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
- /* Where no mapping for FQDN match on top-level domain */
- /* MapAddress .google.com .torserver.exit */
- strlcpy(address, "reader.google.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "reader.torserver.exit");
- /* MapAddress *.yahoo.com *.google.com.torserver.exit */
- strlcpy(address, "reader.yahoo.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "reader.google.com.torserver.exit");
- /*MapAddress *.cnn.com www.cnn.com */
- strlcpy(address, "cnn.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.cnn.com");
- /* MapAddress .cn.com www.cnn.com */
- strlcpy(address, "www.cn.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.cnn.com");
- /* MapAddress ex.com www.cnn.com - no match */
- strlcpy(address, "www.ex.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
- /* MapAddress ey.com *.cnn.com - invalid expression */
- strlcpy(address, "ey.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
- /* Where mapping for FQDN match on FQDN */
- strlcpy(address, "www.google.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "3.3.3.3");
- strlcpy(address, "www.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "1.1.1.1");
- strlcpy(address, "other.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "this.torproject.org.otherserver.exit");
- strlcpy(address, "test.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "2.2.2.2");
- /* Test a chain of address mappings and the order in which they were added:
- "MapAddress www.example.org 4.4.4.4"
- "MapAddress 4.4.4.4 7.7.7.7"
- "MapAddress 4.4.4.4 5.5.5.5"
- */
- strlcpy(address, "www.example.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "5.5.5.5");
- /* Test infinite address mapping results in no change */
- strlcpy(address, "www.infiniteloop.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.infiniteloop.org");
- /* Test we don't find false positives */
- strlcpy(address, "www.example.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
- /* Test top-level-domain matching a bit harder */
- addressmap_clear_configured();
- strlcpy(buf, "MapAddress *.com *.torserver.exit\n"
- "MapAddress *.torproject.org 1.1.1.1\n"
- "MapAddress *.net 2.2.2.2\n"
- , sizeof(buf));
- config_get_lines(buf, &(get_options_mutable()->AddressMap), 0);
- config_register_addressmaps(get_options());
- strlcpy(address, "www.abc.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.abc.torserver.exit");
- strlcpy(address, "www.def.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.def.torserver.exit");
- strlcpy(address, "www.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "1.1.1.1");
- strlcpy(address, "test.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "1.1.1.1");
- strlcpy(address, "torproject.net", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "2.2.2.2");
- /* We don't support '*' as a mapping directive */
- addressmap_clear_configured();
- strlcpy(buf, "MapAddress * *.torserver.exit\n", sizeof(buf));
- config_get_lines(buf, &(get_options_mutable()->AddressMap), 0);
- config_register_addressmaps(get_options());
- strlcpy(address, "www.abc.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
- strlcpy(address, "www.def.net", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
- strlcpy(address, "www.torproject.org", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
- #undef addressmap_rewrite
- done:
- ;
- }
- static int
- is_private_dir(const char* path)
- {
- struct stat st;
- int r = stat(path, &st);
- if (r) {
- return 0;
- }
- #if !defined (_WIN32) || defined (WINCE)
- if ((st.st_mode & (S_IFDIR | 0777)) != (S_IFDIR | 0700)) {
- return 0;
- }
- #endif
- return 1;
- }
- static void
- test_config_check_or_create_data_subdir(void *arg)
- {
- or_options_t *options = get_options_mutable();
- char *datadir = options->DataDirectory = tor_strdup(get_fname("datadir-0"));
- const char *subdir = "test_stats";
- char *subpath = get_datadir_fname(subdir);
- struct stat st;
- int r;
- #if !defined (_WIN32) || defined (WINCE)
- unsigned group_permission;
- #endif
- (void)arg;
- #if defined (_WIN32) && !defined (WINCE)
- tt_int_op(mkdir(options->DataDirectory), ==, 0);
- #else
- tt_int_op(mkdir(options->DataDirectory, 0700), ==, 0);
- #endif
- r = stat(subpath, &st);
- // The subdirectory shouldn't exist yet,
- // but should be created by the call to check_or_create_data_subdir.
- test_assert(r && (errno == ENOENT));
- test_assert(!check_or_create_data_subdir(subdir));
- test_assert(is_private_dir(subpath));
- // The check should return 0, if the directory already exists
- // and is private to the user.
- test_assert(!check_or_create_data_subdir(subdir));
- r = stat(subpath, &st);
- if (r) {
- tt_abort_perror("stat");
- }
- #if !defined (_WIN32) || defined (WINCE)
- group_permission = st.st_mode | 0070;
- r = chmod(subpath, group_permission);
- if (r) {
- tt_abort_perror("chmod");
- }
- // If the directory exists, but its mode is too permissive
- // a call to check_or_create_data_subdir should reset the mode.
- test_assert(!is_private_dir(subpath));
- test_assert(!check_or_create_data_subdir(subdir));
- test_assert(is_private_dir(subpath));
- #endif
- done:
- rmdir(subpath);
- tor_free(datadir);
- tor_free(subpath);
- }
- static void
- test_config_write_to_data_subdir(void *arg)
- {
- or_options_t* options = get_options_mutable();
- char *datadir = options->DataDirectory = tor_strdup(get_fname("datadir-1"));
- char *cp = NULL;
- const char* subdir = "test_stats";
- const char* fname = "test_file";
- const char* str =
- "Lorem ipsum dolor sit amet, consetetur sadipscing\n"
- "elitr, sed diam nonumy eirmod\n"
- "tempor invidunt ut labore et dolore magna aliquyam\n"
- "erat, sed diam voluptua.\n"
- "At vero eos et accusam et justo duo dolores et ea\n"
- "rebum. Stet clita kasd gubergren,\n"
- "no sea takimata sanctus est Lorem ipsum dolor sit amet.\n"
- "Lorem ipsum dolor sit amet,\n"
- "consetetur sadipscing elitr, sed diam nonumy eirmod\n"
- "tempor invidunt ut labore et dolore\n"
- "magna aliquyam erat, sed diam voluptua. At vero eos et\n"
- "accusam et justo duo dolores et\n"
- "ea rebum. Stet clita kasd gubergren, no sea takimata\n"
- "sanctus est Lorem ipsum dolor sit amet.";
- char* filepath = get_datadir_fname2(subdir, fname);
- (void)arg;
- #if defined (_WIN32) && !defined (WINCE)
- tt_int_op(mkdir(options->DataDirectory), ==, 0);
- #else
- tt_int_op(mkdir(options->DataDirectory, 0700), ==, 0);
- #endif
- // Write attempt shoudl fail, if subdirectory doesn't exist.
- test_assert(write_to_data_subdir(subdir, fname, str, NULL));
- test_assert(! check_or_create_data_subdir(subdir));
- // Content of file after write attempt should be
- // equal to the original string.
- test_assert(!write_to_data_subdir(subdir, fname, str, NULL));
- cp = read_file_to_str(filepath, 0, NULL);
- test_streq(cp, str);
- tor_free(cp);
- // A second write operation should overwrite the old content.
- test_assert(!write_to_data_subdir(subdir, fname, str, NULL));
- cp = read_file_to_str(filepath, 0, NULL);
- test_streq(cp, str);
- tor_free(cp);
- done:
- (void) unlink(filepath);
- rmdir(options->DataDirectory);
- tor_free(datadir);
- tor_free(filepath);
- tor_free(cp);
- }
- /* Test helper function: Make sure that a bridge line gets parsed
- * properly. Also make sure that the resulting bridge_line_t structure
- * has its fields set correctly. */
- static void
- good_bridge_line_test(const char *string, const char *test_addrport,
- const char *test_digest, const char *test_transport,
- const smartlist_t *test_socks_args)
- {
- char *tmp = NULL;
- bridge_line_t *bridge_line = parse_bridge_line(string);
- test_assert(bridge_line);
- /* test addrport */
- tmp = tor_strdup(fmt_addrport(&bridge_line->addr, bridge_line->port));
- test_streq(test_addrport, tmp);
- tor_free(tmp);
- /* If we were asked to validate a digest, but we did not get a
- digest after parsing, we failed. */
- if (test_digest && tor_digest_is_zero(bridge_line->digest))
- test_assert(0);
- /* If we were not asked to validate a digest, and we got a digest
- after parsing, we failed again. */
- if (!test_digest && !tor_digest_is_zero(bridge_line->digest))
- test_assert(0);
- /* If we were asked to validate a digest, and we got a digest after
- parsing, make sure it's correct. */
- if (test_digest) {
- tmp = tor_strdup(hex_str(bridge_line->digest, DIGEST_LEN));
- tor_strlower(tmp);
- test_streq(test_digest, tmp);
- tor_free(tmp);
- }
- /* If we were asked to validate a transport name, make sure tha it
- matches with the transport name that was parsed. */
- if (test_transport && !bridge_line->transport_name)
- test_assert(0);
- if (!test_transport && bridge_line->transport_name)
- test_assert(0);
- if (test_transport)
- test_streq(test_transport, bridge_line->transport_name);
- /* Validate the SOCKS argument smartlist. */
- if (test_socks_args && !bridge_line->socks_args)
- test_assert(0);
- if (!test_socks_args && bridge_line->socks_args)
- test_assert(0);
- if (test_socks_args)
- test_assert(smartlist_strings_eq(test_socks_args,
- bridge_line->socks_args));
- done:
- tor_free(tmp);
- bridge_line_free(bridge_line);
- }
- /* Test helper function: Make sure that a bridge line is
- * unparseable. */
- static void
- bad_bridge_line_test(const char *string)
- {
- bridge_line_t *bridge_line = parse_bridge_line(string);
- if (bridge_line)
- TT_FAIL(("%s was supposed to fail, but it didn't.", string));
- test_assert(!bridge_line);
- done:
- bridge_line_free(bridge_line);
- }
- static void
- test_config_parse_bridge_line(void *arg)
- {
- (void) arg;
- good_bridge_line_test("192.0.2.1:4123",
- "192.0.2.1:4123", NULL, NULL, NULL);
- good_bridge_line_test("192.0.2.1",
- "192.0.2.1:443", NULL, NULL, NULL);
- good_bridge_line_test("transport [::1]",
- "[::1]:443", NULL, "transport", NULL);
- good_bridge_line_test("transport 192.0.2.1:12 "
- "4352e58420e68f5e40bf7c74faddccd9d1349413",
- "192.0.2.1:12",
- "4352e58420e68f5e40bf7c74faddccd9d1349413",
- "transport", NULL);
- {
- smartlist_t *sl_tmp = smartlist_new();
- smartlist_add_asprintf(sl_tmp, "twoandtwo=five");
- good_bridge_line_test("transport 192.0.2.1:12 "
- "4352e58420e68f5e40bf7c74faddccd9d1349413 twoandtwo=five",
- "192.0.2.1:12", "4352e58420e68f5e40bf7c74faddccd9d1349413",
- "transport", sl_tmp);
- SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
- smartlist_free(sl_tmp);
- }
- {
- smartlist_t *sl_tmp = smartlist_new();
- smartlist_add_asprintf(sl_tmp, "twoandtwo=five");
- smartlist_add_asprintf(sl_tmp, "z=z");
- good_bridge_line_test("transport 192.0.2.1:12 twoandtwo=five z=z",
- "192.0.2.1:12", NULL, "transport", sl_tmp);
- SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
- smartlist_free(sl_tmp);
- }
- {
- smartlist_t *sl_tmp = smartlist_new();
- smartlist_add_asprintf(sl_tmp, "dub=come");
- smartlist_add_asprintf(sl_tmp, "save=me");
- good_bridge_line_test("transport 192.0.2.1:12 "
- "4352e58420e68f5e40bf7c74faddccd9d1349666 "
- "dub=come save=me",
- "192.0.2.1:12",
- "4352e58420e68f5e40bf7c74faddccd9d1349666",
- "transport", sl_tmp);
- SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
- smartlist_free(sl_tmp);
- }
- good_bridge_line_test("192.0.2.1:1231 "
- "4352e58420e68f5e40bf7c74faddccd9d1349413",
- "192.0.2.1:1231",
- "4352e58420e68f5e40bf7c74faddccd9d1349413",
- NULL, NULL);
- /* Empty line */
- bad_bridge_line_test("");
- /* bad transport name */
- bad_bridge_line_test("tr$n_sp0r7 190.20.2.2");
- /* weird ip address */
- bad_bridge_line_test("a.b.c.d");
- /* invalid fpr */
- bad_bridge_line_test("2.2.2.2:1231 4352e58420e68f5e40bf7c74faddccd9d1349");
- /* no k=v in the end */
- bad_bridge_line_test("obfs2 2.2.2.2:1231 "
- "4352e58420e68f5e40bf7c74faddccd9d1349413 what");
- /* no addrport */
- bad_bridge_line_test("asdw");
- /* huge k=v value that can't fit in SOCKS fields */
- bad_bridge_line_test(
- "obfs2 2.2.2.2:1231 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
- "aa=b");
- }
- static void
- test_config_parse_transport_options_line(void *arg)
- {
- smartlist_t *options_sl = NULL, *sl_tmp = NULL;
- (void) arg;
- { /* too small line */
- options_sl = get_options_from_transport_options_line("valley", NULL);
- test_assert(!options_sl);
- }
- { /* no k=v values */
- options_sl = get_options_from_transport_options_line("hit it!", NULL);
- test_assert(!options_sl);
- }
- { /* correct line, but wrong transport specified */
- options_sl =
- get_options_from_transport_options_line("trebuchet k=v", "rook");
- test_assert(!options_sl);
- }
- { /* correct -- no transport specified */
- sl_tmp = smartlist_new();
- smartlist_add_asprintf(sl_tmp, "ladi=dadi");
- smartlist_add_asprintf(sl_tmp, "weliketo=party");
- options_sl =
- get_options_from_transport_options_line("rook ladi=dadi weliketo=party",
- NULL);
- test_assert(options_sl);
- test_assert(smartlist_strings_eq(options_sl, sl_tmp));
- SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
- smartlist_free(sl_tmp);
- sl_tmp = NULL;
- SMARTLIST_FOREACH(options_sl, char *, s, tor_free(s));
- smartlist_free(options_sl);
- options_sl = NULL;
- }
- { /* correct -- correct transport specified */
- sl_tmp = smartlist_new();
- smartlist_add_asprintf(sl_tmp, "ladi=dadi");
- smartlist_add_asprintf(sl_tmp, "weliketo=party");
- options_sl =
- get_options_from_transport_options_line("rook ladi=dadi weliketo=party",
- "rook");
- test_assert(options_sl);
- test_assert(smartlist_strings_eq(options_sl, sl_tmp));
- SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
- smartlist_free(sl_tmp);
- sl_tmp = NULL;
- SMARTLIST_FOREACH(options_sl, char *, s, tor_free(s));
- smartlist_free(options_sl);
- options_sl = NULL;
- }
- done:
- if (options_sl) {
- SMARTLIST_FOREACH(options_sl, char *, s, tor_free(s));
- smartlist_free(options_sl);
- }
- if (sl_tmp) {
- SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
- smartlist_free(sl_tmp);
- }
- }
- // Tests if an options with MyFamily fingerprints missing '$' normalises
- // them correctly and also ensure it also works with multiple fingerprints
- static void
- test_config_fix_my_family(void *arg)
- {
- char *err = NULL;
- const char *family = "$1111111111111111111111111111111111111111, "
- "1111111111111111111111111111111111111112, "
- "$1111111111111111111111111111111111111113";
- or_options_t* options = options_new();
- or_options_t* defaults = options_new();
- (void) arg;
- options_init(options);
- options_init(defaults);
- options->MyFamily = tor_strdup(family);
- options_validate(NULL, options, defaults, 0, &err) ;
- if (err != NULL) {
- TT_FAIL(("options_validate failed: %s", err));
- }
- test_streq(options->MyFamily, "$1111111111111111111111111111111111111111, "
- "$1111111111111111111111111111111111111112, "
- "$1111111111111111111111111111111111111113");
- done:
- if (err != NULL) {
- tor_free(err);
- }
- or_options_free(options);
- or_options_free(defaults);
- }
- #define CONFIG_TEST(name, flags) \
- { #name, test_config_ ## name, flags, NULL, NULL }
- struct testcase_t config_tests[] = {
- CONFIG_TEST(addressmap, 0),
- CONFIG_TEST(parse_bridge_line, 0),
- CONFIG_TEST(parse_transport_options_line, 0),
- CONFIG_TEST(check_or_create_data_subdir, TT_FORK),
- CONFIG_TEST(write_to_data_subdir, TT_FORK),
- CONFIG_TEST(fix_my_family, 0),
- END_OF_TESTCASES
- };
|