[or-cvs] r17171: {tor} Implement the 0x20-hack to make DNS poisoning harder against (tor/trunk/src/or)
nickm at seul.org
nickm at seul.org
Wed Oct 29 19:20:02 UTC 2008
Author: nickm
Date: 2008-10-29 15:20:02 -0400 (Wed, 29 Oct 2008)
New Revision: 17171
Modified:
tor/trunk/src/or/config.c
tor/trunk/src/or/dns.c
tor/trunk/src/or/eventdns.c
tor/trunk/src/or/eventdns.h
tor/trunk/src/or/or.h
Log:
Implement the 0x20-hack to make DNS poisoning harder against us, especially when resolving large names. Add a cfg option to disable it, since apparently 3/10 of a percent of servers get it wrong.
Modified: tor/trunk/src/or/config.c
===================================================================
--- tor/trunk/src/or/config.c 2008-10-29 15:31:26 UTC (rev 17170)
+++ tor/trunk/src/or/config.c 2008-10-29 19:20:02 UTC (rev 17171)
@@ -292,6 +292,7 @@
V(ServerDNSAllowBrokenResolvConf, BOOL, "0"),
V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"),
V(ServerDNSDetectHijacking, BOOL, "1"),
+ V(ServerDNSRandomizeCase, BOOL, "1"),
V(ServerDNSResolvConfFile, STRING, NULL),
V(ServerDNSSearchDomains, BOOL, "0"),
V(ServerDNSTestAddresses, CSV,
Modified: tor/trunk/src/or/dns.c
===================================================================
--- tor/trunk/src/or/dns.c 2008-10-29 15:31:26 UTC (rev 17170)
+++ tor/trunk/src/or/dns.c 2008-10-29 19:20:02 UTC (rev 17171)
@@ -184,13 +184,10 @@
log(severity, LD_EXIT, "eventdns: %s", msg);
}
-/** Helper: generate a good random transaction ID. */
-static uint16_t
-dns_get_transaction_id(void)
+static void
+randfn(char *b, size_t n)
{
- uint16_t result;
- crypto_rand((void*)&result, sizeof(result));
- return result;
+ crypto_rand(b,n);
}
/** Initialize the DNS subsystem; called by the OR process. */
@@ -198,9 +195,15 @@
dns_init(void)
{
init_cache_map();
- evdns_set_transaction_id_fn(dns_get_transaction_id);
- if (server_mode(get_options()))
- return configure_nameservers(1);
+ evdns_set_random_bytes_fn(randfn);
+ if (get_options()->ServerDNSRandomizeCase)
+ evdns_set_option("randomize-case", "1", DNS_OPTIONS_ALL);
+ else
+ evdns_set_option("randomize-case", "0", DNS_OPTIONS_ALL);
+ if (server_mode(get_options())) {
+ int r = configure_nameservers(1);
+ return r;
+ }
return 0;
}
Modified: tor/trunk/src/or/eventdns.c
===================================================================
--- tor/trunk/src/or/eventdns.c 2008-10-29 15:31:26 UTC (rev 17170)
+++ tor/trunk/src/or/eventdns.c 2008-10-29 19:20:02 UTC (rev 17171)
@@ -156,7 +156,6 @@
struct request {
u8 *request; /* the dns packet data */
- char *name; /* the name we requested. */
unsigned int request_len;
int reissue_count;
int tx_count; /* the number of times that this packet has been sent */
@@ -308,6 +307,9 @@
/* number of timeouts in a row before we consider this server to be down */
static int global_max_nameserver_timeout = 3;
+/* DOCDOC */
+static int global_randomize_case = 1;
+
/* These are the timeout values for nameservers. If we find a nameserver is down */
/* we try to probe it at intervals as given below. Values are in seconds. */
static const struct timeval global_nameserver_timeouts[] = {{10, 0}, {60, 0}, {300, 0}, {900, 0}, {3600, 0}};
@@ -378,6 +380,9 @@
#define ISSPACE(c) isspace((int)(unsigned char)(c))
#define ISDIGIT(c) isdigit((int)(unsigned char)(c))
+#define ISALPHA(c) isalpha((int)(unsigned char)(c))
+#define TOLOWER(c) (char)tolower((int)(unsigned char)(c))
+#define TOUPPER(c) (char)toupper((int)(unsigned char)(c))
#ifndef NDEBUG
static const char *
@@ -863,9 +868,10 @@
static int
reply_parse(u8 *packet, int length) {
int j = 0; /* index into packet */
+ int k;
u16 _t; /* used by the macros */
u32 _t32; /* used by the macros */
- char tmp_name[256]; /* used by the macros */
+ char tmp_name[256], cmp_name[256]; /* used by the macros */
u16 trans_id, questions, answers, authority, additional, datalength;
u16 flags = 0;
@@ -898,12 +904,28 @@
}
/* if (!answers) return; */ /* must have an answer of some form */
- /* This macro copies a name in the DNS reply into tmp_name */
-#define GET_NAME \
- do { tmp_name[0] = '\0'; \
- if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) \
- goto err; \
+ /* This macro skips a name in the DNS reply. */
+#define GET_NAME \
+ do { tmp_name[0] = '\0'; \
+ if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0)\
+ goto err; \
} while(0)
+#define TEST_NAME \
+ do { tmp_name[0] = '\0'; \
+ cmp_name[0] = '\0'; \
+ k = j; \
+ if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0)\
+ goto err; \
+ if (name_parse(req->request, req->request_len, &k, cmp_name, sizeof(cmp_name))<0) \
+ goto err; \
+ if (global_randomize_case) { \
+ if (strcmp(tmp_name, cmp_name) == 0) \
+ name_matches = 1; /* we ignore mismatching names */ \
+ } else { \
+ if (strcasecmp(tmp_name, cmp_name) == 0) \
+ name_matches = 1; \
+ } \
+ } while(0)
reply.type = req->request_type;
@@ -912,10 +934,8 @@
/* the question looks like
* <label:name><u16:type><u16:class>
*/
- GET_NAME;
+ TEST_NAME;
j += 4;
- if (!strcasecmp(req->name, tmp_name))
- name_matches = 1;
if (j >= length) goto err;
}
@@ -1127,6 +1147,32 @@
static uint16_t (*trans_id_function)(void) = default_transaction_id_fn;
+static void
+default_random_bytes_fn(char *buf, size_t n)
+{
+ unsigned i;
+ for (i = 0; i < n-1; i += 2) {
+ u16 tid = trans_id_function();
+ buf[i] = (tid >> 8) & 0xff;
+ buf[i+1] = tid & 0xff;
+ }
+ if (i < n) {
+ u16 tid = trans_id_function();
+ buf[i] = tid & 0xff;
+ }
+}
+
+static void (*rand_bytes_function)(char *buf, size_t n) =
+ default_random_bytes_fn;
+
+static u16
+trans_id_from_random_bytes_fn(void)
+{
+ u16 tid;
+ rand_bytes_function((char*) &tid, sizeof(tid));
+ return tid;
+}
+
void
evdns_set_transaction_id_fn(uint16_t (*fn)(void))
{
@@ -1134,8 +1180,16 @@
trans_id_function = fn;
else
trans_id_function = default_transaction_id_fn;
+ rand_bytes_function = default_random_bytes_fn;
}
+void
+evdns_set_random_bytes_fn(void (*fn)(char *, size_t))
+{
+ rand_bytes_function = fn;
+ trans_id_function = trans_id_from_random_bytes_fn;
+}
+
/* Try to choose a strong transaction id which isn't already in flight */
static u16
transaction_id_pick(void) {
@@ -2366,20 +2420,32 @@
const u16 trans_id = issuing_now ? transaction_id_pick() : 0xffff;
/* the request data is alloced in a single block with the header */
struct request *const req =
- (struct request *) malloc(sizeof(struct request) + request_max_len
- + name_len + 1);
+ (struct request *) malloc(sizeof(struct request) + request_max_len);
+ char namebuf[256];
int rlen;
(void) flags;
if (!req) return NULL;
memset(req, 0, sizeof(struct request));
+ if (global_randomize_case) {
+ unsigned i;
+ char randbits[32];
+ strlcpy(namebuf, name, sizeof(namebuf));
+ rand_bytes_function(randbits, (name_len+7)/8);
+ for (i = 0; i < name_len; ++i) {
+ if (ISALPHA(namebuf[i])) {
+ if ((randbits[i >> 3] & (1<<(i%7))))
+ namebuf[i] = TOLOWER(namebuf[i]);
+ else
+ namebuf[i] = TOUPPER(namebuf[i]);
+ }
+ }
+ name = namebuf;
+ }
+
/* request data lives just after the header */
req->request = ((u8 *) req) + sizeof(struct request);
- /* A copy of the name sits after the request data */
- req->name = ((char *)req) + sizeof(struct request) + request_max_len;
- strlcpy(req->name, name, name_len + 1);
-
/* denotes that the request data shouldn't be free()ed */
req->request_appended = 1;
rlen = evdns_request_data_build(name, name_len, trans_id,
@@ -2819,6 +2885,11 @@
if (!(flags & DNS_OPTION_MISC)) return 0;
log(EVDNS_LOG_DEBUG, "Setting retries to %d", retries);
global_max_retransmits = retries;
+ } else if (!strncmp(option, "randomize-case:", 15)) {
+ int randcase = strtoint(val);
+ if (!(flags & DNS_OPTION_MISC)) return 0;
+ log(EVDNS_LOG_DEBUG, "Setting randomize_case to %d", randcase);
+ global_randomize_case = randcase;
}
return 0;
}
@@ -3251,7 +3322,7 @@
}
}
- r = evdns_request_respond(req, 0);
+ r = evdns_server_request_respond(req, 0);
if (r<0)
printf("eeek, couldn't send reply.\n");
}
Modified: tor/trunk/src/or/eventdns.h
===================================================================
--- tor/trunk/src/or/eventdns.h 2008-10-29 15:31:26 UTC (rev 17170)
+++ tor/trunk/src/or/eventdns.h 2008-10-29 19:20:02 UTC (rev 17171)
@@ -283,6 +283,7 @@
void evdns_set_log_fn(evdns_debug_log_fn_type fn);
void evdns_set_transaction_id_fn(uint16_t (*fn)(void));
+void evdns_set_random_bytes_fn(void (*fn)(char *, size_t));
#define DNS_NO_SEARCH 1
Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h 2008-10-29 15:31:26 UTC (rev 17170)
+++ tor/trunk/src/or/or.h 2008-10-29 19:20:02 UTC (rev 17171)
@@ -2397,6 +2397,8 @@
* the local domains. */
int ServerDNSDetectHijacking; /**< Boolean: If true, check for DNS failure
* hijacking. */
+ int ServerDNSRandomizeCase; /**< Boolean: Use the 0x20-hack to prevent
+ * DNS poisoning attacks. */
char *ServerDNSResolvConfFile; /**< If provided, we configure our internal
* resolver from the file here rather than from
* /etc/resolv.conf (Unix) or the registry (Windows). */
More information about the tor-commits
mailing list