aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols/dns.c
diff options
context:
space:
mode:
authorLuca Deri <lucaderi@users.noreply.github.com>2019-03-23 09:51:53 +0100
committerGitHub <noreply@github.com>2019-03-23 09:51:53 +0100
commite2ad6bf79f86e25ec4f882b2dea8ed1649148bf1 (patch)
tree2e9b0723cb65fb551ffe5560c195e450445e53d4 /src/lib/protocols/dns.c
parentef9f395cb6b556f1a40c4bb029622c6c2318be42 (diff)
parenta99754d88bd1386536162d434304b61048da3f22 (diff)
Merge pull request #673 from vel21ripn/dns_fix_name
More accurate hostname verification in a DNS query.
Diffstat (limited to 'src/lib/protocols/dns.c')
-rw-r--r--src/lib/protocols/dns.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c
index e282eb4d3..d17acd2bd 100644
--- a/src/lib/protocols/dns.c
+++ b/src/lib/protocols/dns.c
@@ -59,7 +59,19 @@ static u_int getNameLength(u_int i, const u_int8_t *payload, u_int payloadLen) {
return(off + getNameLength(i+off, payload, payloadLen));
}
}
+/*
+ allowed chars for dns names A-Z 0-9 _ -
+ Perl script for generation map:
+ my @M;
+ for(my $ch=0; $ch < 256; $ch++) {
+ $M[$ch >> 5] |= 1 << ($ch & 0x1f) if chr($ch) =~ /[a-z0-9_-]/i;
+ }
+ print join(',', map { sprintf "0x%08x",$_ } @M),"\n";
+ */
+static uint32_t dns_validchar[8] = {
+ 0x00000000,0x03ff2000,0x87fffffe,0x07fffffe,0,0,0,0
+};
/* *********************************************** */
void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
@@ -108,6 +120,7 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
invalid = 1;
if(!invalid) {
+ int j = 0, max_len, off;
if(is_query) {
/* DNS Request */
if((dns_header.num_queries > 0) && (dns_header.num_queries <= NDPI_MAX_DNS_REQUESTS)
@@ -187,28 +200,31 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
}
/* extract host name server */
- int j = 0, max_len = sizeof(flow->host_server_name)-1, off = sizeof(struct ndpi_dns_packet_header) + 1 + payload_offset;
- while(off < flow->packet.payload_packet_len && flow->packet.payload[off] != '\0') {
- flow->host_server_name[j] = flow->packet.payload[off];
- if(j < max_len) {
- if(flow->host_server_name[j] < ' ')
- flow->host_server_name[j] = '.';
- j++;
- } else
- break;
-
- off++;
+ max_len = sizeof(flow->host_server_name)-1;
+ off = sizeof(struct ndpi_dns_packet_header) + payload_offset;
+
+ while(j < max_len && off < flow->packet.payload_packet_len && flow->packet.payload[off] != '\0') {
+ uint8_t c,cl = flow->packet.payload[off++];
+ if( (cl & 0xc0) != 0 || // we not support compressed names in query
+ off + cl >= flow->packet.payload_packet_len) {
+ j = 0; break;
+ }
+ if(j && j < max_len) flow->host_server_name[j++] = '.';
+ while(j < max_len && cl != 0) {
+ c = flow->packet.payload[off++];
+ flow->host_server_name[j++] = dns_validchar[c >> 5] & (1 << (c & 0x1f)) ? c:'_';
+ cl--;
+ }
}
+ flow->host_server_name[j] = '\0';
if(is_query && (ndpi_struct->dns_dont_dissect_response == 0)) {
// dpi_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
return; /* The response will set the verdict */
}
-
- flow->host_server_name[j] = '\0';
flow->protos.dns.num_queries = (u_int8_t)dns_header.num_queries,
- flow->protos.dns.num_answers = (u_int8_t) (dns_header.num_answers + dns_header.authority_rrs + dns_header.additional_rrs);
+ flow->protos.dns.num_answers = (u_int8_t) (dns_header.num_answers + dns_header.authority_rrs + dns_header.additional_rrs);
if(j > 0) {
ndpi_protocol_match_result ret_match;