[tor-commits] [tor/master] bug933 - Match against super-domains in MapAddress

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


commit c6d8c6baaa983aecd6a5121ec6ed8e2d9a2a24be
Author: Robert Hogan <robert at webkit.org>
Date:   Mon Aug 2 20:09:37 2010 +0100

    bug933 - Match against super-domains in MapAddress
    
    Allow MapAddress to handle directives such as:
    
    MapAddress .torproject.org .torserver.exit
    MapAddress .org 1.1.1.1
    
    Add tests for addressmap_rewrite.
---
 changes/bug933           |    4 ++
 doc/tor.1.txt            |    7 ++-
 src/or/connection_edge.c |   41 ++++++++++++++-
 src/test/Makefile.am     |    1 +
 src/test/test.c          |    2 +
 src/test/test_config.c   |  127 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 178 insertions(+), 4 deletions(-)

diff --git a/changes/bug933 b/changes/bug933
new file mode 100644
index 0000000..b646858
--- /dev/null
+++ b/changes/bug933
@@ -0,0 +1,4 @@
+  o Minor features:
+    - Allow MapAddress directives to specify matches against super-domains,
+      as in 'MapAddress *.torproject.org *.torproject.org.torserver.exit'.
+      Implements issue 933.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 4edee80..4d4ad9f 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -659,7 +659,12 @@ The following options are useful only for clients (that is, if
     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.indymedia.org.torserver.exit". If the value is prepended with a \'.\',
+    it is treated as matching an entire domain.For example, if you always
+    want connections to  any sub-domain of indymedia.org to exit via
+    __torserver__ (where __torserver__ is the nickname of the server), use
+    "MapAddress .indymedia.org .torserver.exit". (Note the leading '.' in
+    each part of the directive.)
 
 **NewCircuitPeriod** __NUM__::
     Every NUM seconds consider whether to build a new circuit. (Default: 30
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index f59f44c..4bb49c8 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -1037,6 +1037,29 @@ addressmap_free_all(void)
   virtaddress_reversemap = NULL;
 }
 
+/** Try to find a match for AddressMap directives that use
+ *  domain notation such as '.torproject.org .exitnode.exit'.
+ */
+static addressmap_entry_t *
+addressmap_match_superdomains(char *address)
+{
+  strmap_iter_t *iter;
+  const char *key;
+  void *_val;
+  addressmap_entry_t *val;
+
+  for (iter = strmap_iter_init(addressmap); !strmap_iter_done(iter); ) {
+    strmap_iter_get(iter, &key, &_val);
+    val = _val;
+    if (key[0] == '.') { /* match end */
+      if (!strcasecmpend(address, key) || !strcasecmp(address, &key[1]))
+        return val;
+    }
+    iter = strmap_iter_next(addressmap,iter);
+  }
+  return 0;
+}
+
 /** 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
@@ -1050,24 +1073,36 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out)
   addressmap_entry_t *ent;
   int rewrites;
   char *cp;
+  char *s;
   time_t expires = TIME_MAX;
 
   for (rewrites = 0; rewrites < 16; rewrites++) {
     ent = strmap_get(addressmap, address);
 
+    if (!ent || !ent->new_address)
+      ent = addressmap_match_superdomains(address);
+
     if (!ent || !ent->new_address) {
       if (expires_out)
         *expires_out = expires;
       return (rewrites > 0); /* done, no rewrite needed */
     }
 
-    cp = tor_strdup(escaped_safe_str_client(ent->new_address));
+    cp = tor_strdup(escaped_safe_str_client(address));
+    /* If the address to rewrite to is in the form '.exitnode.exit'
+       then append it to the given address */
+    s = strrchr(ent->new_address,'.');
+    if (ent->new_address[0] == '.' && !strcmp(s+1,"exit"))
+      strlcpy(address + strlen(address), ent->new_address,
+              (maxlen - strlen(address)));
+    else
+      strlcpy(address, ent->new_address, maxlen);
+
     log_info(LD_APP, "Addressmap: rewriting %s to %s",
-             escaped_safe_str_client(address), cp);
+             cp, escaped_safe_str_client(address));
     if (ent->expires > 1 && ent->expires < expires)
       expires = ent->expires;
     tor_free(cp);
-    strlcpy(address, ent->new_address, maxlen);
   }
   log_warn(LD_CONFIG,
            "Loop detected: we've rewritten %s 16 times! Using it as-is.",
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 8527150..e675431 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -20,6 +20,7 @@ test_SOURCES = \
 	test_dir.c \
 	test_microdesc.c \
 	test_util.c \
+	test_config.c \
 	tinytest.c
 
 test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
diff --git a/src/test/test.c b/src/test/test.c
index 605e44c..76644a7 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1941,6 +1941,7 @@ extern struct testcase_t container_tests[];
 extern struct testcase_t util_tests[];
 extern struct testcase_t dir_tests[];
 extern struct testcase_t microdesc_tests[];
+extern struct testcase_t config_tests[];
 
 static struct testgroup_t testgroups[] = {
   { "", test_array },
@@ -1951,6 +1952,7 @@ static struct testgroup_t testgroups[] = {
   { "util/", util_tests },
   { "dir/", dir_tests },
   { "dir/md/", microdesc_tests },
+  { "config/", config_tests },
   END_OF_GROUPS
 };
 
diff --git a/src/test/test_config.c b/src/test/test_config.c
new file mode 100644
index 0000000..f39a9ef
--- /dev/null
+++ b/src/test/test_config.c
@@ -0,0 +1,127 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2010, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "or.h"
+#include "config.h"
+#include "connection_edge.h"
+#include "test.h"
+
+static void
+test_config_addressmap(void)
+{
+  char buf[1024];
+  char address[256];
+  time_t expires = TIME_MAX;
+  strlcpy(buf, "MapAddress .google.com .torserver.exit\n"
+          "MapAddress www.torproject.org 1.1.1.1\n"
+          "MapAddress other.torproject.org "
+            "this.torproject.org.otherserver.exit\n"
+          "MapAddress test.torproject.org 2.2.2.2\n"
+          "MapAddress www.google.com 3.3.3.3\n"
+          "MapAddress www.example.org 4.4.4.4\n"
+          "MapAddress 4.4.4.4 5.5.5.5\n"
+          "MapAddress www.infiniteloop.org 6.6.6.6\n"
+          "MapAddress 6.6.6.6 www.infiniteloop.org\n"
+          , sizeof(buf));
+
+  config_get_lines(buf, &(get_options()->AddressMap));
+  config_register_addressmaps(get_options());
+
+  /* Where no mapping for FQDN match on top-level domain */
+  strlcpy(address, "reader.google.com", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "reader.google.com.torserver.exit");
+
+  /* Where mapping for FQDN match on FQDN */
+  strlcpy(address, "www.google.com", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "3.3.3.3");
+
+  strlcpy(address, "www.torproject.org", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "1.1.1.1");
+
+  strlcpy(address, "other.torproject.org", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "this.torproject.org.otherserver.exit");
+
+  strlcpy(address, "test.torproject.org", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "2.2.2.2");
+
+  /* Test a chain of address mappings */
+  strlcpy(address, "www.example.org", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "5.5.5.5");
+
+  /* Test infinite address mapping results in no change */
+  strlcpy(address, "www.infiniteloop.org", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "www.infiniteloop.org");
+
+  /* Test we don't find false positives */
+  strlcpy(address, "www.example.com", sizeof(address));
+  test_assert(!addressmap_rewrite(address, sizeof(address), &expires));
+
+  /* Test top-level-domain matching a bit harder */
+  addressmap_clear_configured();
+  strlcpy(buf, "MapAddress .com .torserver.exit\n"
+          "MapAddress .torproject.org 1.1.1.1\n"
+          "MapAddress .net 2.2.2.2\n"
+          , sizeof(buf));
+  config_get_lines(buf, &(get_options()->AddressMap));
+  config_register_addressmaps(get_options());
+
+  strlcpy(address, "www.abc.com", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "www.abc.com.torserver.exit");
+
+  strlcpy(address, "www.def.com", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "www.def.com.torserver.exit");
+
+  strlcpy(address, "www.torproject.org", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "1.1.1.1");
+
+  strlcpy(address, "test.torproject.org", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "1.1.1.1");
+
+  strlcpy(address, "torproject.net", sizeof(address));
+  test_assert(addressmap_rewrite(address, sizeof(address), &expires));
+  test_streq(address, "2.2.2.2");
+
+  /* We don't support '.' as a mapping directive */
+  addressmap_clear_configured();
+  strlcpy(buf, "MapAddress . .torserver.exit\n", sizeof(buf));
+  config_get_lines(buf, &(get_options()->AddressMap));
+  config_register_addressmaps(get_options());
+
+  strlcpy(address, "www.abc.com", sizeof(address));
+  test_assert(!addressmap_rewrite(address, sizeof(address), &expires));
+
+  strlcpy(address, "www.def.net", sizeof(address));
+  test_assert(!addressmap_rewrite(address, sizeof(address), &expires));
+
+  strlcpy(address, "www.torproject.org", sizeof(address));
+  test_assert(!addressmap_rewrite(address, sizeof(address), &expires));
+
+done:
+  ;
+}
+
+#define CONFIG_LEGACY(name)                                               \
+  { #name, legacy_test_helper, 0, &legacy_setup, test_config_ ## name }
+
+#define CONFIG_TEST(name, flags)                          \
+  { #name, test_config_ ## name, flags, NULL, NULL }
+
+struct testcase_t config_tests[] = {
+  CONFIG_LEGACY(addressmap),
+  END_OF_TESTCASES
+};
+





More information about the tor-commits mailing list