41fa067
Index: validator/validator.c
41fa067
===================================================================
41fa067
--- validator/validator.c	(revision 1669)
41fa067
+++ validator/validator.c	(revision 1670)
41fa067
@@ -479,6 +479,36 @@
41fa067
 }
41fa067
 
41fa067
 /**
41fa067
+ * Detect wrong truncated response, by a bad recursor out there.
41fa067
+ * The positive response has a mangled authority section.
41fa067
+ * Remove that authority section.
41fa067
+ * @param rep: reply
41fa067
+ * @return true if a wrongly truncated response.
41fa067
+ */
41fa067
+static int
41fa067
+detect_wrongly_truncated(struct reply_info* rep)
41fa067
+{
41fa067
+	size_t i;
41fa067
+	/* no additional, only NS in authority, and it is bogus */
41fa067
+	if(rep->ar_numrrsets != 0 || rep->ns_numrrsets != 1 ||
41fa067
+		rep->an_numrrsets == 0)
41fa067
+		return 0;
41fa067
+	if(ntohs(rep->rrsets[ rep->an_numrrsets ]->rk.type) != LDNS_RR_TYPE_NS)
41fa067
+		return 0;
41fa067
+	if(((struct packed_rrset_data*)rep->rrsets[ rep->an_numrrsets ]
41fa067
+		->entry.data)->security != sec_status_bogus)
41fa067
+		return 0;
41fa067
+	/* answer section is present and secure */
41fa067
+	for(i=0; i<rep->an_numrrsets; i++) {
41fa067
+		if(((struct packed_rrset_data*)rep->rrsets[ i ]
41fa067
+			->entry.data)->security != sec_status_secure)
41fa067
+			return 0;
41fa067
+	}
41fa067
+	return 1;
41fa067
+}
41fa067
+
41fa067
+
41fa067
+/**
41fa067
  * Given a "positive" response -- a response that contains an answer to the
41fa067
  * question, and no CNAME chain, validate this response. 
41fa067
  *
41fa067
@@ -1449,17 +1479,31 @@
41fa067
 		vq->chase_reply->security = sec_status_bogus;
41fa067
 		return 1;
41fa067
 	}
41fa067
+	subtype = val_classify_response(qstate->query_flags, &qstate->qinfo,
41fa067
+		&vq->qchase, vq->orig_msg->rep, vq->rrset_skip);
41fa067
 
41fa067
 	/* check signatures in the message; 
41fa067
 	 * answer and authority must be valid, additional is only checked. */
41fa067
 	if(!validate_msg_signatures(qstate->env, ve, &vq->qchase, 
41fa067
 		vq->chase_reply, vq->key_entry)) {
41fa067
-		verbose(VERB_DETAIL, "Validate: message contains bad rrsets");
41fa067
-		return 1;
41fa067
+		/* workaround bad recursor out there that truncates (even
41fa067
+		 * with EDNS4k) to 512 by removing RRSIG from auth section
41fa067
+		 * for positive replies*/
41fa067
+		if(subtype == VAL_CLASS_POSITIVE &&
41fa067
+			detect_wrongly_truncated(vq->orig_msg->rep)) {
41fa067
+			/* truncate the message some more */
41fa067
+			vq->orig_msg->rep->ns_numrrsets = 0;
41fa067
+			vq->orig_msg->rep->rrset_count--;
41fa067
+			vq->chase_reply->ns_numrrsets = 0;
41fa067
+			vq->chase_reply->rrset_count--;
41fa067
+		}
41fa067
+		else {
41fa067
+			verbose(VERB_DETAIL, "Validate: message contains "
41fa067
+				"bad rrsets");
41fa067
+			return 1;
41fa067
+		}
41fa067
 	}
41fa067
 
41fa067
-	subtype = val_classify_response(qstate->query_flags, &qstate->qinfo,
41fa067
-		&vq->qchase, vq->orig_msg->rep, vq->rrset_skip);
41fa067
 	switch(subtype) {
41fa067
 		case VAL_CLASS_POSITIVE:
41fa067
 			verbose(VERB_ALGO, "Validating a positive response");