summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-03-02 19:26:46 +0000
committerNick Mathewson <nickm@torproject.org>2005-03-02 19:26:46 +0000
commit65230fd39f0c333ce8616f5a578f4941ea9f0b94 (patch)
treee6d33d51eac0f07d35e7fbebcc021f350c724646 /src
parent06a574b0c95b332b01aa8beb30bfb8237c1f7747 (diff)
downloadtor-65230fd39f0c333ce8616f5a578f4941ea9f0b94.tar.gz
tor-65230fd39f0c333ce8616f5a578f4941ea9f0b94.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/or/connection_edge.c82
-rw-r--r--src/or/control.c12
-rw-r--r--src/or/or.h2
3 files changed, 96 insertions, 0 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index f0a9fbde26..52619e392f 100644
--- a/src/or/connection_edge.c
+++ b/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).
*/
diff --git a/src/or/control.c b/src/or/control.c
index 4ce437283b..ff54f38959 100644
--- a/src/or/control.c
+++ b/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));
diff --git a/src/or/or.h b/src/or/or.h
index 90a3245321..fa76f55d5c 100644
--- a/src/or/or.h
+++ b/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);