mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
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).
This commit is contained in:
parent
df0da3991c
commit
69d16900aa
@ -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
|
||||
|
@ -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.");
|
||||
|
@ -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;
|
||||
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 <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
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user