diff options
author | Nick Mathewson <nickm@torproject.org> | 2011-09-08 11:54:24 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2011-11-30 14:08:11 -0500 |
commit | 69d16900aaf1d54b44d2b28514a09873154c63d3 (patch) | |
tree | dae8d76b14f99e94af2291fab286dc47100a5710 | |
parent | df0da3991cb00efdf7c9362e805877e63ce8a46e (diff) | |
download | tor-69d16900aaf1d54b44d2b28514a09873154c63d3.tar.gz tor-69d16900aaf1d54b44d2b28514a09873154c63d3.zip |
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).
-rw-r--r-- | src/or/circuituse.c | 2 | ||||
-rw-r--r-- | src/or/config.c | 24 | ||||
-rw-r--r-- | src/or/connection_edge.c | 80 | ||||
-rw-r--r-- | src/or/connection_edge.h | 3 | ||||
-rw-r--r-- | src/or/control.c | 2 |
5 files changed, 69 insertions, 42 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 <b>conn</b> to <b>circ</b>, 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 <b>address</b> '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 <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) { - strmap_iter_t *iter; - const char *key; - void *_val; addressmap_entry_t *val; - char *matched_domains = NULL; - - 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; - } + 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; } - 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 <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>." + * + * 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)) { /* 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 <b>address</b> resolved to <b>val</b>. @@ -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); } |