|
@@ -664,6 +664,7 @@ addressmap_rewrite(char *address, size_t maxlen)
|
|
|
{
|
|
|
addressmap_entry_t *ent;
|
|
|
int rewrites;
|
|
|
+ char *cp;
|
|
|
|
|
|
for (rewrites = 0; rewrites < 16; rewrites++) {
|
|
|
ent = strmap_get(addressmap, address);
|
|
@@ -671,8 +672,10 @@ addressmap_rewrite(char *address, size_t maxlen)
|
|
|
if (!ent || !ent->new_address)
|
|
|
return;
|
|
|
|
|
|
+ cp = tor_strdup(escaped_safe_str(ent->new_address));
|
|
|
log_info(LD_APP, "Addressmap: rewriting '%s' to '%s'",
|
|
|
- safe_str(address), safe_str(ent->new_address));
|
|
|
+ escaped_safe_str(address), cp);
|
|
|
+ tor_free(cp);
|
|
|
strlcpy(address, ent->new_address, maxlen);
|
|
|
}
|
|
|
log_warn(LD_CONFIG,
|
|
@@ -681,6 +684,28 @@ addressmap_rewrite(char *address, size_t maxlen)
|
|
|
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+static int
|
|
|
+addressmap_rewrite_reverse(char *address, size_t maxlen)
|
|
|
+{
|
|
|
+ size_t len = maxlen + 16;
|
|
|
+ char *s = tor_malloc(len), *cp;
|
|
|
+ addressmap_entry_t *ent;
|
|
|
+ int r = 0;
|
|
|
+ tor_snprintf(s, len, "REVERSE[%s]", address);
|
|
|
+ ent = strmap_get(addressmap, s);
|
|
|
+ if (ent) {
|
|
|
+ cp = tor_strdup(escaped_safe_str(ent->new_address));
|
|
|
+ log_info(LD_APP, "Rewrote reverse lookup '%s' -> '%s'",
|
|
|
+ escaped_safe_str(s), cp);
|
|
|
+ tor_free(cp);
|
|
|
+ strlcpy(address, ent->new_address, maxlen);
|
|
|
+ r = 1;
|
|
|
+ }
|
|
|
+ tor_free(s);
|
|
|
+ return r;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
int
|
|
|
addressmap_have_mapping(const char *address)
|
|
@@ -775,7 +800,7 @@ client_dns_clear_failures(const char *address)
|
|
|
ent->num_resolve_failures = 0;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
* We can now use this in subsequent streams via addressmap_rewrite()
|
|
|
* so we can more correctly choose an exit that will allow <b>address</b>.
|
|
|
*
|
|
@@ -785,30 +810,24 @@ client_dns_clear_failures(const char *address)
|
|
|
* If <b>ttl</b> is nonnegative, the mapping will be valid for
|
|
|
* <b>ttl</b>seconds; otherwise, we use the default.
|
|
|
*/
|
|
|
-void
|
|
|
-client_dns_set_addressmap(const char *address, uint32_t val,
|
|
|
- const char *exitname,
|
|
|
- int ttl)
|
|
|
+static void
|
|
|
+client_dns_set_addressmap_impl(const char *address, const char *name,
|
|
|
+ const char *exitname,
|
|
|
+ int ttl)
|
|
|
{
|
|
|
- struct in_addr in;
|
|
|
|
|
|
char extendedaddress[MAX_SOCKS_ADDR_LEN+MAX_VERBOSE_NICKNAME_LEN+10];
|
|
|
|
|
|
char extendedval[INET_NTOA_BUF_LEN+MAX_VERBOSE_NICKNAME_LEN+10];
|
|
|
- char valbuf[INET_NTOA_BUF_LEN];
|
|
|
|
|
|
tor_assert(address);
|
|
|
- tor_assert(val);
|
|
|
+ tor_assert(name);
|
|
|
|
|
|
if (ttl<0)
|
|
|
ttl = DEFAULT_DNS_TTL;
|
|
|
else
|
|
|
ttl = dns_clip_ttl(ttl);
|
|
|
|
|
|
- if (tor_inet_aton(address, &in))
|
|
|
- return;
|
|
|
- in.s_addr = htonl(val);
|
|
|
- tor_inet_ntoa(&in,valbuf,sizeof(valbuf));
|
|
|
if (exitname) {
|
|
|
|
|
|
* google.com.digest[=~]nickname.exit; we need a syntax for this that
|
|
@@ -816,17 +835,58 @@ client_dns_set_addressmap(const char *address, uint32_t val,
|
|
|
tor_snprintf(extendedaddress, sizeof(extendedaddress),
|
|
|
"%s.%s.exit", address, exitname);
|
|
|
tor_snprintf(extendedval, sizeof(extendedval),
|
|
|
- "%s.%s.exit", valbuf, exitname);
|
|
|
+ "%s.%s.exit", name, exitname);
|
|
|
} else {
|
|
|
tor_snprintf(extendedaddress, sizeof(extendedaddress),
|
|
|
"%s", address);
|
|
|
tor_snprintf(extendedval, sizeof(extendedval),
|
|
|
- "%s", valbuf);
|
|
|
+ "%s", name);
|
|
|
}
|
|
|
addressmap_register(extendedaddress, tor_strdup(extendedval),
|
|
|
time(NULL) + ttl);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * We can now use this in subsequent streams via addressmap_rewrite()
|
|
|
+ * so we can more correctly choose an exit that will allow <b>address</b>.
|
|
|
+ *
|
|
|
+ * If <b>exitname</b> is defined, then append the addresses with
|
|
|
+ * ".exitname.exit" before registering the mapping.
|
|
|
+ *
|
|
|
+ * If <b>ttl</b> is nonnegative, the mapping will be valid for
|
|
|
+ * <b>ttl</b>seconds; otherwise, we use the default.
|
|
|
+ */
|
|
|
+void
|
|
|
+client_dns_set_addressmap(const char *address, uint32_t val,
|
|
|
+ const char *exitname,
|
|
|
+ int ttl)
|
|
|
+{
|
|
|
+ struct in_addr in;
|
|
|
+ char valbuf[INET_NTOA_BUF_LEN];
|
|
|
+
|
|
|
+ tor_assert(address);
|
|
|
+
|
|
|
+ if (tor_inet_aton(address, &in))
|
|
|
+ return;
|
|
|
+ in.s_addr = htonl(val);
|
|
|
+ tor_inet_ntoa(&in,valbuf,sizeof(valbuf));
|
|
|
+
|
|
|
+ client_dns_set_addressmap_impl(address, valbuf, exitname, ttl);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void
|
|
|
+client_dns_set_reverse_addressmap(const char *address, const char *v,
|
|
|
+ const char *exitname,
|
|
|
+ int ttl)
|
|
|
+{
|
|
|
+ size_t len = strlen(address) + 16;
|
|
|
+ char *s = tor_malloc(len);
|
|
|
+ tor_snprintf(s, len, "REVERSE[%s]", address);
|
|
|
+ client_dns_set_addressmap_impl(s, v, exitname, ttl);
|
|
|
+ tor_free(s);
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
* These addresses should map to localhost, so even if the
|
|
|
* application accidentally tried to connect to them directly (not
|
|
@@ -1103,8 +1163,19 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
|
|
|
safe_str(socks->address),
|
|
|
socks->port);
|
|
|
|
|
|
-
|
|
|
- addressmap_rewrite(socks->address, sizeof(socks->address));
|
|
|
+ if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) {
|
|
|
+ if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address))) {
|
|
|
+ connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_HOSTNAME,
|
|
|
+ strlen(socks->address),
|
|
|
+ socks->address, -1);
|
|
|
+ connection_mark_unattached_ap(conn,
|
|
|
+ END_STREAM_REASON_ALREADY_SOCKS_REPLIED);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+ addressmap_rewrite(socks->address, sizeof(socks->address));
|
|
|
+ }
|
|
|
|
|
|
if (address_is_in_virtual_range(socks->address)) {
|
|
|
|
|
@@ -1826,11 +1897,19 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
|
|
|
char buf[384];
|
|
|
size_t replylen;
|
|
|
|
|
|
- if (answer_type == RESOLVED_TYPE_IPV4) {
|
|
|
- uint32_t a = ntohl(get_uint32(answer));
|
|
|
- if (a)
|
|
|
- client_dns_set_addressmap(conn->socks_request->address, a,
|
|
|
- conn->chosen_exit_name, ttl);
|
|
|
+ if (ttl >= 0) {
|
|
|
+ if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
|
|
|
+ uint32_t a = ntohl(get_uint32(answer));
|
|
|
+ if (a)
|
|
|
+ client_dns_set_addressmap(conn->socks_request->address, a,
|
|
|
+ conn->chosen_exit_name, ttl);
|
|
|
+ } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
|
|
|
+ char *cp = tor_strndup(answer, answer_len);
|
|
|
+ client_dns_set_reverse_addressmap(conn->socks_request->address,
|
|
|
+ cp,
|
|
|
+ conn->chosen_exit_name, ttl);
|
|
|
+ tor_free(cp);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (conn->socks_request->socks_version == 4) {
|