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:
151
nmap_dns.cc
151
nmap_dns.cc
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user