Skip to content

Commit

Permalink
Implemented more testing fixed some subtle bug thanks to it
Browse files Browse the repository at this point in the history
  • Loading branch information
G10h4ck committed Jul 30, 2015
1 parent a44030a commit 94e8a7a
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 21 deletions.
5 changes: 4 additions & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ release-rpms:
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:
rm -f dependencies.mk
Expand Down Expand Up @@ -300,6 +300,9 @@ nmap-update/default_channel.h: nmap.h
tests/check_dns: $(OBJS)
$(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
# location of the Python interpreter they were built with (something
# like #!/usr/bin/python2.4). This is the wrong thing to do when
Expand Down
27 changes: 17 additions & 10 deletions nmap_dns.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1477,29 +1477,31 @@ size_t DNS::Factory::putDomainName(const std::string &name, char *buf, size_t of

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

Expand Down Expand Up @@ -1537,7 +1539,7 @@ size_t DNS::Factory::parseDomainName(std::string &name, char *buf, size_t offset
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;

Expand All @@ -1552,7 +1554,7 @@ size_t DNS::Query::parseFromBuffer(char *buf, size_t offset, size_t maxlen)
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;

Expand All @@ -1570,21 +1572,26 @@ size_t DNS::Answer::parseFromBuffer(char * buf, size_t offset, size_t maxlen)

switch(record_type)
{
case A:
{
record = new A_Record();
break;
}
case CNAME:
{
record = new CNAME_Record();
DNS_CHECK_ACCUMLATE(ret, tmp, record->parseFromBuffer(buf, offset+ret, maxlen));
break;
}
case PTR:
{
record = new PTR_Record();
DNS_CHECK_ACCUMLATE(ret, tmp, record->parseFromBuffer(buf, offset+ret, maxlen));
break;
}
default:
return 0;
}

DNS_CHECK_ACCUMLATE(ret, tmp, record->parseFromBuffer(buf, offset+ret, maxlen));
}

return ret;
Expand All @@ -1600,7 +1607,7 @@ DNS::Answer& DNS::Answer::operator=(const Answer &r)
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;

Expand Down
40 changes: 31 additions & 9 deletions nmap_dns.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class Target;
#include <algorithm>
#include <sstream>


namespace DNS
{

Expand Down Expand Up @@ -206,17 +207,38 @@ class Factory
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 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 parseUnsignedInt(u32 &num, 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 parseUnsignedShort(u16 &num, const 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, const char *buf, size_t offset, size_t maxlen);
};

class Record
{
public:
virtual Record * clone() = 0;
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
Expand All @@ -225,7 +247,7 @@ class PTR_Record : public Record
std::string value;
Record * clone() { return new PTR_Record(*this); }
~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);
}
Expand All @@ -237,7 +259,7 @@ class CNAME_Record : public Record
std::string value;
Record * clone() { return new CNAME_Record(*this); }
~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);
}
Expand All @@ -250,7 +272,7 @@ class Query
u16 record_type;
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
Expand All @@ -270,7 +292,7 @@ class Answer
Record * record;

// 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);
};

Expand All @@ -284,7 +306,7 @@ class Packet
void removeFlags(FLAGS fl){ flags &= ~fl; }
void resetFlags() { flags = 0; }
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 flags;
Expand Down
120 changes: 119 additions & 1 deletion tests/nmap_dns_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@

int main()
{
std::cout << "Testing nmap_dns" << std::endl;

int ret = 0;
std::string target = "scanme.nmap.org";
DNS::RECORD_TYPE rt = DNS::A;
const size_t buflen = 1500;
Expand All @@ -135,5 +138,120 @@ int main()
DNS::Packet p;
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
}

0 comments on commit 94e8a7a

Please sign in to comment.