diff --git a/ChangeLog b/ChangeLog
index 823dba958b..01584aa2c6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,8 @@ Changes in version 0.2.1.7-alpha - 2008-10-xx
- Now NodeFamily and MyFamily config options allow spaces in
identity fingerprints, so it's easier to paste them in.
Suggested by Lucky Green.
+ - Preserve case in replies to DNSPort requests in order to support
+ the 0x20 hack for resisting DNS poisoning attacks.
o Hidden service performance improvements:
- When the client launches an introduction circuit, retry with a
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c
index afd0f28364..46017f89cb 100644
--- a/src/or/dnsserv.c
+++ b/src/or/dnsserv.c
@@ -207,6 +207,38 @@ dnsserv_reject_request(edge_connection_t *conn)
}
}
+/** Look up the original name that corresponds to 'addr' in req. We use this
+ * to preserve case in order to facilitate people using 0x20-hacks to avoid
+ * DNS poisoning. */
+static const char *
+evdns_get_orig_address(const struct evdns_server_request *req,
+ int rtype, const char *addr)
+{
+ int i, type;
+
+ switch (rtype) {
+ case RESOLVED_TYPE_IPV4:
+ type = EVDNS_TYPE_A;
+ break;
+ case RESOLVED_TYPE_HOSTNAME:
+ type = EVDNS_TYPE_PTR;
+ break;
+ case RESOLVED_TYPE_IPV6:
+ type = EVDNS_TYPE_AAAA;
+ break;
+ default:
+ tor_fragile_assert();
+ return addr;
+ }
+
+ for (i = 0; i < req->nquestions; ++i) {
+ const struct evdns_server_question *q = req->questions[i];
+ if (q->type == type && !strcasecmp(q->name, addr))
+ return q->name;
+ }
+ return addr;
+}
+
/** Tell the dns request waiting for an answer on conn that we have an
* answer of type answer_type (RESOLVE_TYPE_IPV4/IPV6/ERR), of length
* answer_len, in answer, with TTL ttl. Doesn't do
@@ -219,9 +251,11 @@ dnsserv_resolved(edge_connection_t *conn,
int ttl)
{
struct evdns_server_request *req = conn->dns_server_request;
+ const char *name;
int err = DNS_ERR_NONE;
if (!req)
return;
+ name = evdns_get_orig_address(req, answer_type, conn->socks_request->address);
/* XXXX021 Re-do; this is dumb. */
if (ttl < 60)
@@ -236,13 +270,13 @@ dnsserv_resolved(edge_connection_t *conn,
} else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4 &&
conn->socks_request->command == SOCKS_COMMAND_RESOLVE) {
evdns_server_request_add_a_reply(req,
- conn->socks_request->address,
+ name,
1, (char*)answer, ttl);
} else if (answer_type == RESOLVED_TYPE_HOSTNAME &&
conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR) {
char *ans = tor_strndup(answer, answer_len);
evdns_server_request_add_ptr_reply(req, NULL,
- conn->socks_request->address,
+ name,
(char*)answer, ttl);
tor_free(ans);
} else if (answer_type == RESOLVED_TYPE_ERROR) {