Browse Source

Merge remote-tracking branch 'origin/maint-0.2.2'

Conflicts:
	src/or/connection_edge.c
Nick Mathewson 13 years ago
parent
commit
37e3fb8af2
10 changed files with 139 additions and 27 deletions
  1. 13 0
      changes/bug1345
  2. 19 0
      src/common/container.c
  3. 2 0
      src/common/container.h
  4. 28 23
      src/or/circuituse.c
  5. 2 0
      src/or/circuituse.h
  6. 23 0
      src/or/config.c
  7. 48 3
      src/or/connection_edge.c
  8. 1 0
      src/or/connection_edge.h
  9. 0 1
      src/or/main.c
  10. 3 0
      src/or/or.h

+ 13 - 0
changes/bug1345

@@ -0,0 +1,13 @@
+  o Minor bugfixes:
+    - On SIGHUP, do not clear out all TrackHostExits mappings, client DNS
+      cache entries, and virtual address mappings: that's what NEWNYM is
+      for.  Bugfix on Tor 0.1.0.1-rc; fixes bug 1345.
+    - When TrackHostExits is changed from a controller, remove any
+      mappings for hosts that should no longer have their exits tracked.
+      Bugfix on Tor 0.1.0.1-rc.
+    - When VirtualAddrNetwork option is changed from a controller,
+      remove any mappings for hosts that were automapped to
+      that network.  Bugfix on 0.1.1.19-rc.
+    - When one of the AutomapHosts* options is changed from a
+      controller, remove any mappings for hosts that should no longer be
+      automapped.  Bugfix on 0.2.0.1-alpha.

+ 19 - 0
src/common/container.c

@@ -215,6 +215,25 @@ smartlist_string_num_isin(const smartlist_t *sl, int num)
   return smartlist_string_isin(sl, buf);
 }
 
+/** Return true iff the two lists contain the same strings in the same
+ * order, or if they are both NULL. */
+int
+smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
+{
+  if (sl1 == NULL)
+    return sl2 == NULL;
+  if (sl2 == NULL)
+    return 0;
+  if (smartlist_len(sl1) != smartlist_len(sl2))
+    return 0;
+  SMARTLIST_FOREACH(sl1, const char *, cp1, {
+      const char *cp2 = smartlist_get(sl2, cp1_sl_idx);
+      if (strcmp(cp1, cp2))
+        return 0;
+    });
+  return 1;
+}
+
 /** Return true iff <b>sl</b> has some element E such that
  * tor_memeq(E,<b>element</b>,DIGEST_LEN)
  */

+ 2 - 0
src/common/container.h

@@ -42,6 +42,8 @@ int smartlist_string_pos(const smartlist_t *, const char *elt) ATTR_PURE;
 int smartlist_string_isin_case(const smartlist_t *sl, const char *element)
   ATTR_PURE;
 int smartlist_string_num_isin(const smartlist_t *sl, int num) ATTR_PURE;
+int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
+  ATTR_PURE;
 int smartlist_digest_isin(const smartlist_t *sl, const char *element)
   ATTR_PURE;
 int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2)

+ 28 - 23
src/or/circuituse.c

@@ -1478,15 +1478,35 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
   }
 }
 
-/** If an exit wasn't specifically chosen, save the history for future
- * use. */
+/** Return true iff <b>address</b> is matched by one of the entries in
+ * TrackHostExits. */
+int
+hostname_in_track_host_exits(or_options_t *options, const char *address)
+{
+  if (!options->TrackHostExits)
+    return 0;
+  SMARTLIST_FOREACH_BEGIN(options->TrackHostExits, const char *, cp) {
+    if (cp[0] == '.') { /* match end */
+      if (cp[1] == '\0' ||
+          !strcasecmpend(address, cp) ||
+          !strcasecmp(address, &cp[1]))
+        return 1;
+    } else if (strcasecmp(cp, address) == 0) {
+      return 1;
+    }
+  } SMARTLIST_FOREACH_END(cp);
+  return 0;
+}
+
+/** If an exit wasn't explicitly specified for <b>conn</b>, consider saving
+ * the exit that we *did* choose for use by future connections to
+ * <b>conn</b>'s destination.
+ */
 static void
 consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
 {
-  int found_needle = 0;
   or_options_t *options = get_options();
-  size_t len;
-  char *new_address;
+  char *new_address = NULL;
   char fp[HEX_DIGEST_LEN+1];
 
   /* Search the addressmap for this conn's destination. */
@@ -1496,18 +1516,8 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
                               options->TrackHostExitsExpire))
     return; /* nothing to track, or already mapped */
 
-  SMARTLIST_FOREACH(options->TrackHostExits, const char *, cp, {
-    if (cp[0] == '.') { /* match end */
-      if (cp[1] == '\0' ||
-          !strcasecmpend(conn->socks_request->address, cp) ||
-          !strcasecmp(conn->socks_request->address, &cp[1]))
-          found_needle = 1;
-    } else if (strcasecmp(cp, conn->socks_request->address) == 0) {
-      found_needle = 1;
-    }
-  });
-
-  if (!found_needle || !circ->build_state->chosen_exit)
+  if (!hostname_in_track_host_exits(options, conn->socks_request->address) ||
+      !circ->build_state->chosen_exit)
     return;
 
   /* write down the fingerprint of the chosen exit, not the nickname,
@@ -1516,12 +1526,7 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
                 circ->build_state->chosen_exit->identity_digest, DIGEST_LEN);
 
   /* Add this exit/hostname pair to the addressmap. */
-  len = strlen(conn->socks_request->address) + 1 /* '.' */ +
-        strlen(fp) + 1 /* '.' */ +
-        strlen("exit") + 1 /* '\0' */;
-  new_address = tor_malloc(len);
-
-  tor_snprintf(new_address, len, "%s.%s.exit",
+  tor_asprintf(&new_address, "%s.%s.exit",
                conn->socks_request->address, fp);
 
   addressmap_register(conn->socks_request->address, new_address,

+ 2 - 0
src/or/circuituse.h

@@ -50,5 +50,7 @@ int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
                                                   crypt_path_t *cpath);
 int connection_ap_handshake_attach_circuit(edge_connection_t *conn);
 
+int hostname_in_track_host_exits(or_options_t *options, const char *address);
+
 #endif
 

+ 23 - 0
src/or/config.c

@@ -1285,6 +1285,8 @@ options_act(or_options_t *old_options)
 
   /* Check for transitions that need action. */
   if (old_options) {
+    int revise_trackexithosts = 0;
+    int revise_automap_entries = 0;
     if ((options->UseEntryGuards && !old_options->UseEntryGuards) ||
         !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes) ||
         !routerset_equal(old_options->ExcludeExitNodes,
@@ -1297,9 +1299,30 @@ options_act(or_options_t *old_options)
                "excluded node lists. Abandoning previous circuits.");
       circuit_mark_all_unused_circs();
       circuit_expire_all_dirty_circs();
+      revise_trackexithosts = 1;
+    }
+
+    if (!smartlist_strings_eq(old_options->TrackHostExits,
+                              options->TrackHostExits))
+      revise_trackexithosts = 1;
+
+    if (revise_trackexithosts)
       addressmap_clear_excluded_trackexithosts(options);
+
+    if (old_options->AutomapHostsOnResolve && !options->AutomapHostsOnResolve) {
+      revise_automap_entries = 1;
+    } else if (options->AutomapHostsOnResolve) {
+      if (!smartlist_strings_eq(old_options->AutomapHostsSuffixes,
+                                options->AutomapHostsSuffixes))
+        revise_automap_entries = 1;
+      else if (!opt_streq(old_options->VirtualAddrNetwork,
+                          options->VirtualAddrNetwork))
+        revise_automap_entries = 1;
     }
 
+    if (revise_automap_entries)
+      addressmap_clear_invalid_automaps(options);
+
 /* How long should we delay counting bridge stats after becoming a bridge?
  * We use this so we don't count people who used our bridge thinking it is
  * a relay. If you change this, don't forget to change the log message

+ 48 - 3
src/or/connection_edge.c

@@ -810,7 +810,8 @@ clear_trackexithost_mappings(const char *exitname)
 }
 
 /** Remove all TRACKEXIT mappings from the addressmap for which the target
- * host is unknown or no longer allowed. */
+ * host is unknown or no longer allowed, or for which the source address
+ * is no longer in trackexithosts. */
 void
 addressmap_clear_excluded_trackexithosts(or_options_t *options)
 {
@@ -851,7 +852,8 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
     tor_free(nodename);
     if (!node ||
         (allow_nodes && !routerset_contains_node(allow_nodes, node)) ||
-        routerset_contains_node(exclude_nodes, node)) {
+        routerset_contains_node(exclude_nodes, node) ||
+        !hostname_in_track_host_exits(options, address)) {
       /* We don't know this one, or we want to be rid of it. */
       addressmap_ent_remove(address, ent);
       MAP_DEL_CURRENT(address);
@@ -859,6 +861,49 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
   } STRMAP_FOREACH_END;
 }
 
+/** Remove all AUTOMAP mappings from the addressmap for which the
+ * source address no longer matches AutomapHostsSuffixes, which is
+ * no longer allowed by AutomapHostsOnResolve, or for which the
+ * target address is no longer in the virtual network. */
+void
+addressmap_clear_invalid_automaps(or_options_t *options)
+{
+  int clear_all = !options->AutomapHostsOnResolve;
+  const smartlist_t *suffixes = options->AutomapHostsSuffixes;
+
+  if (!addressmap)
+    return;
+
+  if (!suffixes)
+    clear_all = 1; /* This should be impossible, but let's be sure. */
+
+  STRMAP_FOREACH_MODIFY(addressmap, src_address, addressmap_entry_t *, ent) {
+    int remove = clear_all;
+    if (ent->source != ADDRMAPSRC_AUTOMAP)
+      continue; /* not an automap mapping. */
+
+    if (!remove) {
+      int suffix_found = 0;
+      SMARTLIST_FOREACH(suffixes, const char *, suffix, {
+          if (!strcasecmpend(src_address, suffix)) {
+            suffix_found = 1;
+            break;
+          }
+      });
+      if (!suffix_found)
+        remove = 1;
+    }
+
+    if (!remove && ! address_is_in_virtual_range(ent->new_address))
+      remove = 1;
+
+    if (remove) {
+      addressmap_ent_remove(src_address, ent);
+      MAP_DEL_CURRENT(src_address);
+    }
+  } STRMAP_FOREACH_END;
+}
+
 /** Remove all entries from the addressmap that were set via the
  * configuration file or the command line. */
 void
@@ -1370,7 +1415,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_CONTROLLER);
+  addressmap_register(*addrp, new_address, 2, ADDRMAPSRC_AUTOMAP);
 
 #if 0
   {

+ 1 - 0
src/or/connection_edge.h

@@ -64,6 +64,7 @@ int address_is_invalid_destination(const char *address, int client);
 
 void addressmap_init(void);
 void addressmap_clear_excluded_trackexithosts(or_options_t *options);
+void addressmap_clear_invalid_automaps(or_options_t *options);
 void addressmap_clean(time_t now);
 void addressmap_clear_configured(void);
 void addressmap_clear_transient(void);

+ 0 - 1
src/or/main.c

@@ -1639,7 +1639,6 @@ do_hup(void)
 
   router_reset_warnings();
   routerlist_reset_warnings();
-  addressmap_clear_transient();
   /* first, reload config variables, in case they've changed */
   if (options->ReloadTorrcOnSIGHUP) {
     /* no need to provide argc/v, they've been cached in init_from_config */

+ 3 - 0
src/or/or.h

@@ -3335,6 +3335,9 @@ typedef enum setopt_err_t {
 typedef enum {
   /** We're remapping this address because the controller told us to. */
   ADDRMAPSRC_CONTROLLER,
+  /** We're remapping this address because of an AutomapHostsOnResolve
+   * configuration. */
+  ADDRMAPSRC_AUTOMAP,
   /** We're remapping this address because our configuration (via torrc, the
    * command line, or a SETCONF command) told us to. */
   ADDRMAPSRC_TORRC,