Browse Source

Oops; we need to make sure that DNS request names are matched in the _questions_ section of the replies. Rejecting answers whether the _answers_ section did not match made us reject A records waiting at the end of a CNAME record. Bug 823.

svn:r16933
Nick Mathewson 17 years ago
parent
commit
b0c48d8e45
2 changed files with 23 additions and 23 deletions
  1. 3 0
      ChangeLog
  2. 20 23
      src/or/eventdns.c

+ 3 - 0
ChangeLog

@@ -12,6 +12,9 @@ Changes in version 0.2.1.6-alpha - 2008-09-xx
       descriptor from a hidden service directory for which the router
       descriptor has not yet been downloaded. Fixes bug 767. Bugfix
       on 0.2.0.10-alpha.
+    - DNS replies need to have names matching their requests, but these names
+      should be in the questions section, not necessarily in the answers
+      section.  Fixes bug 823.  Bugfix on 0.2.1.5-alpha.
 
   o Minor bugfixes:
     - Fix compile on OpenBSD 4.4-current. Bugfix on 0.2.1.5-alpha.

+ 20 - 23
src/or/eventdns.c

@@ -873,6 +873,7 @@ reply_parse(u8 *packet, int length) {
 	struct reply reply;
 	struct request *req = NULL;
 	unsigned int i;
+	int name_matches = 0;
 
 	GET16(trans_id);
 	GET16(flags);
@@ -913,16 +914,20 @@ reply_parse(u8 *packet, int length) {
 		 */
 		GET_NAME;
 		j += 4;
+		if (!strcasecmp(req->name, tmp_name))
+		    name_matches = 1;
 		if (j >= length) goto err;
 	}
 
+	if (!name_matches)
+		goto err;
+
 	/* now we have the answer section which looks like
 	 * <label:name><u16:type><u16:class><u32:ttl><u16:len><data...>
 	 */
 
 	for (i = 0; i < answers; ++i) {
 		u16 type, class;
-		int name_matches;
 
 		GET_NAME;
 		GET16(type);
@@ -930,8 +935,6 @@ reply_parse(u8 *packet, int length) {
 		GET32(ttl);
 		GET16(datalength);
 
-		name_matches = !strcasecmp(req->name, tmp_name);
-
 		if (type == TYPE_A && class == CLASS_INET) {
 			int addrcount, addrtocopy;
 			if (req->request_type != TYPE_A) {
@@ -945,25 +948,21 @@ reply_parse(u8 *packet, int length) {
 			ttl_r = MIN(ttl_r, ttl);
 			/* we only bother with the first four addresses. */
 			if (j + 4*addrtocopy > length) goto err;
-			if (name_matches) {
-				memcpy(&reply.data.a.addresses[reply.data.a.addrcount],
-					   packet + j, 4*addrtocopy);
-				reply.data.a.addrcount += addrtocopy;
-				reply.have_answer = 1;
-				if (reply.data.a.addrcount == MAX_ADDRS) break;
-			}
+			memcpy(&reply.data.a.addresses[reply.data.a.addrcount],
+				   packet + j, 4*addrtocopy);
+			reply.data.a.addrcount += addrtocopy;
+			reply.have_answer = 1;
+			if (reply.data.a.addrcount == MAX_ADDRS) break;
 			j += 4*addrtocopy;
 		} else if (type == TYPE_PTR && class == CLASS_INET) {
 			if (req->request_type != TYPE_PTR) {
 				j += datalength; continue;
 			}
 			GET_NAME;
-			if (name_matches) {
-				strlcpy(reply.data.ptr.name, tmp_name,
-						sizeof(reply.data.ptr.name));
-				ttl_r = MIN(ttl_r, ttl);
-				reply.have_answer = 1;
-			}
+			strlcpy(reply.data.ptr.name, tmp_name,
+					sizeof(reply.data.ptr.name));
+			ttl_r = MIN(ttl_r, ttl);
+			reply.have_answer = 1;
 			break;
 		} else if (type == TYPE_AAAA && class == CLASS_INET) {
 			int addrcount, addrtocopy;
@@ -978,13 +977,11 @@ reply_parse(u8 *packet, int length) {
 
 			/* we only bother with the first four addresses. */
 			if (j + 16*addrtocopy > length) goto err;
-			if (name_matches) {
-				memcpy(&reply.data.aaaa.addresses[reply.data.aaaa.addrcount],
-					   packet + j, 16*addrtocopy);
-				reply.data.aaaa.addrcount += addrtocopy;
-				reply.have_answer = 1;
-				if (reply.data.aaaa.addrcount == MAX_ADDRS) break;
-			}
+			memcpy(&reply.data.aaaa.addresses[reply.data.aaaa.addrcount],
+				   packet + j, 16*addrtocopy);
+			reply.data.aaaa.addrcount += addrtocopy;
+			reply.have_answer = 1;
+			if (reply.data.aaaa.addrcount == MAX_ADDRS) break;
 			j += 16*addrtocopy;
 		} else {
 			/* skip over any other type of resource */