BUG/MEDIUM: dns: Consider the fact that dns answers are case-insensitive
We can't expect the DNS answer to always match the case we used for the request, so we can't just use memcmp() to compare the DNS answer with what we are expected. Instead, introduce dns_hostname_cmp(), which compares each string in a case-insensitive way. This should fix github issue #566. This should be backported to 2.1, 2.0, 1.9 and 1.8.
This commit is contained in:
parent
5e8017d53c
commit
b17b884870
29
src/dns.c
29
src/dns.c
|
@ -77,6 +77,19 @@ struct dns_resolvers *find_resolvers_by_id(const char *id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Compare hostnames in a case-insensitive way .
|
||||
* Returns 0 if they are the same, non-zero otherwise
|
||||
*/
|
||||
static __inline int dns_hostname_cmp(const char *name1, const char *name2, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
if (tolower(name1[i]) != tolower(name2[i]))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns a pointer on the SRV request matching the name <name> for the proxy
|
||||
* <px>. NULL is returned if no match is found.
|
||||
*/
|
||||
|
@ -540,7 +553,7 @@ static void dns_check_dns_response(struct dns_resolution *res)
|
|||
HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
|
||||
if (srv->srvrq == srvrq && srv->svc_port == item->port &&
|
||||
item->data_len == srv->hostname_dn_len &&
|
||||
!memcmp(srv->hostname_dn, item->target, item->data_len)) {
|
||||
!dns_hostname_cmp(srv->hostname_dn, item->target, item->data_len)) {
|
||||
snr_update_srv_status(srv, 1);
|
||||
free(srv->hostname);
|
||||
free(srv->hostname_dn);
|
||||
|
@ -572,7 +585,7 @@ static void dns_check_dns_response(struct dns_resolution *res)
|
|||
HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
|
||||
if (srv->srvrq == srvrq && srv->svc_port == item->port &&
|
||||
item->data_len == srv->hostname_dn_len &&
|
||||
!memcmp(srv->hostname_dn, item->target, item->data_len) &&
|
||||
!dns_hostname_cmp(srv->hostname_dn, item->target, item->data_len) &&
|
||||
!srv->dns_opts.ignore_weight) {
|
||||
int ha_weight;
|
||||
|
||||
|
@ -820,7 +833,7 @@ static int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend,
|
|||
|
||||
/* Check if the current record dname is valid. previous_dname
|
||||
* points either to queried dname or last CNAME target */
|
||||
if (dns_query->type != DNS_RTYPE_SRV && memcmp(previous_dname, tmpname, len) != 0) {
|
||||
if (dns_query->type != DNS_RTYPE_SRV && dns_hostname_cmp(previous_dname, tmpname, len) != 0) {
|
||||
pool_free(dns_answer_item_pool, dns_answer_record);
|
||||
if (i == 0) {
|
||||
/* First record, means a mismatch issue between
|
||||
|
@ -999,7 +1012,7 @@ static int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend,
|
|||
|
||||
case DNS_RTYPE_SRV:
|
||||
if (dns_answer_record->data_len == tmp_record->data_len &&
|
||||
!memcmp(dns_answer_record->target, tmp_record->target, dns_answer_record->data_len) &&
|
||||
!dns_hostname_cmp(dns_answer_record->target, tmp_record->target, dns_answer_record->data_len) &&
|
||||
dns_answer_record->port == tmp_record->port) {
|
||||
tmp_record->weight = dns_answer_record->weight;
|
||||
found = 1;
|
||||
|
@ -1179,7 +1192,7 @@ static int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend,
|
|||
if ( !(
|
||||
(tmp_record->type == DNS_RTYPE_SRV) &&
|
||||
(tmp_record->ar_item == NULL) &&
|
||||
(memcmp(tmp_record->target, dns_answer_record->name, tmp_record->data_len) == 0)
|
||||
(dns_hostname_cmp(tmp_record->target, dns_answer_record->name, tmp_record->data_len) == 0)
|
||||
)
|
||||
)
|
||||
continue;
|
||||
|
@ -1520,7 +1533,7 @@ static struct dns_resolution *dns_pick_resolution(struct dns_resolvers *resolver
|
|||
continue;
|
||||
if ((query_type == res->prefered_query_type) &&
|
||||
hostname_dn_len == res->hostname_dn_len &&
|
||||
!memcmp(*hostname_dn, res->hostname_dn, hostname_dn_len))
|
||||
!dns_hostname_cmp(*hostname_dn, res->hostname_dn, hostname_dn_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1530,7 +1543,7 @@ static struct dns_resolution *dns_pick_resolution(struct dns_resolvers *resolver
|
|||
continue;
|
||||
if ((query_type == res->prefered_query_type) &&
|
||||
hostname_dn_len == res->hostname_dn_len &&
|
||||
!memcmp(*hostname_dn, res->hostname_dn, hostname_dn_len))
|
||||
!dns_hostname_cmp(*hostname_dn, res->hostname_dn, hostname_dn_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1897,7 +1910,7 @@ static void dns_resolve_recv(struct dgram_conn *dgram)
|
|||
* sent. We can check only the first query of the list. We send
|
||||
* one query at a time so we get one query in the response */
|
||||
query = LIST_NEXT(&res->response.query_list, struct dns_query_item *, list);
|
||||
if (query && memcmp(query->name, res->hostname_dn, res->hostname_dn_len) != 0) {
|
||||
if (query && dns_hostname_cmp(query->name, res->hostname_dn, res->hostname_dn_len) != 0) {
|
||||
dns_resp = DNS_RESP_WRONG_NAME;
|
||||
ns->counters.other++;
|
||||
goto report_res_error;
|
||||
|
|
Loading…
Reference in New Issue