Commit e935dae5 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[trac117] shared the "from wire" bitmap operation between NSEC and NSEC3

this fixed various bugs in the NSEC3 implementation.
also added tests for NSEC3.
parent 355e2efd
......@@ -88,6 +88,8 @@ libdns___la_SOURCES += tsigkey.h tsigkey.cc
nodist_libdns___la_SOURCES = rdataclass.cc rrclass.h rrtype.h
nodist_libdns___la_SOURCES += rrparamregistry.cc
nodist_libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
nodist_libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
rrclass.h: rrclass-placeholder.h
rrtype.h: rrtype-placeholder.h
......@@ -117,5 +119,6 @@ libdns___include_HEADERS = \
tsigkey.h
# Purposely not installing these headers:
# util/*.h: used only internally, and not actually DNS specific
# rdata/*/detail/*.h: these are internal use only
# rrclass-placeholder.h
# rrtype-placeholder.h
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <stdint.h>
#include <vector>
#include <dns/exceptions.h>
using namespace std;
namespace isc {
namespace dns {
namespace rdata {
namespace generic {
namespace detail {
namespace nsec {
void
buildRRTypeBitmap(const char* const rrtype_name,
const size_t total_len, vector<uint8_t>& typebits)
{
int len = 0;
bool first = true;
unsigned int block, lastblock = 0;
for (int i = 0; i < total_len; i += len) {
if (i + 2 > total_len) {
isc_throw(DNSMessageFORMERR, rrtype_name <<
" RDATA from wire: incomplete bit map field");
}
block = typebits[i];
len = typebits[i + 1];
// Check that bitmap window blocks are in the correct order.
if (!first && block <= lastblock) {
isc_throw(DNSMessageFORMERR, rrtype_name <<
" RDATA from wire: Disordered window blocks found: "
<< lastblock << " then " << block);
}
// Check for legal length
if (len < 1 || len > 32) {
isc_throw(DNSMessageFORMERR, rrtype_name <<
" RDATA from wire: Invalid bitmap length: " << len);
}
// Check for overflow.
i += 2;
if (i + len > total_len) {
isc_throw(DNSMessageFORMERR, rrtype_name <<
" RDATA from wire: bitmap length too large: " << len);
}
// The last octet of the bitmap must be non zero.
if (typebits[i + len - 1] == 0) {
isc_throw(DNSMessageFORMERR, rrtype_name <<
" RDATA from wire: bitmap ending an all-zero byte");
}
lastblock = block;
first = false;
}
}
}
}
}
}
}
}
/*
* Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdint.h>
#include <vector>
namespace isc {
namespace dns {
namespace rdata {
namespace generic {
namespace detail {
namespace nsec {
void buildRRTypeBitmap(const char* const rrtype_name,
const size_t total_len, std::vector<uint8_t>& typebits);
}
}
}
}
}
}
// Local Variables:
// mode: c++
// End:
......@@ -30,11 +30,13 @@
#include <dns/rrttl.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdata/generic/detail/nsec_bitmap.h>
#include <stdio.h>
#include <time.h>
using namespace std;
using namespace isc::dns::rdata::generic::detail::nsec;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
......@@ -126,17 +128,18 @@ NSEC3::NSEC3(const string& nsec3_str) :
}
NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) {
// NSEC3 RR must have at least 5 octets:
// hash(1), flags(1), iteration(2), saltlen(1)
if (rdata_len < 5) {
isc_throw(InvalidRdataLength, "NSEC3 too short");
}
uint8_t hashalg = buffer.readUint8();
uint8_t flags = buffer.readUint8();
uint16_t iterations = buffer.readUint16();
rdata_len -= 4;
const uint8_t hashalg = buffer.readUint8();
const uint8_t flags = buffer.readUint8();
const uint16_t iterations = buffer.readUint16();
uint8_t saltlen = buffer.readUint8();
--rdata_len;
const uint8_t saltlen = buffer.readUint8();
rdata_len -= 5;
if (rdata_len < saltlen) {
isc_throw(InvalidRdataLength, "NSEC3 salt too short");
......@@ -163,20 +166,7 @@ NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) {
vector<uint8_t> typebits(rdata_len);
buffer.readData(&typebits[0], rdata_len);
int len = 0;
for (int i = 0; i < typebits.size(); i += len) {
if (i + 2 > typebits.size()) {
isc_throw(DNSMessageFORMERR, "Invalid rdata: "
"bad NSEC3 type bitmap");
}
len = typebits[i + 1];
if (len > 31) {
isc_throw(DNSMessageFORMERR, "Invalid rdata: "
"bad NSEC3 type bitmap");
}
i += 2;
}
buildRRTypeBitmap("NSEC3", rdata_len, typebits);
impl_ = new NSEC3Impl(hashalg, flags, iterations, salt, next, typebits);
}
......
......@@ -26,11 +26,13 @@
#include <dns/rrttl.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdata/generic/detail/nsec_bitmap.h>
#include <stdio.h>
#include <time.h>
using namespace std;
using namespace isc::dns::rdata::generic::detail::nsec;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
......@@ -103,43 +105,7 @@ NSEC::NSEC(InputBuffer& buffer, size_t rdata_len) {
vector<uint8_t> typebits(rdata_len);
buffer.readData(&typebits[0], rdata_len);
int len = 0;
bool first = true;
unsigned int block, lastblock = 0;
for (int i = 0; i < rdata_len; i += len) {
if (i + 2 > rdata_len) {
isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: "
"incomplete bit map field");
}
block = typebits[i];
len = typebits[i + 1];
// Check that bitmap window blocks are in the correct order.
if (!first && block <= lastblock) {
isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: Disordered "
"window blocks found: " << lastblock <<
" then " << block);
}
// Check for legal length
if (len < 1 || len > 32) {
isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: Invalid bitmap "
"length: " << len);
}
// Check for overflow.
i += 2;
if (i + len > rdata_len) {
isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: bitmap length "
"too large: " << len);
}
// The last octet of the bitmap must be non zero.
if (typebits[i + len - 1] == 0) {
isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: bitmap ending "
"an all-zero byte");
}
lastblock = block;
first = false;
}
buildRRTypeBitmap("NSEC", rdata_len, typebits);
impl_ = new NSECImpl(nextname, typebits);
}
......
......@@ -95,33 +95,32 @@ TEST_F(Rdata_NSEC3_Test, createFromWire) {
"rdata_nsec3_fromWire2"),
InvalidRdataLength);
// Invalid type bits
// These tests are the same as NSEC tests. See the NSEC cases for
// details.
EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire3"),
DNSMessageFORMERR);
try {
rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire4.wire");
rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire5.wire");
rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire7.wire");
rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire8.wire");
// the following tests currently fail.
rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire6.wire");
rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire9.wire");
rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire10.wire");
} catch (const std::exception& ex) {
cout << "got exception: " << ex.what() << endl;
}
EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire4.wire"),
DNSMessageFORMERR);
EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire5.wire"),
DNSMessageFORMERR);
EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire6.wire"),
DNSMessageFORMERR);
EXPECT_NO_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire7.wire"));
EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire8.wire"),
DNSMessageFORMERR);
EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire9.wire"),
DNSMessageFORMERR);
EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire10.wire"),
DNSMessageFORMERR);
}
TEST_F(Rdata_NSEC3_Test, toWireRenderer) {
......
......@@ -8,6 +8,10 @@ BUILT_SOURCES += rdata_nsec_fromWire4.wire rdata_nsec_fromWire5.wire
BUILT_SOURCES += rdata_nsec_fromWire6.wire rdata_nsec_fromWire7.wire
BUILT_SOURCES += rdata_nsec_fromWire8.wire rdata_nsec_fromWire9.wire
BUILT_SOURCES += rdata_nsec_fromWire10.wire
BUILT_SOURCES += rdata_nsec3_fromWire4.wire rdata_nsec3_fromWire5.wire
BUILT_SOURCES += rdata_nsec3_fromWire6.wire rdata_nsec3_fromWire7.wire
BUILT_SOURCES += rdata_nsec3_fromWire8.wire rdata_nsec3_fromWire9.wire
BUILT_SOURCES += rdata_nsec3_fromWire10.wire
BUILT_SOURCES += rdata_rrsig_fromWire2.wire
BUILT_SOURCES += rdata_soa_toWireUncompressed.wire
BUILT_SOURCES += rdata_txt_fromWire2.wire rdata_txt_fromWire3.wire
......@@ -51,6 +55,10 @@ EXTRA_DIST += rdata_nsec_fromWire4.spec rdata_nsec_fromWire5.spec
EXTRA_DIST += rdata_nsec_fromWire6.spec rdata_nsec_fromWire7.spec
EXTRA_DIST += rdata_nsec_fromWire8.spec rdata_nsec_fromWire9.spec
EXTRA_DIST += rdata_nsec_fromWire10.spec
EXTRA_DIST += rdata_nsec3_fromWire4.spec rdata_nsec3_fromWire5.spec
EXTRA_DIST += rdata_nsec3_fromWire6.spec rdata_nsec3_fromWire7.spec
EXTRA_DIST += rdata_nsec3_fromWire8.spec rdata_nsec3_fromWire9.spec
EXTRA_DIST += rdata_nsec3_fromWire10.spec
EXTRA_DIST += rdata_opt_fromWire rdata_rrsig_fromWire1
EXTRA_DIST += rdata_rrsig_fromWire2.spec
EXTRA_DIST += rdata_soa_fromWire rdata_soa_toWireUncompressed.spec
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment