Parcourir la source

Implement "Dont-Care" from addresses to MapAddress control message. For safety, refuse to launch connections to unmapped addresses in the dont-care range.

svn:r3725
Nick Mathewson il y a 20 ans
Parent
commit
65230fd39f
4 fichiers modifiés avec 104 ajouts et 4 suppressions
  1. 8 4
      doc/TODO
  2. 82 0
      src/or/connection_edge.c
  3. 12 0
      src/or/control.c
  4. 2 0
      src/or/or.h

+ 8 - 4
doc/TODO

@@ -59,14 +59,16 @@ N  . Implement pending controller features.
       - List of address mappings (all, or mapaddress+config,
                                   or just mapadddress?)
     o POSTDESCRIPTOR
-    . MAPADDRESS
+    o MAPADDRESS
       o Map A->B.
-      - Map DontCare->B.
+      o Map DontCare->B.
+    - Way to handle overlong messages?
     - Event for "new descriptors"
     o Better stream IDs
     - EXTENDCIRCUIT <depends on revised circ selection stuff.>
     - ATTACHSTREAM <depends on making streams have 'unattached' state.>
     - Stream status changed: "new" state.
+    - Tests for new controller features
 R . HTTPS proxy for OR CONNECT stuff. (For outgoing SSL connections to
     other ORs.)
   o Changes for forward compatibility
@@ -86,7 +88,7 @@ R . HTTPS proxy for OR CONNECT stuff. (For outgoing SSL connections to
       (Turns out, if package_raw_inbuf fails, it *can't* send an end cell.)
     o Check for any place where we can close an edge connection without
       sending an end; see if we should send an end.
-N   . Feed end reason back into SOCK5 as reasonable.
+N . Feed end reason back into SOCK5 as reasonable.
 R o cache .foo.exit names better, or differently, or not.
 N - make !advertised_server_mode() ORs fetch dirs less often.
 N - Clean up NT service code even more.  Document it. Enable it by default.
@@ -128,7 +130,9 @@ R  o client software not upload descriptor until:
        * no need to do this yet. few people define their ORPort.
 
  Arguable
-N - Reverse DNS: specify and implement.
+N . Reverse DNS
+    o specify
+    - implement
 r - make min uptime a function of the available choices (say, choose 60th
     percentile, not 1 day.)
 r - kill dns workers more slowly

+ 82 - 0
src/or/connection_edge.c

@@ -534,6 +534,77 @@ void client_dns_set_addressmap(const char *address, uint32_t val, const char *ex
                       time(NULL) + MAX_DNS_ENTRY_AGE);
 }
 
+/* Currently, we hand out 127.192.0.1 through 127.254.254.254.
+ * These addresses should map to localhost, so even if the
+ * application accidentally tried to connect to them directly (not
+ * via Tor), it wouldn't get too far astray.
+ *
+ * Eventually, we should probably make this configurable.
+ */
+#define MIN_UNUSED_IPV4 0x7fc00001u
+#define MAX_UNUSED_IPV4 0x7ffefefeu
+
+/**
+ * Return true iff <b>addr</b> is likely to have been returned by
+ * client_dns_get_unmapped_address.
+ **/
+static int
+address_is_in_unmapped_range(const char *addr)
+{
+  struct in_addr in;
+  tor_assert(addr);
+  if (!strcasecmpend(addr, ".virtual")) {
+    return 1;
+  } else if (tor_inet_aton(addr, &in)) {
+    uint32_t a = ntohl(in.s_addr);
+    if (a >= MIN_UNUSED_IPV4 && a <= MAX_UNUSED_IPV4)
+      return 1;
+  }
+  return 0;
+}
+
+/** Return a newly allocated string holding an address of <b>type</b>
+ * (one of RESOLVED_TYPE_{IPV4|HOSTNAME}) that has not yet been mapped,
+ * and that is very unlikely to be the address of any real host.
+ */
+char *
+client_dns_get_unmapped_address(int type)
+{
+  char buf[64];
+  static uint32_t next_ipv4 = MIN_UNUSED_IPV4;
+  struct in_addr in;
+
+  if (type == RESOLVED_TYPE_HOSTNAME) {
+    char rand[16];
+    do {
+      crypto_rand(rand, sizeof(rand));
+      base32_encode(buf,sizeof(buf),rand,sizeof(rand));
+      strlcat(buf, ".virtual", sizeof(buf));
+    } while (strmap_get(addressmap, buf));
+    return tor_strdup(buf);
+  } else if (type == RESOLVED_TYPE_IPV4) {
+    while (1) {
+      /* Don't hand out any .0 or .255 address. */
+      while ((next_ipv4 & 0xff) == 0 ||
+             (next_ipv4 & 0xff) == 0xff)
+        ++next_ipv4;
+      in.s_addr = htonl(next_ipv4);
+      tor_inet_ntoa(&in, buf, sizeof(buf));
+      if (!strmap_get(addressmap, buf))
+        break;
+
+      ++next_ipv4;
+      if (next_ipv4 > MAX_UNUSED_IPV4)
+        next_ipv4 = MIN_UNUSED_IPV4;
+    }
+    return tor_strdup(buf);
+  } else {
+    log_fn(LOG_WARN, "Called with unsupported address type (%d)",
+           type);
+    return NULL;
+  }
+}
+
 /** Return 1 if <b>address</b> has funny characters in it like
  * colons. Return 0 if it's fine.
  */
@@ -593,6 +664,17 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
   /* For address map controls, remap the address */
   addressmap_rewrite(socks->address, sizeof(socks->address));
 
+  if (address_is_in_unmapped_range(socks->address)) {
+    /* This address was probably handed out by client_dns_get_unmapped_address,
+     * but the mapping was discarded for some reason.  We *don't* want to send
+     * the address through tor; that's likely to fail, and may leak
+     * information.
+     */
+    log_fn(LOG_WARN,"Missing mapping for virtual address '%s'. Refusing.",
+           socks->address);
+    return -1;
+  }
+
   /* Parse the address provided by SOCKS.  Modify it in-place if it
    * specifies a hidden-service (.onion) or particular exit node (.exit).
    */

+ 12 - 0
src/or/control.c

@@ -471,6 +471,18 @@ handle_control_mapaddress(connection_t *conn, uint16_t len, const char *body)
         log_fn(LOG_WARN,"Skipping invalid argument '%s' in MapAddress msg",from);
       } else if (!is_plausible_address(to)) {
         log_fn(LOG_WARN,"Skipping invalid argument '%s' in AddressMap msg",to);
+      } else if (!strcmp(from, ".") || !strcmp(from, "0.0.0.0")) {
+        char *addr = client_dns_get_unmapped_address(
+               strcmp(from,".") ? RESOLVED_TYPE_HOSTNAME : RESOLVED_TYPE_IPV4);
+        if (!addr) {
+          log_fn(LOG_WARN,
+                 "Unable to allocate address for '%s' in AdressMap msg", line);
+        } else {
+          char *ans = tor_malloc(strlen(addr)+strlen(to)+2);
+          tor_snprintf(ans, "%s %s", addr, to);
+          addressmap_register(addr, tor_strdup(to), 0);
+          smartlist_add(reply, ans);
+        }
       } else {
         addressmap_register(from, tor_strdup(to), 0);
         smartlist_add(reply, tor_strdup(line));

+ 2 - 0
src/or/or.h

@@ -427,6 +427,7 @@ typedef enum {
 #define END_STREAM_REASON_CONNRESET 12
 #define END_STREAM_REASON_TORPROTOCOL 13
 
+#define RESOLVED_TYPE_HOSTNAME 0
 #define RESOLVED_TYPE_IPV4 4
 #define RESOLVED_TYPE_IPV6 6
 #define RESOLVED_TYPE_ERROR_TRANSIENT 0xF0
@@ -1318,6 +1319,7 @@ int addressmap_already_mapped(const char *address);
 void addressmap_register(const char *address, char *new_address, time_t expires);
 int client_dns_incr_failures(const char *address);
 void client_dns_set_addressmap(const char *address, uint32_t val, const char *exitname);
+char *client_dns_get_unmapped_address(int type);
 
 void parse_socks_policy(void);
 void free_socks_policy(void);