Commit cc884a66 authored by Evan Hunt's avatar Evan Hunt
Browse files

checkpoint:

 - added code for findCoveringNSEC3()


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1126 e5f2f494-b856-4b98-b285-d166d9295462
parent 5fd4500e
......@@ -20,11 +20,14 @@
#include <boost/foreach.hpp>
#include <dns/base32.h>
#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/rdataclass.h>
#include <dns/rrset.h>
#include <dns/rrsetlist.h>
#include <dns/sha1.h>
#include <cc/data.h>
......@@ -689,5 +692,38 @@ NameMatch::update(const DataSrc& new_source, const Name& container)
}
}
Nsec3Param::Nsec3Param(uint8_t a, uint8_t f, uint16_t i,
std::vector<uint8_t>& s) :
algorithm(a), flags(f), iterations(i), salt(s)
{}
string
Nsec3Param::getHash(const Name& name) const {
OutputBuffer buf(0);
name.toWire(buf);
buf.writeData(&salt[0], salt.size());
uint8_t* in = (uint8_t*) buf.getData();
size_t inlength = buf.getLength();
uint8_t digest[SHA1_HASHSIZE];
int n = 0;
SHA1Context sha;
do {
SHA1Reset(&sha);
SHA1Input(&sha, in, inlength);
SHA1Result(&sha, digest);
in = digest;
inlength = SHA1_HASHSIZE;
} while (n++ < iterations);
vector<uint8_t> result;
for (int i = 0; i < SHA1_HASHSIZE; ++i) {
result.push_back(digest[i]);
}
return (encodeBase32(result));
}
}
}
......@@ -37,6 +37,7 @@ namespace auth {
class NameMatch;
class Query;
class Nsec3Param;
class DataSrc;
typedef boost::shared_ptr<DataSrc> DataSrcPtr;
......@@ -141,6 +142,13 @@ public:
isc::dns::Name& target,
const isc::dns::Name* zonename) const = 0;
// This MUST be implemented by concrete data sources which support
// NSEC3, but is optional for others
virtual Result findCoveringNSEC3(const Query& q,
const Nsec3Param& param,
const isc::dns::Name& qname,
const isc::dns::Name& zonename,
isc::dns::RRsetList& target) const = 0;
};
// Base class for a DNS Data Source
......@@ -205,6 +213,13 @@ public:
const isc::dns::Name& qname,
isc::dns::Name& target,
const isc::dns::Name* zonename) const = 0;
virtual Result findCoveringNSEC3(const Query& q,
const Nsec3Param& param,
const isc::dns::Name& qname,
const isc::dns::Name& zonename,
isc::dns::RRsetList& target) const = 0;
private:
isc::dns::RRClass rrclass;
};
......@@ -278,6 +293,15 @@ public:
return (NOT_IMPLEMENTED);
}
virtual Result findCoveringNSEC3(const Query& q,
const Nsec3Param& param,
const isc::dns::Name& qname,
const isc::dns::Name& zonename,
isc::dns::RRsetList& target) const
{
return (NOT_IMPLEMENTED);
}
private:
std::vector<ConstDataSrcPtr> data_sources;
};
......@@ -300,6 +324,18 @@ private:
const isc::dns::Name qname_;
};
class Nsec3Param {
public:
Nsec3Param(uint8_t a, uint8_t f, uint16_t i, std::vector<uint8_t>& s);
const uint8_t algorithm;
const uint8_t flags;
const uint16_t iterations;
const std::vector<uint8_t>& salt;
std::string getHash(const isc::dns::Name& name) const;
};
}
}
......
......@@ -15,6 +15,7 @@
// $Id$
#include "data_source_sqlite3.h"
#include <dns/rrttl.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
......@@ -123,21 +124,21 @@ Sqlite3DataSrc::findRecords(const Name& name, const RRType& rdtype,
rc = sqlite3_bind_int(query, 1, zone_id);
if (rc != SQLITE_OK) {
throw("Could not bind 1 (record)");
throw("Could not bind 1 (query)");
}
rc = sqlite3_bind_text(query, 2, c_name, -1, SQLITE_STATIC);
if (rc != SQLITE_OK) {
throw("Could not bind 2 (record)");
throw("Could not bind 2 (query)");
}
if (query == q_record) {
rc = sqlite3_bind_text(query, 3, rdtype.toText().c_str(), -1,
SQLITE_STATIC);
if (rc != SQLITE_OK) {
throw("Could not bind 3 (record)");
throw("Could not bind 3 (query)");
}
}
// loop
int target_ttl = -1;
int sig_ttl = -1;
......@@ -365,6 +366,26 @@ Sqlite3DataSrc::setupPreparedStatements(void) {
throw(e);
}
const char* q_nsec3_str = "SELECT rdtype, ttl, rdata FROM nsec3 "
"WHERE zone_id=?1 AND hash == $2";
try {
q_nsec3 = prepare(q_nsec3_str);
} catch (const char* e) {
cout << e << endl << q_nsec3_str << endl;
cout << sqlite3_errmsg(db) << endl;
throw(e);
}
const char* q_prevnsec3_str = "SELECT rdtype, ttl, rdata FROM nsec3 "
"WHERE zone_id=?1 AND hash <= $2 "
"ORDER BY rhash DESC LIMIT 1";
try {
q_prevnsec3 = prepare(q_prevnsec3_str);
} catch (const char* e) {
cout << e << endl << q_prevnsec3_str << endl;
cout << sqlite3_errmsg(db) << endl;
throw(e);
}
}
void
......@@ -392,6 +413,7 @@ Sqlite3DataSrc::checkAndSetupSchema(void) {
"name STRING NOT NULL, "
"rdclass STRING NOT NULL DEFAULT 'IN', "
"dnssec BOOLEAN NOT NULL DEFAULT 0)");
execSetupQuery("CREATE INDEX zones_byname ON zones (name)");
execSetupQuery("CREATE TABLE records ("
"id INTEGER PRIMARY KEY, "
"zone_id INTEGER NOT NULL, "
......@@ -403,7 +425,15 @@ Sqlite3DataSrc::checkAndSetupSchema(void) {
"rdata STRING NOT NULL)");
execSetupQuery("CREATE INDEX records_byname ON records (name)");
execSetupQuery("CREATE INDEX records_byrname ON records (rname)");
execSetupQuery("CREATE INDEX zones_byname ON zones (name)");
execSetupQuery("CREATE TABLE nsec3 ("
"id INTEGER PRIMARY KEY, "
"zone_id INTEGER NOT NULL, "
"hash STRING NOT NULL, "
"owner STRING NOT NULL, "
"ttl INTEGER NOT NULL, "
"rdtype STRING NOT NULL, "
"rdata STRING NOT NULL)");
execSetupQuery("CREATE INDEX nsec3_byhash ON nsec3 (hash)");
setupPreparedStatements();
cout << "Created new file and schema" << endl;
......@@ -420,6 +450,8 @@ Sqlite3DataSrc::Sqlite3DataSrc() {
q_any = NULL;
q_count = NULL;
q_previous = NULL;
q_nsec3 = NULL;
q_prevnsec3 = NULL;
}
Sqlite3DataSrc::~Sqlite3DataSrc() {
......@@ -469,14 +501,14 @@ Sqlite3DataSrc::findPreviousName(const Query& q,
int rc = sqlite3_bind_int(q_previous, 1, zone_id);
if (rc != SQLITE_OK) {
throw ("Could not bind 1 (record)");
throw ("Could not bind 1 (previous)");
}
rc = sqlite3_bind_text(q_previous, 2, qname.reverse().toText().c_str(),
-1, SQLITE_STATIC);
if (rc != SQLITE_OK) {
throw ("Could not bind 2 (record)");
throw ("Could not bind 2 (previous)");
}
rc = sqlite3_step(q_previous);
if (rc != SQLITE_ROW) {
sqlite3_reset(q_previous);
......@@ -489,6 +521,112 @@ Sqlite3DataSrc::findPreviousName(const Query& q,
return (SUCCESS);
}
DataSrc::Result
Sqlite3DataSrc::findCoveringNSEC3(const Query& q,
const Nsec3Param& nsec3param,
const Name& qname,
const Name& zonename,
RRsetList& target) const
{
int zone_id = findClosest(zonename.toText().c_str(), NULL);
if (zone_id < 0) {
return (ERROR);
}
string hashstr = nsec3param.getHash(qname);
sqlite3_reset(q_prevnsec3);
sqlite3_clear_bindings(q_prevnsec3);
int rc = sqlite3_bind_int(q_prevnsec3, 1, zone_id);
if (rc != SQLITE_OK) {
throw ("Could not bind 1 (previous NSEC3)");
}
rc = sqlite3_bind_text(q_prevnsec3, 2, hashstr.c_str(), -1, SQLITE_STATIC);
if (rc != SQLITE_OK) {
throw ("Could not bind 2 (previous NSEC3)");
}
rc = sqlite3_step(q_prevnsec3);
const char* hash;
if (rc == SQLITE_ROW) {
hash = (const char*) sqlite3_column_text(q_prevnsec3, 0);
} else {
// We need to find the final NSEC3 in the chain.
// A valid NSEC3 hash is in base32, which contains no
// letters higher than V, so a search for the previous
// NSEC3 from "W" will always find it.
sqlite3_reset(q_prevnsec3);
rc = sqlite3_bind_text(q_prevnsec3, 2, "W", -1, SQLITE_STATIC);
if (rc != SQLITE_OK) {
throw ("Could not bind 2 (last NSEC3)");
}
rc = sqlite3_step(q_prevnsec3);
if (rc != SQLITE_ROW) {
return (ERROR);
}
hash = (const char*) sqlite3_column_text(q_prevnsec3, 0);
}
sqlite3_reset(q_nsec3);
sqlite3_clear_bindings(q_nsec3);
rc = sqlite3_bind_int(q_nsec3, 1, zone_id);
if (rc != SQLITE_OK) {
throw ("Could not bind 1 (NSEC3)");
}
rc = sqlite3_bind_text(q_nsec3, 2, hash, -1, SQLITE_STATIC);
if (rc != SQLITE_OK) {
throw ("Could not bind 2 (NSEC3)");
}
int target_ttl = -1;
int sig_ttl = -1;
const Name& name(Name(hash).concatenate(zonename));
RRsetPtr rrset(new RRset(name, RRClass::IN(), RRType::NSEC3(), RRTTL(0)));
if (!target[RRType::NSEC3()]) {
target.addRRset(rrset);
}
rc = sqlite3_step(q_nsec3);
while (rc == SQLITE_ROW) {
RRType type((const char*)sqlite3_column_text(q_nsec3, 1));
int ttl = sqlite3_column_int(q_nsec3, 2);
const char* rdata = (const char*)sqlite3_column_text(q_nsec3, 3);
if (type == RRType::NSEC3()) {
rrset->addRdata(createRdata(type, RRClass::IN(), rdata));
if (target_ttl == -1 || target_ttl > ttl) {
target_ttl = ttl;
}
rrset->setTTL(RRTTL(target_ttl));
} else {
RdataPtr rrsig = createRdata(RRType::RRSIG(), RRClass::IN(), rdata);
if (rrset->getRRsig()) {
rrset->getRRsig()->addRdata(rrsig);
} else {
RRsetPtr sigs = RRsetPtr(new RRset(name, RRClass::IN(),
RRType::RRSIG(), RRTTL(0)));
sigs->addRdata(rrsig);
rrset->addRRsig(sigs);
}
}
if (sig_ttl == -1 || sig_ttl > ttl) {
sig_ttl = ttl;
}
rrset->getRRsig()->setTTL(RRTTL(sig_ttl));
rc = sqlite3_step(q_nsec3);
}
sqlite3_reset(q_nsec3);
return (SUCCESS);
}
DataSrc::Result
Sqlite3DataSrc::findRRset(const Query& q,
const Name& qname,
......@@ -608,6 +746,16 @@ Sqlite3DataSrc::close(void) {
q_previous = NULL;
}
if (q_prevnsec3) {
release(q_prevnsec3);
q_prevnsec3 = NULL;
}
if (q_nsec3) {
release(q_nsec3);
q_nsec3 = NULL;
}
sqlite3_close(db);
db = NULL;
......
......@@ -35,6 +35,7 @@ class RRsetList;
namespace auth {
class Query;
class Nsec3Param;
class Sqlite3DataSrc : public DataSrc {
///
......@@ -48,48 +49,54 @@ private:
Sqlite3DataSrc& operator=(const Sqlite3DataSrc& source);
public:
Sqlite3DataSrc();
virtual ~Sqlite3DataSrc();
~Sqlite3DataSrc();
//@}
virtual void findClosestEnclosure(NameMatch& match) const;
virtual Result findRRset(const Query& q,
void findClosestEnclosure(NameMatch& match) const;
Result findRRset(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const;
Result findExactRRset(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const;
Result findAddrs(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const;
Result findReferral(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const;
DataSrc::Result findPreviousName(const Query& q,
const isc::dns::Name& qname,
isc::dns::Name& target,
const isc::dns::Name* zonename) const;
Result findCoveringNSEC3(const Query& q,
const Nsec3Param& param,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const;
virtual Result findExactRRset(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const;
virtual Result findAddrs(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const;
virtual Result findReferral(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const;
virtual DataSrc::Result findPreviousName(const Query& q,
const isc::dns::Name& qname,
isc::dns::Name& target,
const isc::dns::Name* zonename) const;
virtual Result init();
virtual Result close();
const isc::dns::Name& zonename,
isc::dns::RRsetList& target) const;
Result init();
Result close();
private:
enum Mode {
......@@ -126,6 +133,8 @@ private:
sqlite3_stmt *q_any;
sqlite3_stmt *q_count;
sqlite3_stmt *q_previous;
sqlite3_stmt *q_nsec3;
sqlite3_stmt *q_prevnsec3;
};
}
......
......@@ -164,6 +164,14 @@ StaticDataSrc::findPreviousName(const Query& q, const Name& qname,
return (NOT_IMPLEMENTED);
}
DataSrc::Result
StaticDataSrc::findCoveringNSEC3(const Query& q, const Nsec3Param& param,
const Name& qname, const Name& zonename,
RRsetList& target) const
{
return (NOT_IMPLEMENTED);
}
DataSrc::Result
StaticDataSrc::init()
{
......
......@@ -80,6 +80,12 @@ public:
isc::dns::Name& target,
const isc::dns::Name* zonename) const;
Result findCoveringNSEC3(const Query& q,
const Nsec3Param& param,
const isc::dns::Name& qname,
const isc::dns::Name& zonename,
isc::dns::RRsetList& target) const;
Result init();
Result close();
};
......
......@@ -765,5 +765,15 @@ TestDataSrc::findPreviousName(const Query& q,
return (SUCCESS);
}
DataSrc::Result
TestDataSrc::findCoveringNSEC3(const Query& q,
const Nsec3Param& param,
const Name& qname,
const Name& zonename,
RRsetList& target) const
{
return (NOT_IMPLEMENTED);
}
}
}
......@@ -85,6 +85,12 @@ public:
isc::dns::Name& target,
const isc::dns::Name* zonename) const;
Result findCoveringNSEC3(const Query& q,
const Nsec3Param& param,
const isc::dns::Name& qname,
const isc::dns::Name& zonename,
isc::dns::RRsetList& target) const;
Result init() { return (SUCCESS); }
Result close() { return (SUCCESS); }
......
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