Browse code

core: resolve - early safety checks to deal faster with broken dns responses

(cherry picked from commit 20752cf945d4ba0660d321d73efff5c93f6d20a8)
(cherry picked from commit 95e0976ce7e1976664f5ae107936e94e6fd618f0)
(cherry picked from commit 982910c597485b6bdce1f4bf99cd19b7bf8db47e)

Daniel-Constantin Mierla authored on 30/12/2017 15:57:42
Showing 1 changed files
... ...
@@ -679,13 +679,16 @@ void free_rdata_list(struct rdata* head)
679 679
 int match_search_list(const struct __res_state* res, char* name) {
680 680
 	int i;
681 681
 	for (i=0; (i<MAXDNSRCH) && (res->dnsrch[i]); i++) {
682
-		if (strcasecmp(name, res->dnsrch[i])==0) 
682
+		if (strcasecmp(name, res->dnsrch[i])==0)
683 683
 			return 1;
684 684
 	}
685 685
 	return 0;
686 686
 }
687 687
 #endif
688 688
 
689
+#define SR_DNS_MAX_QNO 10
690
+#define SR_DNS_MAX_ANO 100
691
+
689 692
 /** gets the DNS records for name:type
690 693
  * returns a dyn. alloc'ed struct rdata linked list with the parsed responses
691 694
  * or 0 on error
... ...
@@ -714,7 +717,7 @@ struct rdata* get_record(char* name, int type, int flags)
714 717
 	int name_len;
715 718
 	struct rdata* fullname_rd;
716 719
 	char c;
717
-	
720
+
718 721
 	name_len=strlen(name);
719 722
 
720 723
 	for (i = 0; i < name_len; i++) {
... ...
@@ -744,12 +747,21 @@ struct rdata* get_record(char* name, int type, int flags)
744 747
 	else if (unlikely(size > sizeof(buff))) size=sizeof(buff);
745 748
 	head=rd=0;
746 749
 	last=crt=&head;
747
-	
750
+
748 751
 	p=buff.buff+DNS_HDR_SIZE;
749 752
 	end=buff.buff+size;
750 753
 	if (unlikely(p>=end)) goto error_boundary;
751 754
 	qno=ntohs((unsigned short)buff.hdr.qdcount);
752 755
 
756
+	if(qno!=1) {
757
+		/* usually the query is with a single domain name */
758
+		LM_INFO("dns questions number is: %u\n", (uint32_t)qno);
759
+		if(qno>SR_DNS_MAX_QNO) {
760
+			/* early safe check against broken results */
761
+			LM_ERR("dns questions number is too high: %u\n", (uint32_t)qno);
762
+			goto error;
763
+		}
764
+	}
753 765
 	for (r=0; r<qno; r++){
754 766
 		/* skip the name of the question */
755 767
 		if (unlikely((p=dns_skipname(p, end))==0)) {
... ...
@@ -765,8 +777,13 @@ struct rdata* get_record(char* name, int type, int flags)
765 777
 			LM_ERR("p>=end\n");
766 778
 			goto error;
767 779
 		}
768
-	};
780
+	}
769 781
 	answers_no=ntohs((unsigned short)buff.hdr.ancount);
782
+	if(answers_no>SR_DNS_MAX_ANO) {
783
+		/* early safety check on answers number */
784
+		LM_ERR("dns answers number is too high: %u\n", (uint32_t)answers_no);
785
+		goto error;
786
+	}
770 787
 again:
771 788
 	for (r=0; (r<answers_no) && (p<end); r++){
772 789
 #if 0
... ...
@@ -815,7 +832,7 @@ again:
815 832
 			continue;
816 833
 		}
817 834
 		/* expand the "type" record  (rdata)*/
818
-		
835
+
819 836
 		rd=(struct rdata*) local_malloc(sizeof(struct rdata)+rec_name_len+
820 837
 										1-1);
821 838
 		if (rd==0){
... ...
@@ -857,14 +874,14 @@ again:
857 874
 				srv_rd= dns_srv_parser(buff.buff, end, rd_end, p);
858 875
 				rd->rdata=(void*)srv_rd;
859 876
 				if (unlikely(srv_rd==0)) goto error_parse;
860
-				
877
+
861 878
 				/* insert sorted into the list */
862 879
 				for (crt=&head; *crt; crt= &((*crt)->next)){
863 880
 					if ((*crt)->type!=T_SRV)
864 881
 						continue;
865 882
 					crt_srv=(struct srv_rdata*)(*crt)->rdata;
866 883
 					if ((srv_rd->priority <  crt_srv->priority) ||
867
-					   ( (srv_rd->priority == crt_srv->priority) && 
884
+					   ( (srv_rd->priority == crt_srv->priority) &&
868 885
 							 (srv_rd->weight > crt_srv->weight) ) ){
869 886
 						/* insert here */
870 887
 						goto skip;
... ...
@@ -926,9 +943,9 @@ again:
926 943
 				*last=rd;
927 944
 				last=&(rd->next);
928 945
 		}
929
-		
946
+
930 947
 		p+=rdlength;
931
-		
948
+
932 949
 	}
933 950
 	if (flags & RES_AR){
934 951
 		flags&=~RES_AR;