aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-11-30 14:10:22 -0500
committerNick Mathewson <nickm@torproject.org>2011-11-30 14:10:22 -0500
commit3b88b638264011158d27d5b451fd07d16f60e16b (patch)
tree3af8591550471211fd0ee0a20f9602c4d761a7ce /src/or
parent60b41cd435c0acef274209a2a9b494b5f42964f6 (diff)
parente8d598c4acc55b655f2e49566bf8802d7d6524ba (diff)
downloadtor-3b88b638264011158d27d5b451fd07d16f60e16b.tar
tor-3b88b638264011158d27d5b451fd07d16f60e16b.tar.gz
Merge branch 'bug933_nm_rebased_v2'
Conflicts: src/test/test.c
Diffstat (limited to 'src/or')
-rw-r--r--src/or/circuituse.c2
-rw-r--r--src/or/config.c62
-rw-r--r--src/or/connection_edge.c105
-rw-r--r--src/or/connection_edge.h3
-rw-r--r--src/or/control.c3
5 files changed, 147 insertions, 28 deletions
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 4382d4412..0cb934491 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -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
diff --git a/src/or/config.c b/src/or/config.c
index 391d2905f..9da33ba38 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -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) {
- 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.");
- }
- }
- } 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;
+ }
+
+ 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_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);
}
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index ad0e8c53f..4fb220642 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -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;
@@ -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
@@ -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.",
@@ -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) {
@@ -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),
@@ -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>.
@@ -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
{
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index 830667e60..47c9c45b1 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 65b161996..20caabf0c 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);
+ addressmap_register(from, tor_strdup(to), 1,
+ ADDRMAPSRC_CONTROLLER, 0, 0);
tor_snprintf(ans, anslen, "250-%s", line);
smartlist_add(reply, ans);
}