[tor-commits] [tor/master] Refactor addressmap_match_superdomains and representation of wildcards

nickm at torproject.org nickm at torproject.org
Wed Nov 30 19:10:01 UTC 2011


commit 69d16900aaf1d54b44d2b28514a09873154c63d3
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Sep 8 11:54:24 2011 -0400

    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).
---
 src/or/circuituse.c      |    2 +-
 src/or/config.c          |   24 ++++++++-----
 src/or/connection_edge.c |   80 ++++++++++++++++++++++++++++-----------------
 src/or/connection_edge.h |    3 +-
 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 f7f080d..fc252c9 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 1d42413..ef54dcb 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 284b320..f7b2411 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 830667e..47c9c45 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 f852659..ce37aca 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);
       }





More information about the tor-commits mailing list