Commit 356ffa38 authored by Shane Kerr's avatar Shane Kerr
Browse files

Merge branch 'master' into trac950

parents 9cc499cb 50f16fdb
257. [bug] y-aharen
Fixed a bug an instance of IntervalTimerImpl may be destructed
while deadline_timer is holding the handler. This fix addresses
occasional failure of IntervalTimerTest.destructIntervalTimer.
(Trac #957, git e59c215e14b5718f62699ec32514453b983ff603)
256. [bug] jerry
src/bin/xfrin: update xfrin to check TSIG before other part of
incoming message.
(Trac955, git 261450e93af0b0406178e9ef121f81e721e0855c)
255. [func] zhang likun
src/lib/cache: remove empty code in lib/cache and the corresponding
suppression rule in src/cppcheck-suppress.lst.
(Trac639, git 4f714bac4547d0a025afd314c309ca5cb603e212)
254. [bug] jinmei
b10-xfrout: failed to send notifies over IPv6 correctly.
(Trac964, git 3255c92714737bb461fb67012376788530f16e40)
253. [func] jelte
Add configuration options for logging through the virtual module
Logging.
(Trac 736, git 9fa2a95177265905408c51d13c96e752b14a0824)
252. [func] stephen
Add syslog as destination for logging.
(Trac976, git 31a30f5485859fd3df2839fc309d836e3206546e)
251. [bug]* jinmei
Make sure bindctl private files are non readable to anyone except
the owner or users in the same group. Note that if BIND 10 is run
with changing the user, this change means that the file owner or
group will have to be adjusted. Also note that this change is
only effective for a fresh install; if these files already exist,
their permissions must be adjusted by hand (if necessary).
(Trac870, git 461fc3cb6ebabc9f3fa5213749956467a14ebfd4)
250. [bug] ocean
src/lib/util/encode, in some conditions, the DecodeNormalizer's
iterator may reach the end() and when later being dereferenced
it will cause crash on some platform.
(Trac838, git 83e33ec80c0c6485d8b116b13045b3488071770f)
249. [func] jerry
xfrout: add support for TSIG verification.
(Trac816, git 3b2040e2af2f8139c1c319a2cbc429035d93f217)
248. [func] stephen
Add file and stderr as destinations for logging.
(Trac555, git 38b3546867425bd64dbc5920111a843a3330646b)
247. [func] jelte
Upstream queries from the resolver now set EDNS0 buffer size.
(Trac834, git 48e10c2530fe52c9bde6197db07674a851aa0f5d)
246. [func] stephen
Implement logging using log4cplus (http://log4cplus.sourceforge.net)
(Trac899, git 31d3f525dc01638aecae460cb4bc2040c9e4df10)
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
......@@ -80,7 +159,7 @@ bind10-devel-20110519 released on May 19, 2011
(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
......
......@@ -38,8 +38,11 @@ report-cpp-coverage:
c++/4.4\*/ext/\* \
c++/4.4\*/\*-\*/bits/\* \
boost/\* \
botan/\* \
ext/asio/\* \
ext/coroutine/\* \
gtest/\* \
log4cplus/\* \
usr/include/\* \
tests/\* \
unittests/\* \
......
......@@ -447,6 +447,55 @@ AC_LINK_IFELSE(
CPPFLAGS=$CPPFLAGS_SAVED
LDFLAGS=$LDFLAGS_SAVED
# Check for log4cplus
log4cplus_path="yes"
AC_ARG_WITH([log4cplus],
AC_HELP_STRING([--with-log4cplus=PATH],
[specify exact directory of log4cplus library and headers]),
[log4cplus_path="$withval"])
if test "${log4cplus_path}" == "no" ; then
AC_MSG_ERROR([Need log4cplus])
elif test "${log4cplus_path}" != "yes" ; then
LOG4CPLUS_INCLUDES="-I${log4cplus_path}/include"
LOG4CPLUS_LDFLAGS="-L${log4cplus_path}/lib"
else
# If not specified, try some common paths.
log4cplusdirs="/usr/local /usr/pkg /opt /opt/local"
for d in $log4cplusdirs
do
if test -f $d/include/log4cplus/logger.h; then
LOG4CPLUS_INCLUDES="-I$d/include"
LOG4CPLUS_LDFLAGS="-L$d/lib"
break
fi
done
fi
LOG4CPLUS_LDFLAGS="$LOG4CPLUS_LDFLAGS -llog4cplus $MULTITHREADING_FLAG"
AC_SUBST(LOG4CPLUS_LDFLAGS)
AC_SUBST(LOG4CPLUS_INCLUDES)
CPPFLAGS_SAVED=$CPPFLAGS
CPPFLAGS="$LOG4CPLUS_INCLUDES $CPPFLAGS"
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LOG4CPLUS_LDFLAGS $LDFLAGS"
AC_CHECK_HEADERS([log4cplus/logger.h],,AC_MSG_ERROR([Missing required header files.]))
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <log4cplus/logger.h>
],
[using namespace log4cplus;
Logger logger = Logger::getInstance("main");
])],
[AC_MSG_RESULT([checking for log4cplus library... yes])],
[AC_MSG_RESULT([checking for log4cplus library... no])
AC_MSG_ERROR([Needs log4cplus library])]
)
CPPFLAGS=$CPPFLAGS_SAVED
LDFLAGS=$LDFLAGS_SAVED
#
# Configure Boost header path
#
......@@ -775,10 +824,11 @@ 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
src/lib/acl/Makefile
src/lib/acl/tests/Makefile
tests/Makefile
tests/system/Makefile
tests/tools/Makefile
......@@ -842,7 +892,11 @@ AC_OUTPUT([doc/version.ent
src/lib/dns/tests/testdata/gen-wiredata.py
src/lib/cc/session_config.h.pre
src/lib/cc/tests/session_unittests_config.h
src/lib/log/tests/run_time_init_test.sh
src/lib/log/tests/console_test.sh
src/lib/log/tests/destination_test.sh
src/lib/log/tests/local_file_test.sh
src/lib/log/tests/severity_test.sh
src/lib/log/tests/tempdir.h
src/lib/util/python/mkpywrapper.py
src/lib/server_common/tests/data_path.h
tests/system/conf.sh
......@@ -869,7 +923,10 @@ AC_OUTPUT([doc/version.ent
chmod +x src/bin/msgq/tests/msgq_test
chmod +x src/lib/dns/gen-rdatacode.py
chmod +x src/lib/dns/tests/testdata/gen-wiredata.py
chmod +x src/lib/log/tests/run_time_init_test.sh
chmod +x src/lib/log/tests/local_file_test.sh
chmod +x src/lib/log/tests/console_test.sh
chmod +x src/lib/log/tests/destination_test.sh
chmod +x src/lib/log/tests/severity_test.sh
chmod +x src/lib/util/python/mkpywrapper.py
chmod +x tests/system/conf.sh
])
......@@ -902,6 +959,8 @@ dnl includes too
Boost: ${BOOST_INCLUDES}
Botan: ${BOTAN_INCLUDES}
${BOTAN_LDFLAGS}
Log4cplus: ${LOG4CPLUS_INCLUDES}
${LOG4CPLUS_LDFLAGS}
SQLite: $SQLITE_CFLAGS
$SQLITE_LIBS
......
......@@ -573,8 +573,8 @@ INPUT = ../src/lib/cc ../src/lib/config \
../src/bin/auth ../src/bin/resolver ../src/lib/bench \
../src/lib/log ../src/lib/asiolink/ ../src/lib/nsas \
../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \
../src/bin/sockcreator/ ../src/lib/util/
../src/lib/resolve
../src/bin/sockcreator/ ../src/lib/util/ \
../src/lib/resolve ../src/lib/acl
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
......
......@@ -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_;
......
......@@ -26,3 +26,4 @@ query_bench_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
query_bench_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
query_bench_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
query_bench_LDADD += $(SQLITE_LIBS)
......@@ -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) <<