#include <boost/lexical_cast.hpp>
#include <util/buffer.h>
-#include <util/strutil.h>
#include <util/encode/base64.h>
#include <dns/messagerenderer.h>
using boost::lexical_cast;
using namespace isc::util;
using namespace isc::util::encode;
-using namespace isc::util::str;
using namespace isc::dns;
using isc::dns::rdata::generic::detail::createNameFromLexer;
// helper function for string and lexer constructors
TSIGImpl*
-TSIG::constructFromLexer(MasterLexer& lexer) {
+TSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) {
// RFC2845 defines Algorithm Name to be "in domain name syntax",
// but it's not actually a domain name, so we allow it to be not
// fully qualified.
- const Name root(".");
- const Name& algorithm = createNameFromLexer(lexer, &root);
+ const Name& algorithm =
+ createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME());
- const string time_str =
+ const string& time_txt =
lexer.getNextToken(MasterToken::STRING).getString();
uint64_t time_signed;
try {
- time_signed = boost::lexical_cast<uint64_t>(time_str);
+ time_signed = boost::lexical_cast<uint64_t>(time_txt);
} catch (const boost::bad_lexical_cast&) {
isc_throw(InvalidRdataText, "Invalid TSIG Time");
}
isc_throw(InvalidRdataText, "TSIG MAC Size out of range");
}
- const string mac_txt = (macsize > 0) ?
+ const string& mac_txt = (macsize > 0) ?
lexer.getNextToken(MasterToken::STRING).getString() : "";
vector<uint8_t> mac;
decodeBase64(mac_txt, mac);
isc_throw(InvalidRdataText, "TSIG Original ID out of range");
}
- const string error_txt =
+ const string& error_txt =
lexer.getNextToken(MasterToken::STRING).getString();
- uint16_t error = 0;
+ uint32_t error = 0;
// XXX: In the initial implementation we hardcode the mnemonics.
// We'll soon generalize this.
if (error_txt == "NOERROR") {
error = TSIGError::BAD_TIME_CODE;
} else {
try {
- error = boost::lexical_cast<uint16_t>(error_txt);
+ error = boost::lexical_cast<uint32_t>(error_txt);
} catch (const boost::bad_lexical_cast&) {
isc_throw(InvalidRdataText, "Invalid TSIG Error");
}
+ if (error > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG Error out of range");
+ }
}
- const int32_t otherlen =
+ const uint32_t otherlen =
lexer.getNextToken(MasterToken::NUMBER).getNumber();
if (otherlen > 0xffff) {
isc_throw(InvalidRdataText, "TSIG Other Len out of range");
isc_throw(InvalidRdataText,
"TSIG Other Data length does not match Other Len");
}
- // also verify Error == BADTIME?
+ // RFC2845 says Other Data is "empty unless Error == BADTIME".
+ // However, we don't enforce that.
return (new TSIGImpl(algorithm, time_signed, fudge, mac, orig_id,
error, other_data));
MasterLexer lexer;
lexer.pushSource(ss);
- impl_ptr.reset(constructFromLexer(lexer));
+ impl_ptr.reset(constructFromLexer(lexer, NULL));
if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
isc_throw(InvalidRdataText,
///
/// \param lexer A \c MasterLexer object parsing a master file for the
/// RDATA to be created
-TSIG::TSIG(MasterLexer& lexer, const Name*,
- MasterLoader::Options, MasterLoaderCallbacks&) :
- impl_(constructFromLexer(lexer))
+TSIG::TSIG(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer, origin))
{
}
/// But this constructor does not use this parameter; if necessary, the caller
/// must check consistency between the length parameter and the actual
/// RDATA length.
-TSIG::TSIG(InputBuffer& buffer, size_t) : impl_(NULL) {
+TSIG::TSIG(InputBuffer& buffer, size_t) :
+ impl_(NULL)
+{
Name algorithm(buffer);
uint8_t time_signed_buf[6];
using namespace isc::dns::rdata;
namespace {
-const char* const valid_text1 = "hmac-md5.sig-alg.reg.int. 1286779327 300 "
+const string valid_text1 = "hmac-md5.sig-alg.reg.int. 1286779327 300 "
"0 16020 BADKEY 0";
-const char* const valid_text2 = "hmac-sha256. 1286779327 300 12 "
+const string valid_text2 = "hmac-sha256. 1286779327 300 12 "
"FAKEFAKEFAKEFAKE 16020 BADSIG 0";
-
-const char* const valid_text3 = "hmac-sha1. 1286779327 300 12 "
+const string valid_text3 = "hmac-sha1. 1286779327 300 12 "
"FAKEFAKEFAKEFAKE 16020 BADTIME 6 FAKEFAKE";
-const char* const valid_text4 = "hmac-sha1. 1286779327 300 12 "
+const string valid_text4 = "hmac-sha1. 1286779327 300 12 "
"FAKEFAKEFAKEFAKE 16020 BADSIG 6 FAKEFAKE";
-const char* const valid_text5 = "hmac-sha256. 1286779327 300 12 "
+const string valid_text5 = "hmac-sha256. 1286779327 300 12 "
"FAKEFAKEFAKEFAKE 16020 2845 0"; // using numeric error code
-const char* const too_long_label = "012345678901234567890123456789"
- "0123456789012345678901234567890123";
class Rdata_TSIG_Test : public RdataTest {
protected:
- Rdata_TSIG_Test() : rdata_tsig(valid_text1) {}
+ Rdata_TSIG_Test() :
+ rdata_tsig(valid_text1)
+ {}
void checkFromText_InvalidText(const string& rdata_str) {
checkFromText<any::TSIG, InvalidRdataText, InvalidRdataText>(
rdata_str, rdata_tsig, true, true);
}
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <any::TSIG, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_tsig, true, false);
+ }
+
template <typename Output>
void toWireCommonChecks(Output& output) const;
TEST_F(Rdata_TSIG_Test, badText) {
// too many fields
- EXPECT_THROW(any::TSIG("foo 0 0 0 0 BADKEY 0 0"), InvalidRdataText);
+ checkFromText_BadString(valid_text1 + " 0 0");
// not enough fields
checkFromText_LexerError("foo 0 0 0 0 BADKEY");
// bad domain name
- checkFromText_TooLongLabel(string(too_long_label) + "0 0 0 0 BADKEY 0");
+ checkFromText_TooLongLabel(
+ "0123456789012345678901234567890123456789012345678901234567890123"
+ " 0 0 0 0 BADKEY 0");
checkFromText_EmptyLabel("foo..bar 0 0 0 0 BADKEY");
// time is too large (2814...6 is 2^48)
checkFromText_InvalidText("foo 281474976710656 0 0 0 BADKEY 0");
checkFromText_InvalidText("foo 0 0 0 0 TEST 0");
// Numeric error code is too large
checkFromText_InvalidText("foo 0 0 0 0 65536 0");
+ // Numeric error code is negative
+ checkFromText_InvalidText("foo 0 0 0 0 -1 0");
// Other len is too large
checkFromText_InvalidText("foo 0 0 0 0 NOERROR 65536 FAKE");
+ // Other len is negative
+ checkFromText_LexerError("foo 0 0 0 0 NOERROR -1 FAKE");
// invalid Other len
checkFromText_LexerError("foo 0 0 0 0 NOERROR LEN FAKE");
// Other len and data mismatch
isc::InvalidParameter);
}
-TEST_F(Rdata_TSIG_Test, createFromLexer) {
- EXPECT_EQ(0, rdata_tsig.compare(
- *test::createRdataUsingLexer(RRType::TSIG(), RRClass::ANY(),
- valid_text1)));
-
- // Exceptions cause NULL to be returned.
- EXPECT_FALSE(test::createRdataUsingLexer(RRType::TSIG(), RRClass::ANY(),
- "foo 0 0 0 0 BADKEY 0 0"));
-}
-
TEST_F(Rdata_TSIG_Test, assignment) {
any::TSIG copy((string(valid_text2)));
copy = rdata_tsig;