diff options
author | Luca Deri <lucaderi@users.noreply.github.com> | 2019-03-23 09:51:53 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-23 09:51:53 +0100 |
commit | e2ad6bf79f86e25ec4f882b2dea8ed1649148bf1 (patch) | |
tree | 2e9b0723cb65fb551ffe5560c195e450445e53d4 /src/lib/protocols/dns.c | |
parent | ef9f395cb6b556f1a40c4bb029622c6c2318be42 (diff) | |
parent | a99754d88bd1386536162d434304b61048da3f22 (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.c | 44 |
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; |