Loading changes/bug933 0 → 100644 +4 −0 Changes for changes/bug933: 4 added lines, 0 removed lines. Original line number Diff line number Diff line o Minor features: - Allow MapAddress directives to specify matches against super-domains, as in 'MapAddress *.torproject.org *.torproject.org.torserver.exit'. Implements issue 933. doc/tor.1.txt +37 −4 Changes for doc/tor.1.txt: 37 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -691,11 +691,44 @@ 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". 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 \*.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: 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 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 wildcard address: MapAddress www.torproject.org *.torproject.org.torserver.exit 4. Using a wildcard to match only part of a string (as in *ample.com) is also invalid. **NewCircuitPeriod** __NUM__:: Every NUM seconds consider whether to build a new circuit. (Default: 30 Loading src/or/circuituse.c +1 −1 Changes for src/or/circuituse.c: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -1687,7 +1687,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 <b>conn</b> to <b>circ</b>, and send a Loading src/or/config.c +47 −11 Changes for src/or/config.c: 47 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -4647,24 +4647,60 @@ 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) { 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 (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."); if (to[0] == '.' || from[0] == '.') { log_warn(LD_CONFIG,"MapAddress '%s' is ambiguous - address starts with a" "'.'. Ignoring.",opt->value); 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; } } else { log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.", opt->value); /* 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_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", opt->value); goto cleanup; } if (address_is_invalid_destination(to, 1)) { log_warn(LD_CONFIG, "Skipping invalid argument '%s' to MapAddress", opt->value); goto cleanup; } 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."); cleanup: SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp)); smartlist_clear(elts); } Loading src/or/connection_edge.c +93 −12 Changes for src/or/connection_edge.c: 93 added lines, 12 removed lines. Original line number Diff line number Diff line Loading @@ -803,11 +803,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; unsigned src_wildcard:1; unsigned dst_wildcard:1; short num_resolve_failures; } addressmap_entry_t; Loading Loading @@ -1054,6 +1061,37 @@ addressmap_free_all(void) virtaddress_reversemap = NULL; } /** 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). * Return the matching entry in AddressMap or NULL if no match is found. * For expressions such as '*.c.d *.e.f', truncate <b>address</b> '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) { addressmap_entry_t *val; char *cp; 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; } ++cp; } return NULL; } /** 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 Loading @@ -1066,25 +1104,49 @@ 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) { 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(ent->new_address)); if (ent->dst_wildcard && !exact_match) { 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", escaped_safe_str_client(address), cp); addr_orig, escaped_safe_str_client(address)); if (ent->expires > 1 && ent->expires < expires) expires = ent->expires; tor_free(cp); strlcpy(address, ent->new_address, maxlen); tor_free(addr_orig); } log_warn(LD_CONFIG, "Loop detected: we've rewritten %s 16 times! Using it as-is.", Loading Loading @@ -1148,17 +1210,34 @@ addressmap_have_mapping(const char *address, int update_expiry) * <b>new_address</b> should be a newly dup'ed string, which we'll use or * free as appropriate. We will leave address alone. * * If <b>new_address</b> is NULL, or equal to <b>address</b>, remove * any mappings that exist from <b>address</b>. */ * If <b>wildcard_addr</b> is true, then the mapping will match any address * equal to <b>address</b>, or any address ending with a period followed by * <b>address</b>. If <b>wildcard_addr</b> and <b>wildcard_new_addr</b> are * both true, the mapping will rewrite addresses that end with * ".<b>address</b>" into ones that end with ".<b>new_address</b>." * * If <b>new_address</b> is NULL, or <b>new_address</b> is equal to * <b>address</b> and <b>wildcard_addr</b> is equal to * <b>wildcard_new_addr</b>, remove any mappings that exist from * <b>address</b>. * * * It is an error to set <b>wildcard_new_addr</b> if <b>wildcard_addr</b> 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)) { if (!new_address || (!strcasecmp(address,new_address) && wildcard_addr == wildcard_new_addr)) { /* Remove the mapping, if any. */ tor_free(new_address); if (ent) { Loading Loading @@ -1193,6 +1272,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->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), Loading Loading @@ -1277,7 +1358,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 <b>address</b> resolved to <b>val</b>. Loading Loading @@ -1529,7 +1610,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 { Loading Loading
changes/bug933 0 → 100644 +4 −0 Changes for changes/bug933: 4 added lines, 0 removed lines. Original line number Diff line number Diff line o Minor features: - Allow MapAddress directives to specify matches against super-domains, as in 'MapAddress *.torproject.org *.torproject.org.torserver.exit'. Implements issue 933.
doc/tor.1.txt +37 −4 Changes for doc/tor.1.txt: 37 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -691,11 +691,44 @@ 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". 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 \*.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: 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 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 wildcard address: MapAddress www.torproject.org *.torproject.org.torserver.exit 4. Using a wildcard to match only part of a string (as in *ample.com) is also invalid. **NewCircuitPeriod** __NUM__:: Every NUM seconds consider whether to build a new circuit. (Default: 30 Loading
src/or/circuituse.c +1 −1 Changes for src/or/circuituse.c: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -1687,7 +1687,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 <b>conn</b> to <b>circ</b>, and send a Loading
src/or/config.c +47 −11 Changes for src/or/config.c: 47 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -4647,24 +4647,60 @@ 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) { 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 (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."); if (to[0] == '.' || from[0] == '.') { log_warn(LD_CONFIG,"MapAddress '%s' is ambiguous - address starts with a" "'.'. Ignoring.",opt->value); 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; } } else { log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.", opt->value); /* 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_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", opt->value); goto cleanup; } if (address_is_invalid_destination(to, 1)) { log_warn(LD_CONFIG, "Skipping invalid argument '%s' to MapAddress", opt->value); goto cleanup; } 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."); cleanup: SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp)); smartlist_clear(elts); } Loading
src/or/connection_edge.c +93 −12 Changes for src/or/connection_edge.c: 93 added lines, 12 removed lines. Original line number Diff line number Diff line Loading @@ -803,11 +803,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; unsigned src_wildcard:1; unsigned dst_wildcard:1; short num_resolve_failures; } addressmap_entry_t; Loading Loading @@ -1054,6 +1061,37 @@ addressmap_free_all(void) virtaddress_reversemap = NULL; } /** 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). * Return the matching entry in AddressMap or NULL if no match is found. * For expressions such as '*.c.d *.e.f', truncate <b>address</b> '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) { addressmap_entry_t *val; char *cp; 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; } ++cp; } return NULL; } /** 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 Loading @@ -1066,25 +1104,49 @@ 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) { 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(ent->new_address)); if (ent->dst_wildcard && !exact_match) { 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", escaped_safe_str_client(address), cp); addr_orig, escaped_safe_str_client(address)); if (ent->expires > 1 && ent->expires < expires) expires = ent->expires; tor_free(cp); strlcpy(address, ent->new_address, maxlen); tor_free(addr_orig); } log_warn(LD_CONFIG, "Loop detected: we've rewritten %s 16 times! Using it as-is.", Loading Loading @@ -1148,17 +1210,34 @@ addressmap_have_mapping(const char *address, int update_expiry) * <b>new_address</b> should be a newly dup'ed string, which we'll use or * free as appropriate. We will leave address alone. * * If <b>new_address</b> is NULL, or equal to <b>address</b>, remove * any mappings that exist from <b>address</b>. */ * If <b>wildcard_addr</b> is true, then the mapping will match any address * equal to <b>address</b>, or any address ending with a period followed by * <b>address</b>. If <b>wildcard_addr</b> and <b>wildcard_new_addr</b> are * both true, the mapping will rewrite addresses that end with * ".<b>address</b>" into ones that end with ".<b>new_address</b>." * * If <b>new_address</b> is NULL, or <b>new_address</b> is equal to * <b>address</b> and <b>wildcard_addr</b> is equal to * <b>wildcard_new_addr</b>, remove any mappings that exist from * <b>address</b>. * * * It is an error to set <b>wildcard_new_addr</b> if <b>wildcard_addr</b> 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)) { if (!new_address || (!strcasecmp(address,new_address) && wildcard_addr == wildcard_new_addr)) { /* Remove the mapping, if any. */ tor_free(new_address); if (ent) { Loading Loading @@ -1193,6 +1272,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->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), Loading Loading @@ -1277,7 +1358,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 <b>address</b> resolved to <b>val</b>. Loading Loading @@ -1529,7 +1610,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 { Loading