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) {