1
0
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:
gio
2015-07-30 06:27:35 +00:00
parent a44030ae23
commit 94e8a7acd3
4 changed files with 171 additions and 21 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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
} }