Module: kamailio
Branch: master
Commit: 20752cf945d4ba0660d321d73efff5c93f6d20a8
URL:
https://github.com/kamailio/kamailio/commit/20752cf945d4ba0660d321d73efff5c…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)gmail.com>
Date: 2017-12-30T16:57:42+01:00
core: resolve - early safety checks to deal faster with broken dns responses
---
Modified: src/core/resolve.c
---
Diff:
https://github.com/kamailio/kamailio/commit/20752cf945d4ba0660d321d73efff5c…
Patch:
https://github.com/kamailio/kamailio/commit/20752cf945d4ba0660d321d73efff5c…
---
diff --git a/src/core/resolve.c b/src/core/resolve.c
index 0daaa30910..2b1441e36d 100644
--- a/src/core/resolve.c
+++ b/src/core/resolve.c
@@ -679,13 +679,16 @@ void free_rdata_list(struct rdata* head)
int match_search_list(const struct __res_state* res, char* name) {
int i;
for (i=0; (i<MAXDNSRCH) && (res->dnsrch[i]); i++) {
- if (strcasecmp(name, res->dnsrch[i])==0)
+ if (strcasecmp(name, res->dnsrch[i])==0)
return 1;
}
return 0;
}
#endif
+#define SR_DNS_MAX_QNO 10
+#define SR_DNS_MAX_ANO 100
+
/** gets the DNS records for name:type
* returns a dyn. alloc'ed struct rdata linked list with the parsed responses
* or 0 on error
@@ -714,7 +717,7 @@ struct rdata* get_record(char* name, int type, int flags)
int name_len;
struct rdata* fullname_rd;
char c;
-
+
name_len=strlen(name);
for (i = 0; i < name_len; i++) {
@@ -744,12 +747,21 @@ struct rdata* get_record(char* name, int type, int flags)
else if (unlikely(size > sizeof(buff))) size=sizeof(buff);
head=rd=0;
last=crt=&head;
-
+
p=buff.buff+DNS_HDR_SIZE;
end=buff.buff+size;
if (unlikely(p>=end)) goto error_boundary;
qno=ntohs((unsigned short)buff.hdr.qdcount);
+ if(qno!=1) {
+ /* usually the query is with a single domain name */
+ LM_INFO("dns questions number is: %u\n", (uint32_t)qno);
+ if(qno>SR_DNS_MAX_QNO) {
+ /* early safe check against broken results */
+ LM_ERR("dns questions number is too high: %u\n", (uint32_t)qno);
+ goto error;
+ }
+ }
for (r=0; r<qno; r++){
/* skip the name of the question */
if (unlikely((p=dns_skipname(p, end))==0)) {
@@ -765,8 +777,13 @@ struct rdata* get_record(char* name, int type, int flags)
LM_ERR("p>=end\n");
goto error;
}
- };
+ }
answers_no=ntohs((unsigned short)buff.hdr.ancount);
+ if(answers_no>SR_DNS_MAX_ANO) {
+ /* early safety check on answers number */
+ LM_ERR("dns answers number is too high: %u\n", (uint32_t)answers_no);
+ goto error;
+ }
again:
for (r=0; (r<answers_no) && (p<end); r++){
#if 0
@@ -815,7 +832,7 @@ struct rdata* get_record(char* name, int type, int flags)
continue;
}
/* expand the "type" record (rdata)*/
-
+
rd=(struct rdata*) local_malloc(sizeof(struct rdata)+rec_name_len+
1-1);
if (rd==0){
@@ -857,14 +874,14 @@ struct rdata* get_record(char* name, int type, int flags)
srv_rd= dns_srv_parser(buff.buff, end, rd_end, p);
rd->rdata=(void*)srv_rd;
if (unlikely(srv_rd==0)) goto error_parse;
-
+
/* insert sorted into the list */
for (crt=&head; *crt; crt= &((*crt)->next)){
if ((*crt)->type!=T_SRV)
continue;
crt_srv=(struct srv_rdata*)(*crt)->rdata;
if ((srv_rd->priority < crt_srv->priority) ||
- ( (srv_rd->priority == crt_srv->priority) &&
+ ( (srv_rd->priority == crt_srv->priority) &&
(srv_rd->weight > crt_srv->weight) ) ){
/* insert here */
goto skip;
@@ -926,9 +943,9 @@ struct rdata* get_record(char* name, int type, int flags)
*last=rd;
last=&(rd->next);
}
-
+
p+=rdlength;
-
+
}
if (flags & RES_AR){
flags&=~RES_AR;