1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 12:41:29 +00:00

Support forward-DNS in mass_dns (1 addr per name)

This commit is contained in:
dmiller
2024-04-25 17:12:29 +00:00
parent 924f91eb20
commit 480803e24a
2 changed files with 102 additions and 77 deletions

View File

@@ -131,7 +131,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <list> #include <list>
#include <vector>
extern NmapOps o; extern NmapOps o;
@@ -623,26 +622,51 @@ static void process_request(int action, info &reqinfo) {
// After processing a DNS response, we search through the IPs we're // After processing a DNS response, we search through the IPs we're
// looking for and update their results as necessary. // looking for and update their results as necessary.
static int process_result(const sockaddr_storage &ip, const std::string &result, int action, info &reqinfo) static bool process_result(const std::string &name, const DNS::Record *rr, info &reqinfo, bool already_matched)
{ {
assert(action == ACTION_FINISHED); DNS::Request *reqt = reqinfo.tpreq->targ;
request *tpreq = reqinfo.tpreq; const struct sockaddr_storage *ss = NULL;
const DNS::A_Record *a_rec = NULL;
if (!result.empty()) sockaddr_storage ip;
ip.ss_family = AF_UNSPEC;
switch (reqt->type) {
case DNS::A:
case DNS::AAAA:
if (!already_matched && name != reqt->name) {
return false;
}
a_rec = static_cast<const DNS::A_Record *>(rr);
memcpy(&reqt->ss, &a_rec->value, sizeof(struct sockaddr_storage));
if (o.debugging >= TRACE_DEBUG_LEVEL)
{ {
if (!sockaddr_storage_equal(&ip, &tpreq->targ->ss)) log_write(LOG_STDOUT, "mass_dns: OK MATCHED <%s> to <%s>\n",
reqt->name.c_str(),
inet_ntop_ez(&a_rec->value, sizeof(struct sockaddr_storage)));
}
break;
case DNS::PTR:
ss = &reqt->ss;
if (!already_matched) {
if (!DNS::Factory::ptrToIp(name, ip) ||
!sockaddr_storage_equal(&ip, ss)) {
return false;
}
}
reqt->name = static_cast<const DNS::PTR_Record *>(rr)->value;
host_cache.add(*ss, reqt->name);
if (o.debugging >= TRACE_DEBUG_LEVEL)
{ {
if (o.debugging) log_write(LOG_STDOUT, "mass_dns: OK MATCHED <%s> to <%s>\n",
log_write(LOG_STDOUT, "mass_rdns: Mismatched record for ID %d\n", tpreq->id); inet_ntop_ez(ss, sizeof(struct sockaddr_storage)),
return 0; reqt->name.c_str());
}
break;
default:
assert(false);
break;
} }
process_request(ACTION_FINISHED, reqinfo);
tpreq->targ->name = result;
host_cache.add(tpreq->targ->ss, result);
}
process_request(action, reqinfo);
do_possible_writes(); do_possible_writes();
@@ -717,6 +741,7 @@ static void read_evt_handler(nsock_pool nsp, nsock_event evt, void *) {
sockaddr_storage ip; sockaddr_storage ip;
ip.ss_family = AF_UNSPEC; ip.ss_family = AF_UNSPEC;
std::string alias; std::string alias;
DNS::Request *reqt = reqinfo.tpreq->targ;
for(std::list<DNS::Answer>::const_iterator it = p.answers.begin(); for(std::list<DNS::Answer>::const_iterator it = p.answers.begin();
it != p.answers.end() && !processing_successful; ++it ) it != p.answers.end() && !processing_successful; ++it )
@@ -724,51 +749,27 @@ static void read_evt_handler(nsock_pool nsp, nsock_event evt, void *) {
const DNS::Answer &a = *it; const DNS::Answer &a = *it;
if(a.record_class == DNS::CLASS_IN) if(a.record_class == DNS::CLASS_IN)
{ {
switch(a.record_type) if (reqt->type == a.record_type) {
{ processing_successful = process_result(a.name, a.record, reqinfo, a.name == alias);
case DNS::PTR: if (processing_successful) {
{
DNS::PTR_Record * ptr = static_cast<DNS::PTR_Record *>(a.record);
if(
// If CNAME answer filled in ip with a matching alias
(ip.ss_family != AF_UNSPEC && a.name == alias )
// Or if we can get an IP from reversing the .arpa PTR address
|| DNS::Factory::ptrToIp(a.name, ip))
{
if ((processing_successful = process_result(ip, ptr->value, ACTION_FINISHED, reqinfo)))
{
if (o.debugging >= TRACE_DEBUG_LEVEL)
{
char ipstr[INET6_ADDRSTRLEN];
sockaddr_storage_iptop(&ip, ipstr);
log_write(LOG_STDOUT, "mass_rdns: OK MATCHED <%s> to <%s>\n",
ipstr,
ptr->value.c_str());
}
output_summary(); output_summary();
stat_ok++; stat_ok++;
} }
else if (o.debugging) {
log_write(LOG_STDOUT, "mass_dns: Mismatched record for request %s\n", reqt->repr());
} }
break;
} }
case DNS::CNAME: else if (a.record_type == DNS::CNAME) {
const DNS::CNAME_Record *cname = static_cast<const DNS::CNAME_Record *>(a.record);
if((reqt->type == DNS::PTR && DNS::Factory::ptrToIp(a.name, ip))
|| a.name == reqt->name)
{ {
if(DNS::Factory::ptrToIp(a.name, ip))
{
DNS::CNAME_Record * cname = static_cast<DNS::CNAME_Record *>(a.record);
alias = cname->value; alias = cname->value;
if (o.debugging >= TRACE_DEBUG_LEVEL) if (o.debugging >= TRACE_DEBUG_LEVEL)
{ {
char ipstr[INET6_ADDRSTRLEN]; log_write(LOG_STDOUT, "mass_dns: CNAME found for <%s> to <%s>\n", a.name.c_str(), alias.c_str());
sockaddr_storage_iptop(&ip, ipstr);
log_write(LOG_STDOUT, "mass_rdns: CNAME found for <%s> to <%s>\n", ipstr, alias.c_str());
} }
} }
break;
}
default:
break;
} }
} }
} }
@@ -1068,6 +1069,39 @@ static void init_servs(void) {
} }
} }
static bool system_resolve(DNS::Request &reqt)
{
char hostname[FQDN_LEN + 1] = "";
int af = AF_INET;
struct addrinfo *ai_result = NULL, *ai = NULL;
switch (reqt.type) {
case DNS::PTR:
if (getnameinfo((const struct sockaddr *) &reqt.ss,
sizeof(sockaddr_storage), hostname,
sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) {
reqt.name = hostname;
return true;
}
break;
case DNS::AAAA:
af = AF_INET6;
case DNS::A:
ai_result = resolve_all(reqt.name.c_str(), af);
for (ai = ai_result; ai != NULL; ai = ai->ai_next) {
if (ai->ai_addr->sa_family == af && ai->ai_addrlen <= sizeof(reqt.ss)) {
memcpy(&reqt.ss, ai->ai_addr, ai->ai_addrlen);
return true;
}
}
break;
default:
error("System DNS resolution of %s could not be performed.\n", reqt.repr());
break;
}
return false;
}
//------------------- Main loops --------------------- //------------------- Main loops ---------------------
@@ -1102,9 +1136,11 @@ static void nmap_mass_dns_core(DNS::Request *requests, int num_requests) {
DNS::Request &reqt = requests[i]; DNS::Request &reqt = requests[i];
// See if it's cached // See if it's cached
if (reqt.type == DNS::PTR) {
if (host_cache.lookup(reqt.ss, reqt.name)) { if (host_cache.lookup(reqt.ss, reqt.name)) {
continue; continue;
} }
}
tpreq = new request; tpreq = new request;
tpreq->targ = &reqt; tpreq->targ = &reqt;
@@ -1169,19 +1205,14 @@ static void nmap_mass_dns_core(DNS::Request *requests, int num_requests) {
SPM = new ScanProgressMeter(spmobuf); SPM = new ScanProgressMeter(spmobuf);
for(i=0, reqI = deferred_reqs.begin(); reqI != deferred_reqs.end(); reqI++, i++) { for(i=0, reqI = deferred_reqs.begin(); reqI != deferred_reqs.end(); reqI++, i++) {
char hostname[FQDN_LEN + 1] = "";
if (keyWasPressed()) if (keyWasPressed())
SPM->printStats((double) i / deferred_reqs.size(), NULL); SPM->printStats((double) i / deferred_reqs.size(), NULL);
tpreq = *reqI; tpreq = *reqI;
if (system_resolve(*tpreq->targ)) {
if (getnameinfo((const struct sockaddr *)&tpreq->targ->ss,
sizeof(struct sockaddr_storage), hostname,
sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) {
stat_ok++; stat_ok++;
stat_cname++; stat_cname++;
tpreq->targ->name = hostname;
} }
delete tpreq; delete tpreq;
@@ -1197,7 +1228,6 @@ static void nmap_mass_dns_core(DNS::Request *requests, int num_requests) {
} }
static void nmap_system_dns_core(DNS::Request requests[], int num_requests) { static void nmap_system_dns_core(DNS::Request requests[], int num_requests) {
char hostname[FQDN_LEN + 1] = "";
char spmobuf[1024]; char spmobuf[1024];
stat_actual = num_requests; stat_actual = num_requests;
@@ -1206,16 +1236,11 @@ static void nmap_system_dns_core(DNS::Request requests[], int num_requests) {
for (int i=0; i < num_requests; i++) for (int i=0; i < num_requests; i++)
{ {
DNS::Request &reqt = requests[i];
if (keyWasPressed()) if (keyWasPressed())
SPM->printStats((double) i / stat_actual, NULL); SPM->printStats((double) i / stat_actual, NULL);
if (getnameinfo((const struct sockaddr *)&reqt.ss, if (system_resolve(requests[i])) {
sizeof(sockaddr_storage), hostname,
sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) {
stat_ok++; stat_ok++;
reqt.name = hostname;
} }
} }

View File

@@ -252,7 +252,7 @@ struct Request
RECORD_TYPE type; RECORD_TYPE type;
struct sockaddr_storage ss; struct sockaddr_storage ss;
std::string name; std::string name;
Request() : type(NONE), name() {} Request() : type(NONE), name() {ss.ss_family = AF_UNSPEC;}
const char *repr(); // string representation const char *repr(); // string representation
}; };
} }