Commit 489ef1ad authored by Stephen Morris's avatar Stephen Morris

[trac899] Merge branch 'master' into trac899

Conflicts:
	src/bin/resolver/tests/Makefile.am
	src/lib/config/tests/Makefile.am
	src/lib/log/tests/Makefile.am
	src/lib/resolve/tests/Makefile.am
	src/lib/server_common/tests/Makefile.am
	tests/tools/badpacket/tests/Makefile.am
parents c24dd6f8 e402f8d4
245. [func] vorner
Authoritative server can now sign the answers using TSIG
(configured in tsig_keys/keys, list of strings like
"name:<base64-secret>:sha1-hmac"). It doesn't use them for
ACL yet, only verifies them and signs if the request is signed.
(Trac875, git fe5e7003544e4e8f18efa7b466a65f336d8c8e4d)
244. [func] stephen
In unit tests, allow the choice of whether unhandled exceptions are
caught in the unit test program (and details printed) or allowed to
propagate to the default exception handler. See the bind10-dev thread
https://lists.isc.org/pipermail/bind10-dev/2011-January/001867.html
for more details.
(Trac #542, git 1aa773d84cd6431aa1483eb34a7f4204949a610f)
243. [func]* feng
Add optional hmac algorithm SHA224/384/812.
(Trac#782, git 77d792c9d7c1a3f95d3e6a8b721ac79002cd7db1)
bind10-devel-20110519 released on May 19, 2011
242. [func] jinmei
xfrin: added support for TSIG verify. This change completes TSIG
support in b10-xfrin.
......@@ -13,17 +34,19 @@
Updated configuration options to Xfrin, so that you can specify
a master address, port, and TSIG key per zone. Still only one per
zone at this point, and TSIG keys are (currently) only specified
by their full string representation.
by their full string representation. This replaces the
Xfrin/master_addr, Xfrin/master_port, and short-lived
Xfrin/tsig_key configurations with a Xfrin/zones list.
(Trac #811, git 88504d121c5e08fff947b92e698a54d24d14c375)
239. [bug] jerry
src/bin/xfrout: If a zone doesn't have notify slaves(only has
src/bin/xfrout: If a zone doesn't have notify slaves (only has
one apex ns record - the primary master name server) will cause
b10-xfrout uses 100% of CPU.
(Trac #684, git d11b5e89203a5340d4e5ca51c4c02db17c33dc1f)
238. [func] zhang likun
Implement the simplest forwarder, which pass everything throught
Implement the simplest forwarder, which pass everything through
except QID, port number. The response will not be cached.
(Trac #598_new, git 8e28187a582820857ef2dae9b13637a3881f13ba)
......@@ -76,7 +99,7 @@
(Trac #900, git b395258c708b49a5da8d0cffcb48d83294354ba3)
231. [func]* vorner
The logging interface changed slightly. We use
The logging interface changed slightly. We use
logger.foo(MESSAGE_ID).arg(bar); instead of logger.foo(MESSAGE_ID,
bar); internally. The message definitions use '%1,%2,...'
instead of '%s,%d', which allows us to cope better with
......@@ -118,14 +141,14 @@
(Trac #781, git 9df42279a47eb617f586144dce8cce680598558a)
225. [func] naokikambe
Added the HTTP/XML interface(b10-stats-httpd) to the
Added the HTTP/XML interface (b10-stats-httpd) to the
statistics feature in BIND 10. b10-stats-httpd is a standalone
HTTP server and it requests statistics data to the stats
daemon(b10-stats) and sends it to HTTP clients in XML
daemon (b10-stats) and sends it to HTTP clients in XML
format. Items of the data collected via b10-stats-httpd
are almost equivalent to ones which are collected via
bindctl. Since it also can send XSL(Extensible Stylessheet
Language) document and XSD(XML Schema definition) document,
bindctl. Since it also can send XSL (Extensible Stylesheet
Language) document and XSD (XML Schema definition) document,
XML document is human-friendly to view through web browsers
and its data types are strictly defined.
(Trac #547, git 1cbd51919237a6e65983be46e4f5a63d1877b1d3)
......@@ -144,11 +167,13 @@
reconfigure them.
(Trac #775, git 572ac2cf62e18f7eb69d670b890e2a3443bfd6e7)
222. [bug] jerry
src/lib/zonemgr: Fix a bug that xfrin not checking for new copy of
zone on startup. Imposes some random jitters to avoid many zones
need to do refresh at the same time.
(Trac #387, svn 9140fab9bab5f6502bd15d391fd51ac078b0b89b)
222. [bug]* jerry
src/lib/zonemgr: Fix a bug that xfrin not checking for new
copy of zone on startup. Imposes some random jitters to
avoid many zones need to do refresh at the same time. This
removed the Zonemgr/jitter_scope setting and introduced
Zonemgr/refresh_jitter and Zonemgr/reload_jitter.
(Trac #387, git 1241ddcffa16285d0a7bb01d6a8526e19fbb70cb)
221. [func]* jerry
src/lib/util: Create C++ utility library.
......
......@@ -19,7 +19,9 @@ backends), b10-resolver recursive or forwarding DNS server, b10-cmdctl
remote control daemon, b10-cfgmgr configuration manager, b10-xfrin
AXFR inbound service, b10-xfrout outgoing AXFR service, b10-zonemgr
secondary manager, b10-stats statistics collection and reporting
daemon, and a new libdns++ library for C++ with a python wrapper.
daemon, b10-stats-httpd for HTTP access to XML-formatted stats,
b10-host DNS lookup utility, and a new libdns++ library for C++
with a python wrapper.
Documentation is included and also available via the BIND 10
website at http://bind10.isc.org/
......
......@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.59])
AC_INIT(bind10-devel, 20110322, bind10-dev@isc.org)
AC_INIT(bind10-devel, 20110519, bind10-dev@isc.org)
AC_CONFIG_SRCDIR(README)
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([config.h])
......@@ -824,7 +824,6 @@ AC_CONFIG_FILES([Makefile
src/lib/server_common/tests/Makefile
src/lib/util/Makefile
src/lib/util/io/Makefile
src/lib/util/io/tests/Makefile
src/lib/util/unittests/Makefile
src/lib/util/pyunittests/Makefile
src/lib/util/tests/Makefile
......
This diff is collapsed.
......@@ -79,12 +79,24 @@
3.1 is the minimum version which will work.
</para>
<note><para>
<para>
BIND 10 uses the Botan crypto library for C++. It requires
at least Botan version 1.8. To build BIND 10, install the
Botan libraries and development include headers.
</para>
<!--
TODO
Debian and Ubuntu:
libgmp3-dev and libbz2-dev required for botan too
-->
<para>
The authoritative server requires SQLite 3.3.9 or newer.
The <command>b10-xfrin</command>, <command>b10-xfrout</command>,
and <command>b10-zonemgr</command> modules require the
libpython3 library and the Python _sqlite3.so module.
</para></note>
</para>
<!-- TODO: this will change ... -->
<!-- TODO: list where to get these from -->
......
......@@ -51,7 +51,7 @@ b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.la
b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
b10_auth_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
b10_auth_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
b10_auth_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
b10_auth_LDADD += $(top_builddir)/src/lib/log/liblog.la
b10_auth_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
b10_auth_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
b10_auth_LDADD += $(SQLITE_LIBS)
......
......@@ -60,6 +60,15 @@ private:
set<string> configured_sources_;
};
/// A derived \c AuthConfigParser for the version value
/// (which is not used at this moment)
class VersionConfig : public AuthConfigParser {
public:
VersionConfig() {}
virtual void build(ConstElementPtr) {};
virtual void commit() {};
};
void
DatasourcesConfig::build(ConstElementPtr config_value) {
BOOST_FOREACH(ConstElementPtr datasrc_elem, config_value->listValue()) {
......@@ -293,6 +302,11 @@ createAuthConfigParser(AuthSrv& server, const std::string& config_id,
// we may introduce dynamic registration of configuration parsers,
// and then this test can be done in a cleaner and safer way.
return (new ThrowerCommitConfig());
} else if (config_id == "version") {
// Currently, the version identifier is ignored, but it should
// later be used to mark backwards incompatible changes in the
// config data
return (new VersionConfig());
} else {
isc_throw(AuthConfigError, "Unknown configuration identifier: " <<
config_id);
......
......@@ -20,6 +20,7 @@
#include <cassert>
#include <iostream>
#include <vector>
#include <memory>
#include <boost/bind.hpp>
......@@ -43,6 +44,7 @@
#include <dns/rrset.h>
#include <dns/rrttl.h>
#include <dns/message.h>
#include <dns/tsig.h>
#include <datasrc/query.h>
#include <datasrc/data_source.h>
......@@ -73,6 +75,7 @@ using namespace isc::xfr;
using namespace isc::asiolink;
using namespace isc::asiodns;
using namespace isc::server_common::portconfig;
using boost::shared_ptr;
class AuthSrvImpl {
private:
......@@ -85,11 +88,14 @@ public:
isc::data::ConstElementPtr setDbFile(isc::data::ConstElementPtr config);
bool processNormalQuery(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer);
OutputBufferPtr buffer,
auto_ptr<TSIGContext> tsig_context);
bool processAxfrQuery(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer);
OutputBufferPtr buffer,
auto_ptr<TSIGContext> tsig_context);
bool processNotify(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer);
OutputBufferPtr buffer,
auto_ptr<TSIGContext> tsig_context);
IOService io_service_;
......@@ -116,6 +122,9 @@ public:
/// Addresses we listen on
AddressList listen_addresses_;
/// The TSIG keyring
const shared_ptr<TSIGKeyRing>* keyring_;
private:
std::string db_file_;
......@@ -139,6 +148,7 @@ AuthSrvImpl::AuthSrvImpl(const bool use_cache,
memory_datasrc_class_(RRClass::IN()),
statistics_timer_(io_service_),
counters_(verbose_mode_),
keyring_(NULL),
xfrout_connected_(false),
xfrout_client_(xfrout_client)
{
......@@ -241,7 +251,9 @@ public:
void
makeErrorMessage(MessagePtr message, OutputBufferPtr buffer,
const Rcode& rcode, const bool verbose_mode)
const Rcode& rcode, const bool verbose_mode,
std::auto_ptr<TSIGContext> tsig_context =
std::auto_ptr<TSIGContext>())
{
// extract the parameters that should be kept.
// XXX: with the current implementation, it's not easy to set EDNS0
......@@ -272,7 +284,11 @@ makeErrorMessage(MessagePtr message, OutputBufferPtr buffer,
message->setRcode(rcode);
MessageRenderer renderer(*buffer);
message->toWire(renderer);
if (tsig_context.get() != NULL) {
message->toWire(renderer, *tsig_context);
} else {
message->toWire(renderer);
}
if (verbose_mode) {
cerr << "[b10-auth] sending an error response (" <<
......@@ -446,29 +462,51 @@ AuthSrv::processMessage(const IOMessage& io_message, MessagePtr message,
}
// Perform further protocol-level validation.
// TSIG first
// If this is set to something, we know we need to answer with TSIG as well
std::auto_ptr<TSIGContext> tsig_context;
const TSIGRecord* tsig_record(message->getTSIGRecord());
TSIGError tsig_error(TSIGError::NOERROR());
// Do we do TSIG?
// The keyring can be null if we're in test
if (impl_->keyring_ != NULL && tsig_record != NULL) {
tsig_context.reset(new TSIGContext(tsig_record->getName(),
tsig_record->getRdata().
getAlgorithm(),
**impl_->keyring_));
tsig_error = tsig_context->verify(tsig_record, io_message.getData(),
io_message.getDataSize());
}
bool sendAnswer = true;
if (message->getOpcode() == Opcode::NOTIFY()) {
sendAnswer = impl_->processNotify(io_message, message, buffer);
if (tsig_error != TSIGError::NOERROR()) {
makeErrorMessage(message, buffer, tsig_error.toRcode(),
impl_->verbose_mode_, tsig_context);
} else if (message->getOpcode() == Opcode::NOTIFY()) {
sendAnswer = impl_->processNotify(io_message, message, buffer,
tsig_context);
} else if (message->getOpcode() != Opcode::QUERY()) {
if (impl_->verbose_mode_) {
cerr << "[b10-auth] unsupported opcode" << endl;
}
makeErrorMessage(message, buffer, Rcode::NOTIMP(),
impl_->verbose_mode_);
impl_->verbose_mode_, tsig_context);
} else if (message->getRRCount(Message::SECTION_QUESTION) != 1) {
makeErrorMessage(message, buffer, Rcode::FORMERR(),
impl_->verbose_mode_);
impl_->verbose_mode_, tsig_context);
} else {
ConstQuestionPtr question = *message->beginQuestion();
const RRType &qtype = question->getType();
if (qtype == RRType::AXFR()) {
sendAnswer = impl_->processAxfrQuery(io_message, message, buffer);
sendAnswer = impl_->processAxfrQuery(io_message, message, buffer,
tsig_context);
} else if (qtype == RRType::IXFR()) {
makeErrorMessage(message, buffer, Rcode::NOTIMP(),
impl_->verbose_mode_);
impl_->verbose_mode_, tsig_context);
} else {
sendAnswer = impl_->processNormalQuery(io_message, message, buffer);
sendAnswer = impl_->processNormalQuery(io_message, message, buffer,
tsig_context);
}
}
......@@ -477,7 +515,8 @@ AuthSrv::processMessage(const IOMessage& io_message, MessagePtr message,
bool
AuthSrvImpl::processNormalQuery(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer)
OutputBufferPtr buffer,
auto_ptr<TSIGContext> tsig_context)
{
ConstEDNSPtr remote_edns = message->getEDNS();
const bool dnssec_ok = remote_edns && remote_edns->getDNSSECAwareness();
......@@ -523,7 +562,11 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, MessagePtr message,
const bool udp_buffer =
(io_message.getSocket().getProtocol() == IPPROTO_UDP);
renderer.setLengthLimit(udp_buffer ? remote_bufsize : 65535);
message->toWire(renderer);
if (tsig_context.get() != NULL) {
message->toWire(renderer, *tsig_context);
} else {
message->toWire(renderer);
}
if (verbose_mode_) {
cerr << "[b10-auth] sending a response ("
......@@ -536,7 +579,8 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, MessagePtr message,
bool
AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer)
OutputBufferPtr buffer,
auto_ptr<TSIGContext> tsig_context)
{
// Increment query counter.
incCounter(io_message.getSocket().getProtocol());
......@@ -545,7 +589,8 @@ AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, MessagePtr message,
if (verbose_mode_) {
cerr << "[b10-auth] AXFR query over UDP isn't allowed" << endl;
}
makeErrorMessage(message, buffer, Rcode::FORMERR(), verbose_mode_);
makeErrorMessage(message, buffer, Rcode::FORMERR(), verbose_mode_,
tsig_context);
return (true);
}
......@@ -572,7 +617,8 @@ AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, MessagePtr message,
cerr << "[b10-auth] Error in handling XFR request: " << err.what()
<< endl;
}
makeErrorMessage(message, buffer, Rcode::SERVFAIL(), verbose_mode_);
makeErrorMessage(message, buffer, Rcode::SERVFAIL(), verbose_mode_,
tsig_context);
return (true);
}
......@@ -581,7 +627,8 @@ AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, MessagePtr message,
bool
AuthSrvImpl::processNotify(const IOMessage& io_message, MessagePtr message,
OutputBufferPtr buffer)
OutputBufferPtr buffer,
std::auto_ptr<TSIGContext> tsig_context)
{
// The incoming notify must contain exactly one question for SOA of the
// zone name.
......@@ -590,7 +637,8 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, MessagePtr message,
cerr << "[b10-auth] invalid number of questions in notify: "
<< message->getRRCount(Message::SECTION_QUESTION) << endl;
}
makeErrorMessage(message, buffer, Rcode::FORMERR(), verbose_mode_);
makeErrorMessage(message, buffer, Rcode::FORMERR(), verbose_mode_,
tsig_context);
return (true);
}
ConstQuestionPtr question = *message->beginQuestion();
......@@ -599,7 +647,8 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, MessagePtr message,
cerr << "[b10-auth] invalid question RR type in notify: "
<< question->getType() << endl;
}
makeErrorMessage(message, buffer, Rcode::FORMERR(), verbose_mode_);
makeErrorMessage(message, buffer, Rcode::FORMERR(), verbose_mode_,
tsig_context);
return (true);
}
......@@ -662,7 +711,11 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, MessagePtr message,
message->setRcode(Rcode::NOERROR());
MessageRenderer renderer(*buffer);
message->toWire(renderer);
if (tsig_context.get() != NULL) {
message->toWire(renderer, *tsig_context);
} else {
message->toWire(renderer);
}
return (true);
}
......@@ -772,3 +825,8 @@ void
AuthSrv::setDNSService(isc::asiodns::DNSService& dnss) {
dnss_ = &dnss;
}
void
AuthSrv::setTSIGKeyRing(const shared_ptr<TSIGKeyRing>* keyring) {
impl_->keyring_ = keyring;
}
......@@ -44,6 +44,9 @@ class MemoryDataSrc;
namespace xfr {
class AbstractXfroutClient;
}
namespace dns {
class TSIGKeyRing;
}
}
......@@ -374,6 +377,14 @@ public:
/// \brief Assign an ASIO DNS Service queue to this Auth object
void setDNSService(isc::asiodns::DNSService& dnss);
/// \brief Sets the keyring used for verifying and signing
///
/// The parameter is pointer to shared pointer, because the automatic
/// reloading routines of tsig keys replace the actual keyring object.
/// It is expected the pointer will point to some statically-allocated
/// object, it doesn't take ownership of it.
void setTSIGKeyRing(const boost::shared_ptr<isc::dns::TSIGKeyRing>*
keyring);
private:
AuthSrvImpl* impl_;
......
......@@ -47,6 +47,7 @@
#include <asiodns/asiodns.h>
#include <asiolink/asiolink.h>
#include <log/dummylog.h>
#include <server_common/keyring.h>
using namespace std;
using namespace isc::data;
......@@ -152,9 +153,14 @@ main(int argc, char* argv[]) {
cc_session = new Session(io_service.get_io_service());
cout << "[b10-auth] Configuration session channel created." << endl;
// We delay starting listening to new commands/config just before we
// go into the main loop to avoid confusion due to mixture of
// synchronous and asynchronous operations (this would happen in
// initializing TSIG keys below). Until then all operations on the
// CC session will take place synchronously.
config_session = new ModuleCCSession(specfile, *cc_session,
my_config_handler,
my_command_handler);
my_command_handler, false);
cout << "[b10-auth] Configuration channel established." << endl;
xfrin_session = new Session(io_service.get_io_service());
......@@ -190,6 +196,14 @@ main(int argc, char* argv[]) {
changeUser(uid);
}
cout << "[b10-auth] Loading TSIG keys" << endl;
isc::server_common::initKeyring(*config_session);
auth_server->setTSIGKeyRing(&isc::server_common::keyring);
// Now start asynchronous read.
config_session->start();
cout << "[b10-auth] Configuration channel started." << endl;
cout << "[b10-auth] Server started." << endl;
io_service.run();
......
......@@ -52,6 +52,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
run_unittests_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
endif
noinst_PROGRAMS = $(TESTS)
......@@ -16,6 +16,8 @@
#include <vector>
#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>
#include <dns/message.h>
......@@ -25,8 +27,10 @@
#include <dns/rrtype.h>
#include <dns/rrttl.h>
#include <dns/rdataclass.h>
#include <dns/tsig.h>
#include <server_common/portconfig.h>
#include <server_common/keyring.h>
#include <datasrc/memory_datasrc.h>
#include <auth/auth_srv.h>
......@@ -50,6 +54,7 @@ using namespace isc::asiolink;
using namespace isc::testutils;
using namespace isc::server_common::portconfig;
using isc::UnitTestUtil;
using boost::shared_ptr;
namespace {
const char* const CONFIG_TESTDB =
......@@ -242,6 +247,139 @@ TEST_F(AuthSrvTest, AXFRSuccess) {
EXPECT_TRUE(xfrout.isConnected());
}
// Try giving the server a TSIG signed request and see it can anwer signed as
// well
TEST_F(AuthSrvTest, TSIGSigned) {
// Prepare key, the client message, etc
const TSIGKey key("key:c2VjcmV0Cg==:hmac-sha1");
TSIGContext context(key);
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("version.bind"), RRClass::CH(), RRType::TXT());
createRequestPacket(request_message, IPPROTO_UDP, &context);
// Run the message through the server
shared_ptr<TSIGKeyRing> keyring(new TSIGKeyRing);
keyring->add(key);
server.setTSIGKeyRing(&keyring);
server.processMessage(*io_message, parse_message, response_obuffer,
&dnsserv);
// What did we get?
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 1, 0);
// We need to parse the message ourself, or getTSIGRecord won't work
InputBuffer ib(response_obuffer->getData(), response_obuffer->getLength());
Message m(Message::PARSE);
m.fromWire(ib);
const TSIGRecord* tsig = m.getTSIGRecord();
ASSERT_TRUE(tsig != NULL) << "Missing TSIG signature";
TSIGError error(context.verify(tsig, response_obuffer->getData(),
response_obuffer->getLength()));
EXPECT_EQ(TSIGError::NOERROR(), error) <<
"The server signed the response, but it doesn't seem to be valid";
}
// Give the server a signed request, but don't give it the key. It will
// not be able to verify it, returning BADKEY
TEST_F(AuthSrvTest, TSIGSignedBadKey) {
TSIGKey key("key:c2VjcmV0Cg==:hmac-sha1");
TSIGContext context(key);
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("version.bind"), RRClass::CH(), RRType::TXT());
createRequestPacket(request_message, IPPROTO_UDP, &context);
// Process the message, but use a different key there
shared_ptr<TSIGKeyRing> keyring(new TSIGKeyRing);
server.setTSIGKeyRing(&keyring);
server.processMessage(*io_message, parse_message, response_obuffer,
&dnsserv);
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, TSIGError::BAD_KEY().toRcode(),
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
// We need to parse the message ourself, or getTSIGRecord won't work
InputBuffer ib(response_obuffer->getData(), response_obuffer->getLength());
Message m(Message::PARSE);
m.fromWire(ib);
const TSIGRecord* tsig = m.getTSIGRecord();
ASSERT_TRUE(tsig != NULL) <<
"Missing TSIG signature (we should have one even at error)";
EXPECT_EQ(TSIGError::BAD_KEY_CODE, tsig->getRdata().getError());
EXPECT_EQ(0, tsig->getRdata().getMACSize()) <<
"It should be unsigned with this error";
}
// Give the server a signed request, but signed by a different key
// (with the same name). It should return BADSIG
TEST_F(AuthSrvTest, TSIGBadSig) {
TSIGKey key("key:c2VjcmV0Cg==:hmac-sha1");
TSIGContext context(key);
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("version.bind"), RRClass::CH(), RRType::TXT());
createRequestPacket(request_message, IPPROTO_UDP, &context);
// Process the message, but use a different key there
shared_ptr<TSIGKeyRing> keyring(new TSIGKeyRing);
keyring->add(TSIGKey("key:QkFECg==:hmac-sha1"));
server.setTSIGKeyRing(&keyring);
server.processMessage(*io_message, parse_message, response_obuffer,
&dnsserv);
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, TSIGError::BAD_SIG().toRcode(),
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
// We need to parse the message ourself, or getTSIGRecord won't work
InputBuffer ib(response_obuffer->getData(), response_obuffer->getLength());
Message m(Message::PARSE);