From c6d8c6baaa983aecd6a5121ec6ed8e2d9a2a24be Mon Sep 17 00:00:00 2001 From: Robert Hogan Date: Mon, 2 Aug 2010 20:09:37 +0100 Subject: [PATCH 01/11] bug933 - Match against super-domains in MapAddress Allow MapAddress to handle directives such as: MapAddress .torproject.org .torserver.exit MapAddress .org 1.1.1.1 Add tests for addressmap_rewrite. --- changes/bug933 | 4 ++ doc/tor.1.txt | 7 ++- src/or/connection_edge.c | 41 ++++++++++++- src/test/Makefile.am | 1 + src/test/test.c | 2 + src/test/test_config.c | 127 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 changes/bug933 create mode 100644 src/test/test_config.c diff --git a/changes/bug933 b/changes/bug933 new file mode 100644 index 0000000000..b646858202 --- /dev/null +++ b/changes/bug933 @@ -0,0 +1,4 @@ + o Minor features: + - Allow MapAddress directives to specify matches against super-domains, + as in 'MapAddress *.torproject.org *.torproject.org.torserver.exit'. + Implements issue 933. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 4edee80cea..4d4ad9fdb7 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -659,7 +659,12 @@ The following options are useful only for clients (that is, if before processing it. For example, if you always want connections to www.indymedia.org to exit via __torserver__ (where __torserver__ is the nickname of the server), use "MapAddress www.indymedia.org - www.indymedia.org.torserver.exit". + www.indymedia.org.torserver.exit". If the value is prepended with a \'.\', + it is treated as matching an entire domain.For example, if you always + want connections to any sub-domain of indymedia.org to exit via + __torserver__ (where __torserver__ is the nickname of the server), use + "MapAddress .indymedia.org .torserver.exit". (Note the leading '.' in + each part of the directive.) **NewCircuitPeriod** __NUM__:: Every NUM seconds consider whether to build a new circuit. (Default: 30 diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index f59f44c9ad..4bb49c831c 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1037,6 +1037,29 @@ addressmap_free_all(void) virtaddress_reversemap = NULL; } +/** Try to find a match for AddressMap directives that use + * domain notation such as '.torproject.org .exitnode.exit'. + */ +static addressmap_entry_t * +addressmap_match_superdomains(char *address) +{ + strmap_iter_t *iter; + const char *key; + void *_val; + addressmap_entry_t *val; + + for (iter = strmap_iter_init(addressmap); !strmap_iter_done(iter); ) { + strmap_iter_get(iter, &key, &_val); + val = _val; + if (key[0] == '.') { /* match end */ + if (!strcasecmpend(address, key) || !strcasecmp(address, &key[1])) + return val; + } + iter = strmap_iter_next(addressmap,iter); + } + return 0; +} + /** Look at address, and rewrite it until it doesn't want any * more rewrites; but don't get into an infinite loop. * Don't write more than maxlen chars into address. Return true if the @@ -1050,24 +1073,36 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) addressmap_entry_t *ent; int rewrites; char *cp; + char *s; time_t expires = TIME_MAX; for (rewrites = 0; rewrites < 16; rewrites++) { ent = strmap_get(addressmap, address); + if (!ent || !ent->new_address) + ent = addressmap_match_superdomains(address); + if (!ent || !ent->new_address) { if (expires_out) *expires_out = expires; return (rewrites > 0); /* done, no rewrite needed */ } - cp = tor_strdup(escaped_safe_str_client(ent->new_address)); + cp = tor_strdup(escaped_safe_str_client(address)); + /* If the address to rewrite to is in the form '.exitnode.exit' + then append it to the given address */ + s = strrchr(ent->new_address,'.'); + if (ent->new_address[0] == '.' && !strcmp(s+1,"exit")) + strlcpy(address + strlen(address), ent->new_address, + (maxlen - strlen(address))); + else + strlcpy(address, ent->new_address, maxlen); + log_info(LD_APP, "Addressmap: rewriting %s to %s", - escaped_safe_str_client(address), cp); + cp, escaped_safe_str_client(address)); if (ent->expires > 1 && ent->expires < expires) expires = ent->expires; tor_free(cp); - strlcpy(address, ent->new_address, maxlen); } log_warn(LD_CONFIG, "Loop detected: we've rewritten %s 16 times! Using it as-is.", diff --git a/src/test/Makefile.am b/src/test/Makefile.am index 852715079d..e675431c6a 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -20,6 +20,7 @@ test_SOURCES = \ test_dir.c \ test_microdesc.c \ test_util.c \ + test_config.c \ tinytest.c test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ diff --git a/src/test/test.c b/src/test/test.c index 605e44ca4d..76644a71f9 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1941,6 +1941,7 @@ extern struct testcase_t container_tests[]; extern struct testcase_t util_tests[]; extern struct testcase_t dir_tests[]; extern struct testcase_t microdesc_tests[]; +extern struct testcase_t config_tests[]; static struct testgroup_t testgroups[] = { { "", test_array }, @@ -1951,6 +1952,7 @@ static struct testgroup_t testgroups[] = { { "util/", util_tests }, { "dir/", dir_tests }, { "dir/md/", microdesc_tests }, + { "config/", config_tests }, END_OF_GROUPS }; diff --git a/src/test/test_config.c b/src/test/test_config.c new file mode 100644 index 0000000000..f39a9ef52d --- /dev/null +++ b/src/test/test_config.c @@ -0,0 +1,127 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include "or.h" +#include "config.h" +#include "connection_edge.h" +#include "test.h" + +static void +test_config_addressmap(void) +{ + char buf[1024]; + char address[256]; + time_t expires = TIME_MAX; + strlcpy(buf, "MapAddress .google.com .torserver.exit\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 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()->AddressMap)); + config_register_addressmaps(get_options()); + + /* Where no mapping for FQDN match on top-level domain */ + strlcpy(address, "reader.google.com", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + test_streq(address, "reader.google.com.torserver.exit"); + + /* Where mapping for FQDN match on FQDN */ + strlcpy(address, "www.google.com", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + test_streq(address, "3.3.3.3"); + + strlcpy(address, "www.torproject.org", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + test_streq(address, "1.1.1.1"); + + strlcpy(address, "other.torproject.org", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + test_streq(address, "this.torproject.org.otherserver.exit"); + + strlcpy(address, "test.torproject.org", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + test_streq(address, "2.2.2.2"); + + /* Test a chain of address mappings */ + strlcpy(address, "www.example.org", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + 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)); + 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)); + + /* 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()->AddressMap)); + config_register_addressmaps(get_options()); + + strlcpy(address, "www.abc.com", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + test_streq(address, "www.abc.com.torserver.exit"); + + strlcpy(address, "www.def.com", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + test_streq(address, "www.def.com.torserver.exit"); + + strlcpy(address, "www.torproject.org", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + test_streq(address, "1.1.1.1"); + + strlcpy(address, "test.torproject.org", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + test_streq(address, "1.1.1.1"); + + strlcpy(address, "torproject.net", sizeof(address)); + test_assert(addressmap_rewrite(address, sizeof(address), &expires)); + 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()->AddressMap)); + config_register_addressmaps(get_options()); + + strlcpy(address, "www.abc.com", sizeof(address)); + test_assert(!addressmap_rewrite(address, sizeof(address), &expires)); + + strlcpy(address, "www.def.net", sizeof(address)); + test_assert(!addressmap_rewrite(address, sizeof(address), &expires)); + + strlcpy(address, "www.torproject.org", sizeof(address)); + test_assert(!addressmap_rewrite(address, sizeof(address), &expires)); + +done: + ; +} + +#define CONFIG_LEGACY(name) \ + { #name, legacy_test_helper, 0, &legacy_setup, test_config_ ## name } + +#define CONFIG_TEST(name, flags) \ + { #name, test_config_ ## name, flags, NULL, NULL } + +struct testcase_t config_tests[] = { + CONFIG_LEGACY(addressmap), + END_OF_TESTCASES +}; + From 909e9769ece9e89ad0c4bbb558a6f8247c6a62bd Mon Sep 17 00:00:00 2001 From: Robert Hogan Date: Mon, 13 Dec 2010 22:13:01 +0000 Subject: [PATCH 02/11] Address nickm's comments at https://trac.torproject.org/projects/tor/ticket/933#comment:4 1. Implement the following mapping rules: MapAddress a.b.c d.e.f # This is what we have now MapAddress .a.b.c d.e.f # Replaces any address ending with .a.b.c with d.e.f MapAddress .a.b.c .d.e.f # Replaces the .a.b.c at the end of any addr with .d.e.f (Note that 'a.b.c .d.e.f' is invalid, and will be rejected.) 2. Add tests for the new rules. 3. Allow proper wildcard annotation, i.e. '*.d.e' '.d.e' will still work. 4. Update addressmap_entry_t with an is_wildcard member. --- doc/tor.1.txt | 10 ++++++---- src/or/config.c | 13 ++++++++++++- src/or/connection_edge.c | 25 ++++++++++++++++--------- src/test/test_config.c | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 65 insertions(+), 16 deletions(-) diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 4d4ad9fdb7..1c9d387e43 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -659,12 +659,14 @@ The following options are useful only for clients (that is, if before processing it. For example, if you always want connections to www.indymedia.org to exit via __torserver__ (where __torserver__ is the nickname of the server), use "MapAddress www.indymedia.org - www.indymedia.org.torserver.exit". If the value is prepended with a \'.\', - it is treated as matching an entire domain.For example, if you always + www.indymedia.org.torserver.exit". If the value is prepended with a \'*.\', + it is treated as matching an entire domain. For example, if you always want connections to any sub-domain of indymedia.org to exit via __torserver__ (where __torserver__ is the nickname of the server), use - "MapAddress .indymedia.org .torserver.exit". (Note the leading '.' in - each part of the directive.) + "MapAddress *.indymedia.org *.indymedia.org.torserver.exit". (Note the + leading '*.' in each part of the directive.) You can also redirect all + subdomains of a domain to a single address. For example, "MapAddress + *.indymedia.org www.indymedia.org". **NewCircuitPeriod** __NUM__:: Every NUM seconds consider whether to build a new circuit. (Default: 30 diff --git a/src/or/config.c b/src/or/config.c index afcea1f4cd..1744b84c48 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -4464,7 +4464,18 @@ config_register_addressmaps(const or_options_t *options) if (smartlist_len(elts) >= 2) { from = smartlist_get(elts,0); to = smartlist_get(elts,1); - if (address_is_invalid_destination(to, 1)) { + + /* Remove leading asterisk in expressions of type: '*.example.com' */ + if (from[0] == '*' && strlen(from) > 1) + from++; + if (to[0] == '*' && strlen(to) > 1) + to++; + if (to[0] == '.' && from[0] != '.') { + log_warn(LD_CONFIG, + "Skipping invalid argument '%s' to MapAddress: " + "can only use wildcard (i.e. '.' or '*.') if 'from' address " + "uses wildcard also", to); + } else if (address_is_invalid_destination(to, 1)) { log_warn(LD_CONFIG, "Skipping invalid argument '%s' to MapAddress", to); } else { diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 4bb49c831c..2c8c9da259 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -794,6 +794,7 @@ typedef struct { char *new_address; time_t expires; addressmap_entry_source_t source:3; + int is_wildcard:1; short num_resolve_failures; } addressmap_entry_t; @@ -1037,8 +1038,12 @@ addressmap_free_all(void) virtaddress_reversemap = NULL; } -/** Try to find a match for AddressMap directives that use - * domain notation such as '.torproject.org .exitnode.exit'. +/** Try to find a match for AddressMap expressions that use + * wildcard notation such as '*.c.d *.e.f' (so 'a.c.d' will map to 'a.e.f') or + * '*.c.d a.b.c' (so 'a.c.d' will map to a.b.c). + * Returns the matching entry in AddressMap or 0 if no match is found. + * For expressions such as '*.c.d *.e.f' the address 'a.c.d' will + * get truncated to 'a' before we return the matching AddressMap entry. */ static addressmap_entry_t * addressmap_match_superdomains(char *address) @@ -1047,13 +1052,18 @@ addressmap_match_superdomains(char *address) const char *key; void *_val; addressmap_entry_t *val; + char *matched_domains = 0; for (iter = strmap_iter_init(addressmap); !strmap_iter_done(iter); ) { strmap_iter_get(iter, &key, &_val); val = _val; - if (key[0] == '.') { /* match end */ - if (!strcasecmpend(address, key) || !strcasecmp(address, &key[1])) + if (key[0] == '.') { + if (!strcasecmpend(address, key) || !strcasecmp(address, &key[1])) { + matched_domains = strstr(address, key); + if (val->is_wildcard && matched_domains) + *matched_domains = '\0'; return val; + } } iter = strmap_iter_next(addressmap,iter); } @@ -1073,7 +1083,6 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) addressmap_entry_t *ent; int rewrites; char *cp; - char *s; time_t expires = TIME_MAX; for (rewrites = 0; rewrites < 16; rewrites++) { @@ -1089,10 +1098,7 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) } cp = tor_strdup(escaped_safe_str_client(address)); - /* If the address to rewrite to is in the form '.exitnode.exit' - then append it to the given address */ - s = strrchr(ent->new_address,'.'); - if (ent->new_address[0] == '.' && !strcmp(s+1,"exit")) + if (ent->is_wildcard) strlcpy(address + strlen(address), ent->new_address, (maxlen - strlen(address))); else @@ -1211,6 +1217,7 @@ addressmap_register(const char *address, char *new_address, time_t expires, ent->expires = expires==2 ? 1 : expires; ent->num_resolve_failures = 0; ent->source = source; + ent->is_wildcard = (new_address[0] == '.') ? 1 : 0; log_info(LD_CONFIG, "Addressmap: (re)mapped '%s' to '%s'", safe_str_client(address), diff --git a/src/test/test_config.c b/src/test/test_config.c index f39a9ef52d..a7b5d03a0c 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -16,6 +16,11 @@ test_config_addressmap(void) char address[256]; time_t expires = TIME_MAX; strlcpy(buf, "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" @@ -31,10 +36,34 @@ test_config_addressmap(void) config_register_addressmaps(get_options()); /* 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)); + 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)); 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)); + 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)); + 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)); + + /* MapAddress ey.com *.cnn.com - invalid expression */ + strlcpy(address, "ey.com", sizeof(address)); + test_assert(!addressmap_rewrite(address, sizeof(address), &expires)); + /* Where mapping for FQDN match on FQDN */ strlcpy(address, "www.google.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires)); @@ -77,11 +106,11 @@ test_config_addressmap(void) strlcpy(address, "www.abc.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires)); - test_streq(address, "www.abc.com.torserver.exit"); + test_streq(address, "www.abc.torserver.exit"); strlcpy(address, "www.def.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires)); - test_streq(address, "www.def.com.torserver.exit"); + test_streq(address, "www.def.torserver.exit"); strlcpy(address, "www.torproject.org", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires)); From 53ce6bb52d29e80c7efd29b8604bdd680c9515ea Mon Sep 17 00:00:00 2001 From: Robert Hogan Date: Mon, 27 Dec 2010 17:35:16 +0000 Subject: [PATCH 03/11] Address nickm's comments at https://trac.torproject.org/projects/tor/ticket/933#comment:8 1. Only allow '*.' in MapAddress expressions. Ignore '*ample.com' and '.example.com'. This has resulted in a slight refactoring of config_register_addressmaps. 2. Add some more detail to the man page entry for AddressMap. 3. Fix initialization of a pointer to NULL rather than 0. 4. Update the unit tests to cater for the changes in 1 and test more explicitly for recursive mapping. --- doc/tor.1.txt | 41 +++++++++++++++++++++----- src/or/config.c | 62 ++++++++++++++++++++++++---------------- src/or/connection_edge.c | 2 +- src/test/test_config.c | 31 ++++++++++++++------ 4 files changed, 96 insertions(+), 40 deletions(-) diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 1c9d387e43..eb794527c7 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -658,15 +658,42 @@ The following options are useful only for clients (that is, if When a request for address arrives to Tor, it will rewrite it to newaddress before processing it. For example, if you always want connections to www.indymedia.org to exit via __torserver__ (where __torserver__ is the - nickname of the server), use "MapAddress www.indymedia.org - www.indymedia.org.torserver.exit". If the value is prepended with a \'*.\', - it is treated as matching an entire domain. For example, if you always - want connections to any sub-domain of indymedia.org to exit via + nickname of the server), use MapAddress www.indymedia.org + www.indymedia.org.torserver.exit. If the value is prepended with a + '*.', it is treated as matching an entire domain. For example, if you + always want connections to any sub-domain of indymedia.org to exit via __torserver__ (where __torserver__ is the nickname of the server), use - "MapAddress *.indymedia.org *.indymedia.org.torserver.exit". (Note the + MapAddress *.indymedia.org *.indymedia.org.torserver.exit. (Note the leading '*.' in each part of the directive.) You can also redirect all - subdomains of a domain to a single address. For example, "MapAddress - *.indymedia.org www.indymedia.org". + subdomains of a domain to a single address. For example, MapAddress + *.indymedia.org www.indymedia.org. + + + + NOTES: + + 1. When evaluating MapAddress expressions Tor stops when it hits the most + recently added expression that matches the requested address. So if you + have the following in your torrc, www.torproject.org will map to 1.1.1.1: + + MapAddress www.torproject.org 2.2.2.2 + MapAddress www.torproject.org 1.1.1.1 + + 2. Tor evaluates the MapAddress configuration until it finds no matches. So + if you have the following in your torrc, www.torproject.org will map to + 2.2.2.2: + + MapAddress www.torproject.org 3.3.3.3 + MapAddress 1.1.1.1 4.4.4.4 + MapAddress 1.1.1.1 2.2.2.2 + MapAddress www.torproject.org 1.1.1.1 + + 3. The following MapAddress expression is invalid (and will be + ignored) because you cannot map from a specific address to a wildcarded + address: + + MapAddress www.torproject.org *.torproject.org.torserver.exit + + 4. Using a wildcard as a regular expression (e.g. *ample.com) is + also invalid. **NewCircuitPeriod** __NUM__:: Every NUM seconds consider whether to build a new circuit. (Default: 30 diff --git a/src/or/config.c b/src/or/config.c index 1744b84c48..1d42413c16 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -4461,33 +4461,47 @@ config_register_addressmaps(const or_options_t *options) for (opt = options->AddressMap; opt; opt = opt->next) { smartlist_split_string(elts, opt->value, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); - if (smartlist_len(elts) >= 2) { - from = smartlist_get(elts,0); - to = smartlist_get(elts,1); - - /* Remove leading asterisk in expressions of type: '*.example.com' */ - if (from[0] == '*' && strlen(from) > 1) - from++; - if (to[0] == '*' && strlen(to) > 1) - to++; - if (to[0] == '.' && from[0] != '.') { - log_warn(LD_CONFIG, - "Skipping invalid argument '%s' to MapAddress: " - "can only use wildcard (i.e. '.' or '*.') if 'from' address " - "uses wildcard also", to); - } else if (address_is_invalid_destination(to, 1)) { - log_warn(LD_CONFIG, - "Skipping invalid argument '%s' to MapAddress", to); - } else { - addressmap_register(from, tor_strdup(to), 0, ADDRMAPSRC_TORRC); - if (smartlist_len(elts)>2) { - log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress."); - } - } - } else { + if (smartlist_len(elts) < 2) { log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.", opt->value); + goto cleanup; } + + from = smartlist_get(elts,0); + to = smartlist_get(elts,1); + + if (to[0] == '.' || from[0] == '.') { + log_warn(LD_CONFIG,"MapAddress '%s' is ambiguous - address starts with a" + "'.'. Ignoring.",opt->value); + goto cleanup; + } + + /* Remove leading asterisk in expressions of type: '*.example.com' */ + if (!strncmp(from,"*.",2)) + from++; + if (!strncmp(to,"*.",2)) + to++; + + if (to[0] == '.' && from[0] != '.') { + log_warn(LD_CONFIG, + "Skipping invalid argument '%s' to MapAddress: " + "can only use wildcard (i.e. '*.') if 'from' address " + "uses wildcard also", to); + goto cleanup; + } + + if (address_is_invalid_destination(to, 1)) { + log_warn(LD_CONFIG, + "Skipping invalid argument '%s' to MapAddress", to); + goto cleanup; + } + + addressmap_register(from, tor_strdup(to), 0, ADDRMAPSRC_TORRC); + + if (smartlist_len(elts) > 2) + log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress."); + + cleanup: SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp)); smartlist_clear(elts); } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 2c8c9da259..284b320452 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1052,7 +1052,7 @@ addressmap_match_superdomains(char *address) const char *key; void *_val; addressmap_entry_t *val; - char *matched_domains = 0; + char *matched_domains = NULL; for (iter = strmap_iter_init(addressmap); !strmap_iter_done(iter); ) { strmap_iter_get(iter, &key, &_val); diff --git a/src/test/test_config.c b/src/test/test_config.c index a7b5d03a0c..8880bd07fc 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -15,9 +15,11 @@ test_config_addressmap(void) char buf[1024]; char address[256]; time_t expires = TIME_MAX; - strlcpy(buf, "MapAddress .google.com .torserver.exit\n" + 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 *.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" @@ -27,6 +29,7 @@ test_config_addressmap(void) "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" @@ -35,6 +38,14 @@ test_config_addressmap(void) config_get_lines(buf, &(get_options()->AddressMap)); config_register_addressmaps(get_options()); + /* MapAddress .invalidwildcard.com .torserver.exit - no match */ + strlcpy(address, "www.invalidwildcard.com", sizeof(address)); + test_assert(!addressmap_rewrite(address, sizeof(address), &expires)); + + /* MapAddress *invalidasterisk.com .torserver.exit - no match */ + strlcpy(address, "www.invalidasterisk.com", sizeof(address)); + test_assert(!addressmap_rewrite(address, sizeof(address), &expires)); + /* Where no mapping for FQDN match on top-level domain */ /* MapAddress .google.com .torserver.exit */ strlcpy(address, "reader.google.com", sizeof(address)); @@ -81,7 +92,11 @@ test_config_addressmap(void) test_assert(addressmap_rewrite(address, sizeof(address), &expires)); test_streq(address, "2.2.2.2"); - /* Test a chain of address mappings */ + /* 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)); test_streq(address, "5.5.5.5"); @@ -97,9 +112,9 @@ test_config_addressmap(void) /* 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" + 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()->AddressMap)); config_register_addressmaps(get_options()); @@ -124,9 +139,9 @@ test_config_addressmap(void) test_assert(addressmap_rewrite(address, sizeof(address), &expires)); test_streq(address, "2.2.2.2"); - /* We don't support '.' as a mapping directive */ + /* We don't support '*' as a mapping directive */ addressmap_clear_configured(); - strlcpy(buf, "MapAddress . .torserver.exit\n", sizeof(buf)); + strlcpy(buf, "MapAddress * *.torserver.exit\n", sizeof(buf)); config_get_lines(buf, &(get_options()->AddressMap)); config_register_addressmaps(get_options()); From 54d262a728d97a26d1e019a8cd94a679a5741e31 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 8 Sep 2011 09:30:21 -0400 Subject: [PATCH 04/11] Fix compilation: get_options() now returns const --- src/test/test_config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/test_config.c b/src/test/test_config.c index 8880bd07fc..fd38e2f7b9 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -35,7 +35,7 @@ test_config_addressmap(void) "MapAddress 6.6.6.6 www.infiniteloop.org\n" , sizeof(buf)); - config_get_lines(buf, &(get_options()->AddressMap)); + config_get_lines(buf, &(get_options_mutable()->AddressMap)); config_register_addressmaps(get_options()); /* MapAddress .invalidwildcard.com .torserver.exit - no match */ @@ -116,7 +116,7 @@ test_config_addressmap(void) "MapAddress *.torproject.org 1.1.1.1\n" "MapAddress *.net 2.2.2.2\n" , sizeof(buf)); - config_get_lines(buf, &(get_options()->AddressMap)); + config_get_lines(buf, &(get_options_mutable()->AddressMap)); config_register_addressmaps(get_options()); strlcpy(address, "www.abc.com", sizeof(address)); @@ -142,7 +142,7 @@ test_config_addressmap(void) /* 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()->AddressMap)); + config_get_lines(buf, &(get_options_mutable()->AddressMap)); config_register_addressmaps(get_options()); strlcpy(address, "www.abc.com", sizeof(address)); From df0da3991cb00efdf7c9362e805877e63ce8a46e Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 8 Sep 2011 11:19:06 -0400 Subject: [PATCH 05/11] No new "LEGACY" tests allowed. --- src/test/test_config.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/test_config.c b/src/test/test_config.c index fd38e2f7b9..99d7215bed 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -10,11 +10,13 @@ #include "test.h" static void -test_config_addressmap(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" @@ -158,14 +160,11 @@ done: ; } -#define CONFIG_LEGACY(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_config_ ## name } - #define CONFIG_TEST(name, flags) \ { #name, test_config_ ## name, flags, NULL, NULL } struct testcase_t config_tests[] = { - CONFIG_LEGACY(addressmap), + CONFIG_TEST(addressmap, 0), END_OF_TESTCASES }; From 69d16900aaf1d54b44d2b28514a09873154c63d3 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 8 Sep 2011 11:54:24 -0400 Subject: [PATCH 06/11] Refactor addressmap_match_superdomains and representation of wildcards In this new representation for wildcarded addresses, there are no longer any 'magic addresses': rather, "a.b c.d", "*.a.b c.d" and "*.a.b *.c.d" are all represented by a mapping from "a.b" to "c.d". we now distinguish them by setting bits in the addressmap_entry_t structure, where src_wildcard is set if the source address had a wildcard, and dst_wildcard is set if the target address had a wildcard. This lets the case where "*.a.b *.c.d" or "*.a.b c.d" remap the address "a.b" get handled trivially, and lets us simplify and improve the addressmap_match_superdomains implementation: we can now have it run in O(parts of address) rather than O(entries in addressmap). --- src/or/circuituse.c | 2 +- src/or/config.c | 24 ++++++++----- src/or/connection_edge.c | 78 +++++++++++++++++++++++++--------------- src/or/connection_edge.h | 3 +- src/or/control.c | 2 +- 5 files changed, 68 insertions(+), 41 deletions(-) diff --git a/src/or/circuituse.c b/src/or/circuituse.c index f7f080db13..fc252c9b18 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1676,7 +1676,7 @@ consider_recording_trackhost(const entry_connection_t *conn, addressmap_register(conn->socks_request->address, new_address, time(NULL) + options->TrackHostExitsExpire, - ADDRMAPSRC_TRACKEXIT); + ADDRMAPSRC_TRACKEXIT,0,0); } /** Attempt to attach the connection conn to circ, and send a diff --git a/src/or/config.c b/src/or/config.c index 1d42413c16..ef54dcbff2 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -4459,6 +4459,7 @@ config_register_addressmaps(const or_options_t *options) addressmap_clear_configured(); elts = smartlist_create(); for (opt = options->AddressMap; opt; opt = opt->next) { + int from_wildcard = 0, to_wildcard = 0; smartlist_split_string(elts, opt->value, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); if (smartlist_len(elts) < 2) { @@ -4476,27 +4477,32 @@ config_register_addressmaps(const or_options_t *options) goto cleanup; } - /* Remove leading asterisk in expressions of type: '*.example.com' */ - if (!strncmp(from,"*.",2)) - from++; - if (!strncmp(to,"*.",2)) - to++; + /* Detect asterisks in expressions of type: '*.example.com' */ + if (!strncmp(from,"*.",2)) { + from += 2; + from_wildcard = 1; + } + if (!strncmp(to,"*.",2)) { + to += 2; + to_wildcard = 1; + } - if (to[0] == '.' && from[0] != '.') { + if (to_wildcard && !from_wildcard) { log_warn(LD_CONFIG, "Skipping invalid argument '%s' to MapAddress: " "can only use wildcard (i.e. '*.') if 'from' address " - "uses wildcard also", to); + "uses wildcard also", opt->value); goto cleanup; } if (address_is_invalid_destination(to, 1)) { log_warn(LD_CONFIG, - "Skipping invalid argument '%s' to MapAddress", to); + "Skipping invalid argument '%s' to MapAddress", opt->value); goto cleanup; } - addressmap_register(from, tor_strdup(to), 0, ADDRMAPSRC_TORRC); + addressmap_register(from, tor_strdup(to), 0, ADDRMAPSRC_TORRC, + from_wildcard, to_wildcard); if (smartlist_len(elts) > 2) log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress."); diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 284b320452..f7b24112ce 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -789,12 +789,18 @@ connection_ap_detach_retriable(entry_connection_t *conn, * the configuration file, "1" for mappings set from the control * interface, and other values for DNS and TrackHostExit mappings that can * expire.) + * + * A mapping may be 'wildcarded'. If "src_wildcard" is true, then + * any address that ends with a . followed by the key for this entry will + * get remapped by it. If "dst_wildcard" is also true, then only the + * matching suffix of such addresses will get replaced by new_address. */ typedef struct { char *new_address; time_t expires; addressmap_entry_source_t source:3; - int is_wildcard:1; + unsigned src_wildcard:1; + unsigned dst_wildcard:1; short num_resolve_failures; } addressmap_entry_t; @@ -1041,33 +1047,32 @@ addressmap_free_all(void) /** Try to find a match for AddressMap expressions that use * wildcard notation such as '*.c.d *.e.f' (so 'a.c.d' will map to 'a.e.f') or * '*.c.d a.b.c' (so 'a.c.d' will map to a.b.c). - * Returns the matching entry in AddressMap or 0 if no match is found. - * For expressions such as '*.c.d *.e.f' the address 'a.c.d' will - * get truncated to 'a' before we return the matching AddressMap entry. + * Return the matching entry in AddressMap or NULL if no match is found. + * For expressions such as '*.c.d *.e.f', truncate address 'a.c.d' + * to 'a' before we return the matching AddressMap entry. + * + * This function does not handle the case where a pattern of the form "*.c.d" + * matches the address c.d -- that's done by the main addressmap_rewrite + * function. */ static addressmap_entry_t * addressmap_match_superdomains(char *address) { - strmap_iter_t *iter; - const char *key; - void *_val; addressmap_entry_t *val; - char *matched_domains = NULL; + char *cp; - for (iter = strmap_iter_init(addressmap); !strmap_iter_done(iter); ) { - strmap_iter_get(iter, &key, &_val); - val = _val; - if (key[0] == '.') { - if (!strcasecmpend(address, key) || !strcasecmp(address, &key[1])) { - matched_domains = strstr(address, key); - if (val->is_wildcard && matched_domains) - *matched_domains = '\0'; - return val; - } + cp = address; + while ((cp = strchr(cp, '.'))) { + /* cp now points to a suffix of address that begins with a . */ + val = strmap_get_lc(addressmap, cp+1); + if (val && val->src_wildcard) { + if (val->dst_wildcard) + *cp = '\0'; + return val; } - iter = strmap_iter_next(addressmap,iter); + ++cp; } - return 0; + return NULL; } /** Look at address, and rewrite it until it doesn't want any @@ -1098,11 +1103,12 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) } cp = tor_strdup(escaped_safe_str_client(address)); - if (ent->is_wildcard) - strlcpy(address + strlen(address), ent->new_address, - (maxlen - strlen(address))); - else + if (ent->dst_wildcard) { + strlcat(address, ".", maxlen); + strlcat(address, ent->new_address, maxlen); + } else { strlcpy(address, ent->new_address, maxlen); + } log_info(LD_APP, "Addressmap: rewriting %s to %s", cp, escaped_safe_str_client(address)); @@ -1174,13 +1180,26 @@ addressmap_have_mapping(const char *address, int update_expiry) * * If new_address is NULL, or equal to address, remove * any mappings that exist from address. - */ + * + * If wildcard_addr is true, then the mapping will match any address + * equal to address, or any address ending with a period followed by + * address. If wildcard_addr and wildcard_new_addr are + * both true, the mapping will rewrite addresses that end with + * ".address" into ones that end with ".new_address." + * + * It is an error to set wildcard_new_addr if wildcard_addr is + * not set. */ void addressmap_register(const char *address, char *new_address, time_t expires, - addressmap_entry_source_t source) + addressmap_entry_source_t source, + const int wildcard_addr, + const int wildcard_new_addr) { addressmap_entry_t *ent; + if (wildcard_new_addr) + tor_assert(wildcard_addr); + ent = strmap_get(addressmap, address); if (!new_address || !strcasecmp(address,new_address)) { /* Remove the mapping, if any. */ @@ -1217,7 +1236,8 @@ addressmap_register(const char *address, char *new_address, time_t expires, ent->expires = expires==2 ? 1 : expires; ent->num_resolve_failures = 0; ent->source = source; - ent->is_wildcard = (new_address[0] == '.') ? 1 : 0; + ent->src_wildcard = wildcard_addr ? 1 : 0; + ent->dst_wildcard = wildcard_new_addr ? 1 : 0; log_info(LD_CONFIG, "Addressmap: (re)mapped '%s' to '%s'", safe_str_client(address), @@ -1302,7 +1322,7 @@ client_dns_set_addressmap_impl(const char *address, const char *name, "%s", name); } addressmap_register(extendedaddress, tor_strdup(extendedval), - time(NULL) + ttl, ADDRMAPSRC_DNS); + time(NULL) + ttl, ADDRMAPSRC_DNS, 0, 0); } /** Record the fact that address resolved to val. @@ -1554,7 +1574,7 @@ addressmap_register_virtual_address(int type, char *new_address) log_info(LD_APP, "Registering map from %s to %s", *addrp, new_address); if (vent_needs_to_be_added) strmap_set(virtaddress_reversemap, new_address, vent); - addressmap_register(*addrp, new_address, 2, ADDRMAPSRC_AUTOMAP); + addressmap_register(*addrp, new_address, 2, ADDRMAPSRC_AUTOMAP, 0, 0); #if 0 { diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 830667e601..47c9c45b1a 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -78,7 +78,8 @@ int addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out); int addressmap_have_mapping(const char *address, int update_timeout); void addressmap_register(const char *address, char *new_address, - time_t expires, addressmap_entry_source_t source); + time_t expires, addressmap_entry_source_t source, + int address_wildcard, int new_address_wildcard); int parse_virtual_addr_network(const char *val, int validate_only, char **msg); int client_dns_incr_failures(const char *address); diff --git a/src/or/control.c b/src/or/control.c index f852659983..ce37aca5a6 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1331,7 +1331,7 @@ handle_control_mapaddress(control_connection_t *conn, uint32_t len, smartlist_add(reply, ans); } } else { - addressmap_register(from, tor_strdup(to), 1, ADDRMAPSRC_CONTROLLER); + addressmap_register(from, tor_strdup(to), 1, ADDRMAPSRC_CONTROLLER,0,0); tor_snprintf(ans, anslen, "250-%s", line); smartlist_add(reply, ans); } From ff3eb8e023f79edf7b04bf12f770bb3df558c033 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 8 Sep 2011 12:04:34 -0400 Subject: [PATCH 07/11] Forbid remapping of * It might be nice to support this someday, but for now it would fail with an infinite remap cycle. (If I say "remap * *.foo.exit", then example.com -> example.com.foo.exit -> example.com.foo.exit.foo.exit -> example.com.foo.exit.foo.exit.foo.exit -> ...) --- src/or/config.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/or/config.c b/src/or/config.c index ef54dcbff2..f841f932c5 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -4477,6 +4477,11 @@ config_register_addressmaps(const or_options_t *options) goto cleanup; } + if (!strcmp(to, "*") || !strcmp(from, "*")) { + log_warn(LD_CONFIG,"MapAddress '%s' is unsupported - can't remap from " + "or to *. Ignoring.",opt->value); + goto cleanup; + } /* Detect asterisks in expressions of type: '*.example.com' */ if (!strncmp(from,"*.",2)) { from += 2; From 00ecc2212660e3d31c1c5098e5bbef618ece5ef8 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 8 Sep 2011 12:19:27 -0400 Subject: [PATCH 08/11] Revise MapAddress manpage make the asciidoc work; make the example more generic; tighten the prose a little; be more specific that *.example.com matches example.com; simplify an example. --- doc/tor.1.txt | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/doc/tor.1.txt b/doc/tor.1.txt index eb794527c7..76791269cf 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -655,18 +655,19 @@ The following options are useful only for clients (that is, if 5050, 5190, 5222, 5223, 6523, 6667, 6697, 8300) **MapAddress** __address__ __newaddress__:: - When a request for address arrives to Tor, it will rewrite it to newaddress + When a request for address arrives to Tor, it will transform to newaddress before processing it. For example, if you always want connections to - www.indymedia.org to exit via __torserver__ (where __torserver__ is the - nickname of the server), use MapAddress www.indymedia.org - www.indymedia.org.torserver.exit. If the value is prepended with a - '*.', it is treated as matching an entire domain. For example, if you - always want connections to any sub-domain of indymedia.org to exit via + www.example.com to exit via __torserver__ (where __torserver__ is the + nickname of the server), use "MapAddress www.example.com + www.example.com.torserver.exit". If the value is prefixed with a + "\*.", matches an entire domain. For example, if you + always want connections to example.com and any if its subdomains + to exit via __torserver__ (where __torserver__ is the nickname of the server), use - MapAddress *.indymedia.org *.indymedia.org.torserver.exit. (Note the - leading '*.' in each part of the directive.) You can also redirect all - subdomains of a domain to a single address. For example, MapAddress - *.indymedia.org www.indymedia.org. + + "MapAddress \*.example.com \*.example.com.torserver.exit". (Note the + leading "*." in each part of the directive.) You can also redirect all + subdomains of a domain to a single address. For example, "MapAddress + *.example.com www.example.com". + + NOTES: @@ -681,18 +682,16 @@ The following options are useful only for clients (that is, if if you have the following in your torrc, www.torproject.org will map to 2.2.2.2: - MapAddress www.torproject.org 3.3.3.3 - MapAddress 1.1.1.1 4.4.4.4 MapAddress 1.1.1.1 2.2.2.2 MapAddress www.torproject.org 1.1.1.1 3. The following MapAddress expression is invalid (and will be - ignored) because you cannot map from a specific address to a wildcarded + ignored) because you cannot map from a specific address to a wildcard address: MapAddress www.torproject.org *.torproject.org.torserver.exit - 4. Using a wildcard as a regular expression (e.g. *ample.com) is + 4. Using a wildcard to match only part of a string (as in *ample.com) is also invalid. **NewCircuitPeriod** __NUM__:: From 04c622d72004fb7811bc2996551893119869b802 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 25 Nov 2011 19:46:11 -0500 Subject: [PATCH 09/11] Add some post-comma spaces to please arma Incidentally, we've got 30969 lines in master with a comma in them, of which 1995 have a comma followed by a non-newline, non-space character. So about 93% of our commas are right, but we have a substantial number of "crowded" lines. --- src/or/circuituse.c | 2 +- src/or/control.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/or/circuituse.c b/src/or/circuituse.c index fc252c9b18..7a2ab83adc 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1676,7 +1676,7 @@ consider_recording_trackhost(const entry_connection_t *conn, addressmap_register(conn->socks_request->address, new_address, time(NULL) + options->TrackHostExitsExpire, - ADDRMAPSRC_TRACKEXIT,0,0); + ADDRMAPSRC_TRACKEXIT, 0, 0); } /** Attempt to attach the connection conn to circ, and send a diff --git a/src/or/control.c b/src/or/control.c index ce37aca5a6..d570ef97c8 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1331,7 +1331,8 @@ handle_control_mapaddress(control_connection_t *conn, uint32_t len, smartlist_add(reply, ans); } } else { - addressmap_register(from, tor_strdup(to), 1, ADDRMAPSRC_CONTROLLER,0,0); + addressmap_register(from, tor_strdup(to), 1, + ADDRMAPSRC_CONTROLLER, 0, 0); tor_snprintf(ans, anslen, "250-%s", line); smartlist_add(reply, ans); } From 66859e2d4a7823a98a6842e5cf3b09c9fa47c704 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 25 Nov 2011 20:13:55 -0500 Subject: [PATCH 10/11] Fix an issue in my mapaddress domains code spotted by arma MapAddress *.torproject.org torproject.org would have been interpreted as a map from a domain to itself, and would have cleared the mapping. Now we require not only a match of domains, but of wildcards. --- src/or/connection_edge.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index f7b24112ce..4f26a6b972 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1178,15 +1178,18 @@ addressmap_have_mapping(const char *address, int update_expiry) * new_address should be a newly dup'ed string, which we'll use or * free as appropriate. We will leave address alone. * - * If new_address is NULL, or equal to address, remove - * any mappings that exist from address. - * * If wildcard_addr is true, then the mapping will match any address * equal to address, or any address ending with a period followed by * address. If wildcard_addr and wildcard_new_addr are * both true, the mapping will rewrite addresses that end with * ".address" into ones that end with ".new_address." * + * If new_address is NULL, or new_address is equal to + * address and wildcard_addr is equal to + * wildcard_new_addr, remove any mappings that exist from + * address. + * + * * It is an error to set wildcard_new_addr if wildcard_addr is * not set. */ void @@ -1201,7 +1204,8 @@ addressmap_register(const char *address, char *new_address, time_t expires, tor_assert(wildcard_addr); ent = strmap_get(addressmap, address); - if (!new_address || !strcasecmp(address,new_address)) { + if (!new_address || (!strcasecmp(address,new_address) && + wildcard_addr == wildcard_new_addr)) { /* Remove the mapping, if any. */ tor_free(new_address); if (ent) { From e8d598c4acc55b655f2e49566bf8802d7d6524ba Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 30 Nov 2011 14:02:58 -0500 Subject: [PATCH 11/11] Tweak addressmap_rewrite a little more This resolves a loop warning on "MapAddress *.example.com example.com", makes the rewrite log messages correct, and fixes the behavior of "MapAddress *.a *.b" when just given "a" as an input. --- src/or/connection_edge.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 4f26a6b972..3b6231de87 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1087,23 +1087,38 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) { addressmap_entry_t *ent; int rewrites; - char *cp; time_t expires = TIME_MAX; for (rewrites = 0; rewrites < 16; rewrites++) { + int exact_match = 0; + char *addr_orig = tor_strdup(escaped_safe_str_client(address)); + ent = strmap_get(addressmap, address); - if (!ent || !ent->new_address) + if (!ent || !ent->new_address) { ent = addressmap_match_superdomains(address); + } else { + if (ent->src_wildcard && !ent->dst_wildcard && + !strcasecmp(address, ent->new_address)) { + /* This is a rule like *.example.com example.com, and we just got + * "example.com" */ + tor_free(addr_orig); + if (expires_out) + *expires_out = expires; + return rewrites > 0; + } + + exact_match = 1; + } if (!ent || !ent->new_address) { + tor_free(addr_orig); if (expires_out) *expires_out = expires; return (rewrites > 0); /* done, no rewrite needed */ } - cp = tor_strdup(escaped_safe_str_client(address)); - if (ent->dst_wildcard) { + if (ent->dst_wildcard && !exact_match) { strlcat(address, ".", maxlen); strlcat(address, ent->new_address, maxlen); } else { @@ -1111,10 +1126,10 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) } log_info(LD_APP, "Addressmap: rewriting %s to %s", - cp, escaped_safe_str_client(address)); + addr_orig, escaped_safe_str_client(address)); if (ent->expires > 1 && ent->expires < expires) expires = ent->expires; - tor_free(cp); + tor_free(addr_orig); } log_warn(LD_CONFIG, "Loop detected: we've rewritten %s 16 times! Using it as-is.",