mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 12:41:29 +00:00
Implemented more testing fixed some subtle bug thanks to it
This commit is contained in:
@@ -185,7 +185,7 @@ release-rpms:
|
|||||||
web:
|
web:
|
||||||
cd $(NMAPDEVDIR) && $(MAKE) web
|
cd $(NMAPDEVDIR) && $(MAKE) web
|
||||||
|
|
||||||
clean: @LUA_CLEAN@ @LIBLINEAR_CLEAN@ @PCAP_CLEAN@ @PCRE_CLEAN@ @DNET_CLEAN@ nsock_clean nbase_clean netutil_clean my_clean @NPING_CLEAN@ @ZENMAP_CLEAN@ @NCAT_CLEAN@ @NMAP_UPDATE_CLEAN@ @NDIFF_CLEAN@
|
clean: @LUA_CLEAN@ @LIBLINEAR_CLEAN@ @PCAP_CLEAN@ @PCRE_CLEAN@ @DNET_CLEAN@ nsock_clean nbase_clean netutil_clean my_clean @NPING_CLEAN@ @ZENMAP_CLEAN@ @NCAT_CLEAN@ @NMAP_UPDATE_CLEAN@ @NDIFF_CLEAN@ tests/clean
|
||||||
|
|
||||||
my_clean:
|
my_clean:
|
||||||
rm -f dependencies.mk
|
rm -f dependencies.mk
|
||||||
@@ -300,6 +300,9 @@ nmap-update/default_channel.h: nmap.h
|
|||||||
tests/check_dns: $(OBJS)
|
tests/check_dns: $(OBJS)
|
||||||
$(CXX) -o $@ $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $^ $(LIBS) tests/nmap_dns_test.cc
|
$(CXX) -o $@ $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $^ $(LIBS) tests/nmap_dns_test.cc
|
||||||
|
|
||||||
|
tests/clean:
|
||||||
|
@rm -f tests/check_dns
|
||||||
|
|
||||||
# By default distutils rewrites installed scripts to hardcode the
|
# By default distutils rewrites installed scripts to hardcode the
|
||||||
# location of the Python interpreter they were built with (something
|
# location of the Python interpreter they were built with (something
|
||||||
# like #!/usr/bin/python2.4). This is the wrong thing to do when
|
# like #!/usr/bin/python2.4). This is the wrong thing to do when
|
||||||
|
|||||||
27
nmap_dns.cc
27
nmap_dns.cc
@@ -1477,29 +1477,31 @@ size_t DNS::Factory::putDomainName(const std::string &name, char *buf, size_t of
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
size_t DNS::Factory::parseUnsignedShort(u16 &num, char *buf, size_t offset, size_t maxlen)
|
size_t DNS::Factory::parseUnsignedShort(u16 &num, const char *buf, size_t offset, size_t maxlen)
|
||||||
{
|
{
|
||||||
size_t max_access = offset+1;
|
size_t max_access = offset+1;
|
||||||
if(buf && (maxlen > max_access))
|
if(buf && (maxlen > max_access))
|
||||||
{
|
{
|
||||||
num = buf[max_access] + (buf[offset]<<8);
|
const u8 * n = reinterpret_cast<const u8 *>(buf+offset);
|
||||||
|
num = n[1] + (n[0]<<8);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t DNS::Factory::parseUnsignedInt(u32 &num, char *buf, size_t offset, size_t maxlen)
|
size_t DNS::Factory::parseUnsignedInt(u32 &num, const char *buf, size_t offset, size_t maxlen)
|
||||||
{
|
{
|
||||||
size_t max_access = offset+3;
|
size_t max_access = offset+3;
|
||||||
if(buf && (maxlen > max_access))
|
if(buf && (maxlen > max_access))
|
||||||
{
|
{
|
||||||
num = buf[offset+3] + (buf[offset+2]<<8) + (buf[offset+1]<<16) + (buf[offset]<<24);
|
const u8 * n = reinterpret_cast<const u8 *>(buf + offset);
|
||||||
|
num = n[3] + (n[2]<<8) + (n[1]<<16) + (n[0]<<24);
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t DNS::Factory::parseDomainName(std::string &name, char *buf, size_t offset, size_t maxlen)
|
size_t DNS::Factory::parseDomainName(std::string &name, const char *buf, size_t offset, size_t maxlen)
|
||||||
{
|
{
|
||||||
size_t tmp, ret = 0;
|
size_t tmp, ret = 0;
|
||||||
|
|
||||||
@@ -1537,7 +1539,7 @@ size_t DNS::Factory::parseDomainName(std::string &name, char *buf, size_t offset
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t DNS::Query::parseFromBuffer(char *buf, size_t offset, size_t maxlen)
|
size_t DNS::Query::parseFromBuffer(const char *buf, size_t offset, size_t maxlen)
|
||||||
{
|
{
|
||||||
size_t ret=0;
|
size_t ret=0;
|
||||||
|
|
||||||
@@ -1552,7 +1554,7 @@ size_t DNS::Query::parseFromBuffer(char *buf, size_t offset, size_t maxlen)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t DNS::Answer::parseFromBuffer(char * buf, size_t offset, size_t maxlen)
|
size_t DNS::Answer::parseFromBuffer(const char * buf, size_t offset, size_t maxlen)
|
||||||
{
|
{
|
||||||
size_t ret=0;
|
size_t ret=0;
|
||||||
|
|
||||||
@@ -1570,21 +1572,26 @@ size_t DNS::Answer::parseFromBuffer(char * buf, size_t offset, size_t maxlen)
|
|||||||
|
|
||||||
switch(record_type)
|
switch(record_type)
|
||||||
{
|
{
|
||||||
|
case A:
|
||||||
|
{
|
||||||
|
record = new A_Record();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CNAME:
|
case CNAME:
|
||||||
{
|
{
|
||||||
record = new CNAME_Record();
|
record = new CNAME_Record();
|
||||||
DNS_CHECK_ACCUMLATE(ret, tmp, record->parseFromBuffer(buf, offset+ret, maxlen));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PTR:
|
case PTR:
|
||||||
{
|
{
|
||||||
record = new PTR_Record();
|
record = new PTR_Record();
|
||||||
DNS_CHECK_ACCUMLATE(ret, tmp, record->parseFromBuffer(buf, offset+ret, maxlen));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DNS_CHECK_ACCUMLATE(ret, tmp, record->parseFromBuffer(buf, offset+ret, maxlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1600,7 +1607,7 @@ DNS::Answer& DNS::Answer::operator=(const Answer &r)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t DNS::Packet::parseFromBuffer(char *buf, size_t maxlen)
|
size_t DNS::Packet::parseFromBuffer(const char *buf, size_t maxlen)
|
||||||
{
|
{
|
||||||
if( !buf || maxlen < DATA) return 0;
|
if( !buf || maxlen < DATA) return 0;
|
||||||
|
|
||||||
|
|||||||
40
nmap_dns.h
40
nmap_dns.h
@@ -132,6 +132,7 @@ class Target;
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
namespace DNS
|
namespace DNS
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -206,9 +207,9 @@ public:
|
|||||||
static size_t buildReverseRequest(const sockaddr_storage &ip, char *buf, size_t maxlen);
|
static size_t buildReverseRequest(const sockaddr_storage &ip, char *buf, size_t maxlen);
|
||||||
static size_t putUnsignedShort(u16 num, char *buf, size_t offset, size_t maxlen);
|
static size_t putUnsignedShort(u16 num, char *buf, size_t offset, size_t maxlen);
|
||||||
static size_t putDomainName(const std::string &name, char *buf, size_t offset, size_t maxlen);
|
static size_t putDomainName(const std::string &name, char *buf, size_t offset, size_t maxlen);
|
||||||
static size_t parseUnsignedShort(u16 &num, char *buf, size_t offset, size_t maxlen);
|
static size_t parseUnsignedShort(u16 &num, const char *buf, size_t offset, size_t maxlen);
|
||||||
static size_t parseUnsignedInt(u32 &num, char *buf, size_t offset, size_t maxlen);
|
static size_t parseUnsignedInt(u32 &num, const char *buf, size_t offset, size_t maxlen);
|
||||||
static size_t parseDomainName(std::string &name, char *buf, size_t offset, size_t maxlen);
|
static size_t parseDomainName(std::string &name, const char *buf, size_t offset, size_t maxlen);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Record
|
class Record
|
||||||
@@ -216,7 +217,28 @@ class Record
|
|||||||
public:
|
public:
|
||||||
virtual Record * clone() = 0;
|
virtual Record * clone() = 0;
|
||||||
virtual ~Record() {}
|
virtual ~Record() {}
|
||||||
virtual size_t parseFromBuffer(char *buf, size_t offset, size_t maxlen) = 0;
|
virtual size_t parseFromBuffer(const char *buf, size_t offset, size_t maxlen) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class A_Record : public Record
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
sockaddr_storage value;
|
||||||
|
Record * clone() { return new A_Record(*this); }
|
||||||
|
~A_Record() {}
|
||||||
|
size_t parseFromBuffer(const char *buf, size_t offset, size_t maxlen)
|
||||||
|
{
|
||||||
|
size_t tmp, ret = 0;
|
||||||
|
u32 num;
|
||||||
|
DNS_CHECK_ACCUMLATE(ret, tmp, Factory::parseUnsignedInt(num, buf, offset, maxlen));
|
||||||
|
|
||||||
|
memset(&value, 0, sizeof(value));
|
||||||
|
struct sockaddr_in * ip4addr = (sockaddr_in *) &value;
|
||||||
|
ip4addr->sin_family = AF_INET;
|
||||||
|
ip4addr->sin_addr.s_addr = htonl(num);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PTR_Record : public Record
|
class PTR_Record : public Record
|
||||||
@@ -225,7 +247,7 @@ public:
|
|||||||
std::string value;
|
std::string value;
|
||||||
Record * clone() { return new PTR_Record(*this); }
|
Record * clone() { return new PTR_Record(*this); }
|
||||||
~PTR_Record() {}
|
~PTR_Record() {}
|
||||||
size_t parseFromBuffer(char *buf, size_t offset, size_t maxlen)
|
size_t parseFromBuffer(const char *buf, size_t offset, size_t maxlen)
|
||||||
{
|
{
|
||||||
return Factory::parseDomainName(value, buf, offset, maxlen);
|
return Factory::parseDomainName(value, buf, offset, maxlen);
|
||||||
}
|
}
|
||||||
@@ -237,7 +259,7 @@ public:
|
|||||||
std::string value;
|
std::string value;
|
||||||
Record * clone() { return new CNAME_Record(*this); }
|
Record * clone() { return new CNAME_Record(*this); }
|
||||||
~CNAME_Record() {}
|
~CNAME_Record() {}
|
||||||
size_t parseFromBuffer(char *buf, size_t offset, size_t maxlen)
|
size_t parseFromBuffer(const char *buf, size_t offset, size_t maxlen)
|
||||||
{
|
{
|
||||||
return Factory::parseDomainName(value, buf, offset, maxlen);
|
return Factory::parseDomainName(value, buf, offset, maxlen);
|
||||||
}
|
}
|
||||||
@@ -250,7 +272,7 @@ public:
|
|||||||
u16 record_type;
|
u16 record_type;
|
||||||
u16 record_class;
|
u16 record_class;
|
||||||
|
|
||||||
size_t parseFromBuffer(char *buf, size_t offset, size_t maxlen);
|
size_t parseFromBuffer(const char *buf, size_t offset, size_t maxlen);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Answer
|
class Answer
|
||||||
@@ -270,7 +292,7 @@ public:
|
|||||||
Record * record;
|
Record * record;
|
||||||
|
|
||||||
// Populate the object reading from buffer and returns "consumed" bytes
|
// Populate the object reading from buffer and returns "consumed" bytes
|
||||||
size_t parseFromBuffer(char * buf, size_t offset, size_t maxlen);
|
size_t parseFromBuffer(const char *buf, size_t offset, size_t maxlen);
|
||||||
Answer& operator=(const Answer &r);
|
Answer& operator=(const Answer &r);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -284,7 +306,7 @@ public:
|
|||||||
void removeFlags(FLAGS fl){ flags &= ~fl; }
|
void removeFlags(FLAGS fl){ flags &= ~fl; }
|
||||||
void resetFlags() { flags = 0; }
|
void resetFlags() { flags = 0; }
|
||||||
size_t writeToBuffer(char *buf, size_t maxlen);
|
size_t writeToBuffer(char *buf, size_t maxlen);
|
||||||
size_t parseFromBuffer(char *buf, size_t maxlen);
|
size_t parseFromBuffer(const char *buf, size_t maxlen);
|
||||||
|
|
||||||
u16 id;
|
u16 id;
|
||||||
u16 flags;
|
u16 flags;
|
||||||
|
|||||||
@@ -126,6 +126,9 @@
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
std::cout << "Testing nmap_dns" << std::endl;
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
std::string target = "scanme.nmap.org";
|
std::string target = "scanme.nmap.org";
|
||||||
DNS::RECORD_TYPE rt = DNS::A;
|
DNS::RECORD_TYPE rt = DNS::A;
|
||||||
const size_t buflen = 1500;
|
const size_t buflen = 1500;
|
||||||
@@ -135,5 +138,120 @@ int main()
|
|||||||
DNS::Packet p;
|
DNS::Packet p;
|
||||||
size_t plen = p.parseFromBuffer(buf, buflen);
|
size_t plen = p.parseFromBuffer(buf, buflen);
|
||||||
|
|
||||||
return (reqlen - plen); // 0 means ok
|
if (reqlen != plen)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: plen doesn't match reqplen" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
DNS::Query * q = &*p.queries.begin();
|
||||||
|
if ( q->name != target )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: q.name doesn't match target" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( q->record_class != DNS::IN )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: q.record_class doesn't match IN" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( q->record_type != rt )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: q.record_type doesn't match rt" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a possible answere for an A query for scanme.nmap.org
|
||||||
|
const char ipp[] = "45.33.32.156";
|
||||||
|
const size_t answere_len = 49;
|
||||||
|
u8 answere_buf[] = { 0x92, 0xdc, // Trsnsaction ID
|
||||||
|
0x81, 0x80, // Flags
|
||||||
|
0x00, 0x01, // Questions count
|
||||||
|
0x00, 0x01, // Answers RRs count
|
||||||
|
0x00, 0x00, // Authorities RRs count
|
||||||
|
0x00, 0x00, // Additionals RRs count
|
||||||
|
0x06, // Label lenght <-- [12]
|
||||||
|
0x73, 0x63, 0x61, 0x6e, 0x6d, 0x65, // "scanme"
|
||||||
|
0x04, // Label lenght
|
||||||
|
0x6e, 0x6d, 0x61, 0x70, // "nmap"
|
||||||
|
0x03, // Label lenght
|
||||||
|
0x6f, 0x72, 0x67, // "org"
|
||||||
|
0x00, // Name terminator
|
||||||
|
0x00, 0x01, // A
|
||||||
|
0x00, 0x01, // IN
|
||||||
|
0xc0, 0x0c, // Compressed name pointer to offset 12
|
||||||
|
0x00, 0x01, // A
|
||||||
|
0x00, 0x01, // IN
|
||||||
|
0x00, 0x00, 0x0e, 0x0f, // TTL 3599
|
||||||
|
0x00, 0x04, // Record Lenght
|
||||||
|
0x2d, 0x21, 0x20, 0x9c }; // 45.33.32.156
|
||||||
|
|
||||||
|
plen = p.parseFromBuffer((char*)answere_buf, 49);
|
||||||
|
|
||||||
|
if (answere_len != plen)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: plen doesn't match answere_len " << plen << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = &*p.queries.begin();
|
||||||
|
if ( q->name != target )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: q.name doesn't match target" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( q->record_class != DNS::IN )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: q.record_class doesn't match IN" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( q->record_type != rt )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: q.record_type doesn't match rt" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
DNS::Answer * a = &*p.answers.begin();
|
||||||
|
if ( a->name != target )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: a.name doesn't match target" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( a->record_class != DNS::IN )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: a.record_class doesn't match IN" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( a->record_type != DNS::A )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: a.record_type doesn't match rt" << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->ttl != 3599 )
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: a.ttl doesn't match 3599 " << a->ttl << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
DNS::A_Record * ar = static_cast<DNS::A_Record *>(a->record);
|
||||||
|
char ar_ipp[INET6_ADDRSTRLEN];
|
||||||
|
sockaddr_storage_iptop(&ar->value, ar_ipp);
|
||||||
|
if(strcmp(ipp, ar_ipp))
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: ar_ipp doesn't match ipp " << std::endl;
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret) std::cout << "Testing nmap_dns finished with errors" << std::endl;
|
||||||
|
else std::cout << "Testing nmap_dns finished without errors" << std::endl;
|
||||||
|
|
||||||
|
return ret; // 0 means ok
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user