diff --git a/CHANGELOG b/CHANGELOG index f8ff393ae..2de9dde28 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ #Nmap Changelog ($Id$); -*-text-*- +o [GH#2068] Fix reverse-DNS handling of PTR records that are not lowercase. + Nmap was failing to identify reverse-DNS names when the DNS server delivered + them like ".IN-ADDR.ARPA". [Lucas Nussbaum, Daniel Miller] + o [NSE][GH#1999][GH#2005] IKE library was not properly populating the protocol number in aggressive mode requests. [luc-x41] diff --git a/nmap_dns.cc b/nmap_dns.cc index cc6144549..2b29ce8dc 100644 --- a/nmap_dns.cc +++ b/nmap_dns.cc @@ -1414,53 +1414,94 @@ bool DNS::Factory::ipToPtr(const sockaddr_storage &ip, std::string &ptr) bool DNS::Factory::ptrToIp(const std::string &ptr, sockaddr_storage &ip) { - std::string ip_str; + const char *cptr = ptr.c_str(); + const char *p = NULL; - size_t pos = ptr.rfind(IPV6_PTR_DOMAIN); - if(pos != std::string::npos) + memset(&ip, 0, sizeof(sockaddr_storage)); + + // Check whether the name ends with the IPv4 PTR domain + if (NULL != (p = strcasestr(cptr + ptr.length() + 1 - sizeof(C_IPV4_PTR_DOMAIN), C_IPV4_PTR_DOMAIN))) { - u8 counter = 0; - for (std::string::const_reverse_iterator it = ptr.rend()-pos; it != ptr.rend(); ++it) + struct sockaddr_in *ip4 = (struct sockaddr_in *)&ip; + u8 place_value[] = {1, 10, 100}; + u8 *v = (u8 *) &(ip4->sin_addr.s_addr); + size_t place = 0; + size_t i = 0; + + p--; + while (i < sizeof(ip4->sin_addr.s_addr)) { - const char &c = *it; - if(c != '.') + if (*p == '.') { - ip_str += c; - if(++counter==4) counter=0, ip_str+=':'; + place = 0; + p--; + i++; } + if (p < cptr) + { + break; + } + u8 n = *p; + if (n >= '0' && n <= '9') { // 0-9 + n -= 0x30; + } + else { // invalid + return false; + } + v[i] += n * place_value[place]; + place++; + p--; } - - std::string::iterator it = ip_str.end()-1; - if( *it == ':') ip_str.erase(it); + ip.ss_family = AF_INET; } - - std::string mptr = '.' + ptr; - pos = mptr.rfind(IPV4_PTR_DOMAIN); - if(pos != std::string::npos) + // If not, check IPv6 + else if (NULL != (p = strcasestr(cptr + ptr.length() + 1 - sizeof(C_IPV6_PTR_DOMAIN), C_IPV6_PTR_DOMAIN))) { + struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)&ip; + u8 alt = 0; + size_t i=0; - std::string octet; - std::string::const_reverse_iterator crend = mptr.rend(); - for (std::string::const_reverse_iterator it = crend-pos; it != crend; ++it) + p--; + while (i < sizeof(ip6->sin6_addr.s6_addr)) { - const char &c = *it; - if(c == '.') + if (*p == '.') { - std::reverse(octet.begin(), octet.end()); - ip_str += octet + '.'; - octet.clear(); + p--; } - else octet += c; + if (p < cptr) + { + break; + } + u8 n = *p; + if (n < 0x3A) { // 0-9 + n -= 0x30; + } + else if (n < 0x47) { // A-F + n -= 0x37; + } + else if (n < 0x67) { // a-f + n -= 0x57; + } + else { // invalid + return false; + } + if (n < 0) { // invalid + return false; + } + if (alt == 0) { // high nibble + ip6->sin6_addr.s6_addr[i] += n << 4; + alt = 1; + } + else { // low nibble + ip6->sin6_addr.s6_addr[i] += n; + alt = 0; + i++; + } + p--; } - - std::string::iterator it = ip_str.end()-1; - if( *it == '.') ip_str.erase(it); + ip.ss_family = AF_INET6; } - - if(ip_str.empty()) - return false; - - return sockaddr_storage_inet_pton(ip_str.c_str(), &ip); + return true; } size_t DNS::Factory::buildSimpleRequest(const std::string &name, RECORD_TYPE rt, u8 *buf, size_t maxlen) diff --git a/nmap_dns.h b/nmap_dns.h index 8ce346a0e..8ff5797e4 100644 --- a/nmap_dns.h +++ b/nmap_dns.h @@ -201,8 +201,10 @@ typedef enum { const u8 COMPRESSED_NAME = 0xc0; -const std::string IPV4_PTR_DOMAIN = ".in-addr.arpa"; -const std::string IPV6_PTR_DOMAIN = ".ip6.arpa"; +#define C_IPV4_PTR_DOMAIN ".in-addr.arpa" +#define C_IPV6_PTR_DOMAIN ".ip6.arpa" +const std::string IPV4_PTR_DOMAIN = C_IPV4_PTR_DOMAIN; +const std::string IPV6_PTR_DOMAIN = C_IPV6_PTR_DOMAIN; class Factory {