diff options
-rw-r--r-- | doc/tor.1.txt | 10 | ||||
-rw-r--r-- | src/or/config.c | 13 | ||||
-rw-r--r-- | src/or/connection_edge.c | 25 | ||||
-rw-r--r-- | 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 <b>address</b> '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)); |