diff options
author | Paul Selkirk <pselkirk@isc.org> | 2013-05-08 17:37:31 +0200 |
---|---|---|
committer | Paul Selkirk <pselkirk@isc.org> | 2013-05-08 17:37:31 +0200 |
commit | c6603decaadcd33ccf9aee4a7b22447acec4b7f6 (patch) | |
tree | 4e83b3a99ca7a0911336bcab8479becc58a04aaa /src | |
parent | [2467] Merge branch 'master' into trac2467 (diff) | |
parent | [2521] add 0-length check to DHCID from-wire constructor (diff) | |
download | kea-c6603decaadcd33ccf9aee4a7b22447acec4b7f6.tar.xz kea-c6603decaadcd33ccf9aee4a7b22447acec4b7f6.zip |
Merge branch 'trac2521'
Conflicts:
src/lib/dns/gen-rdatacode.py.in
Diffstat (limited to 'src')
-rwxr-xr-x | src/lib/dns/gen-rdatacode.py.in | 8 | ||||
-rw-r--r-- | src/lib/dns/rdata/generic/opt_41.cc | 19 | ||||
-rw-r--r-- | src/lib/dns/rdata/generic/rrsig_46.cc | 142 | ||||
-rw-r--r-- | src/lib/dns/rdata/generic/rrsig_46.h | 12 | ||||
-rw-r--r-- | src/lib/dns/rdata/in_1/dhcid_49.cc | 90 | ||||
-rw-r--r-- | src/lib/dns/rdata/in_1/dhcid_49.h | 5 | ||||
-rw-r--r-- | src/lib/dns/tests/message_unittest.cc | 4 | ||||
-rw-r--r-- | src/lib/dns/tests/rdata_dhcid_unittest.cc | 93 | ||||
-rw-r--r-- | src/lib/dns/tests/rdata_opt_unittest.cc | 2 | ||||
-rw-r--r-- | src/lib/dns/tests/rdata_rrsig_unittest.cc | 233 | ||||
-rw-r--r-- | src/lib/dns/tests/rrcollator_unittest.cc | 6 | ||||
-rw-r--r-- | src/lib/dns/tests/rrset_unittest.cc | 4 |
12 files changed, 497 insertions, 121 deletions
diff --git a/src/lib/dns/gen-rdatacode.py.in b/src/lib/dns/gen-rdatacode.py.in index e265d56603..a49f72f357 100755 --- a/src/lib/dns/gen-rdatacode.py.in +++ b/src/lib/dns/gen-rdatacode.py.in @@ -1,6 +1,6 @@ #!@PYTHON@ -# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2010-2013 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 @@ -32,9 +32,11 @@ import sys # # Example: # new_rdata_factory_users = [('a', 'in'), ('a', 'ch'), ('soa', 'generic')] -new_rdata_factory_users = [('a', 'in'), ('aaaa', 'in'), +new_rdata_factory_users = [('a', 'in'), + ('aaaa', 'in'), ('afsdb', 'generic'), ('cname', 'generic'), + ('dhcid', 'in'), ('dlv', 'generic'), ('dname', 'generic'), ('dnskey', 'generic'), @@ -46,7 +48,9 @@ new_rdata_factory_users = [('a', 'in'), ('aaaa', 'in'), ('nsec', 'generic'), ('nsec3', 'generic'), ('nsec3param', 'generic'), + ('opt', 'generic'), ('ptr', 'generic'), + ('rrsig', 'generic'), ('soa', 'generic'), ('spf', 'generic'), ('srv', 'in'), diff --git a/src/lib/dns/rdata/generic/opt_41.cc b/src/lib/dns/rdata/generic/opt_41.cc index d64effb6af..136bdf931a 100644 --- a/src/lib/dns/rdata/generic/opt_41.cc +++ b/src/lib/dns/rdata/generic/opt_41.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2010-2013 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 @@ -27,10 +27,26 @@ using namespace isc::util; // BEGIN_ISC_NAMESPACE // BEGIN_RDATA_NAMESPACE +/// \brief Constructor from string. +/// +/// This constructor cannot be used, and always throws an exception. +/// +/// \throw InvalidRdataText OPT RR cannot be constructed from text. OPT::OPT(const std::string&) { isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text"); } +/// \brief Constructor with a context of MasterLexer. +/// +/// This constructor cannot be used, and always throws an exception. +/// +/// \throw InvalidRdataText OPT RR cannot be constructed from text. +OPT::OPT(MasterLexer&, const Name*, + MasterLoader::Options, MasterLoaderCallbacks&) +{ + isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text"); +} + OPT::OPT(InputBuffer& buffer, size_t rdata_len) { // setPosition() will throw against a short buffer anyway, but it's safer // to check it explicitly here. @@ -48,6 +64,7 @@ OPT::OPT(const OPT&) : Rdata() { std::string OPT::toText() const { + // OPT records do not have a text format. return (""); } diff --git a/src/lib/dns/rdata/generic/rrsig_46.cc b/src/lib/dns/rdata/generic/rrsig_46.cc index e0137b9fc6..8e826d728e 100644 --- a/src/lib/dns/rdata/generic/rrsig_46.cc +++ b/src/lib/dns/rdata/generic/rrsig_46.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2010-2013 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 @@ -26,9 +26,9 @@ #include <dns/messagerenderer.h> #include <dns/name.h> #include <dns/rrtype.h> -#include <dns/rrttl.h> #include <dns/rdata.h> #include <dns/rdataclass.h> +#include <dns/rdata/generic/detail/lexer_util.h> #include <stdio.h> #include <time.h> @@ -36,6 +36,7 @@ using namespace std; using namespace isc::util; using namespace isc::util::encode; +using isc::dns::rdata::generic::detail::createNameFromLexer; // BEGIN_ISC_NAMESPACE // BEGIN_RDATA_NAMESPACE @@ -52,8 +53,8 @@ const size_t RRSIG_MINIMUM_LEN = 2 * sizeof(uint8_t) + 2 * sizeof(uint16_t) + struct RRSIGImpl { // straightforward representation of RRSIG RDATA fields RRSIGImpl(const RRType& covered, uint8_t algorithm, uint8_t labels, - uint32_t originalttl, uint32_t timeexpire, uint32_t timeinception, - uint16_t tag, const Name& signer, + uint32_t originalttl, uint32_t timeexpire, + uint32_t timeinception, uint16_t tag, const Name& signer, const vector<uint8_t>& signature) : covered_(covered), algorithm_(algorithm), labels_(labels), originalttl_(originalttl), timeexpire_(timeexpire), @@ -72,38 +73,125 @@ struct RRSIGImpl { const vector<uint8_t> signature_; }; -RRSIG::RRSIG(const std::string& rrsig_str) : - impl_(NULL) -{ - istringstream iss(rrsig_str); - string covered_txt, signer_txt, expire_txt, inception_txt; - unsigned int algorithm, labels; - uint32_t originalttl; - uint16_t tag; - stringbuf signaturebuf; - - iss >> covered_txt >> algorithm >> labels >> originalttl - >> expire_txt >> inception_txt >> tag >> signer_txt - >> &signaturebuf; - if (iss.bad() || iss.fail()) { - isc_throw(InvalidRdataText, "Invalid RRSIG text"); - } +// helper function for string and lexer constructors +RRSIGImpl* +RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { + const RRType covered(lexer.getNextToken(MasterToken::STRING).getString()); + const uint32_t algorithm = + lexer.getNextToken(MasterToken::NUMBER).getNumber(); if (algorithm > 0xff) { isc_throw(InvalidRdataText, "RRSIG algorithm out of range"); } + const uint32_t labels = + lexer.getNextToken(MasterToken::NUMBER).getNumber(); if (labels > 0xff) { isc_throw(InvalidRdataText, "RRSIG labels out of range"); } - - const uint32_t timeexpire = timeFromText32(expire_txt); - const uint32_t timeinception = timeFromText32(inception_txt); + const uint32_t originalttl = + lexer.getNextToken(MasterToken::NUMBER).getNumber(); + const uint32_t timeexpire = + timeFromText32(lexer.getNextToken(MasterToken::STRING).getString()); + const uint32_t timeinception = + timeFromText32(lexer.getNextToken(MasterToken::STRING).getString()); + const uint32_t tag = + lexer.getNextToken(MasterToken::NUMBER).getNumber(); + if (tag > 0xffff) { + isc_throw(InvalidRdataText, "RRSIG key tag out of range"); + } + const Name& signer = createNameFromLexer(lexer, origin); + + string signature_txt; + string signature_part; + // Whitespace is allowed within base64 text, so read to the end of input. + while (true) { + const MasterToken& token = + lexer.getNextToken(MasterToken::STRING, true); + if ((token.getType() == MasterToken::END_OF_FILE) || + (token.getType() == MasterToken::END_OF_LINE)) { + break; + } + token.getString(signature_part); + signature_txt.append(signature_part); + } + lexer.ungetToken(); vector<uint8_t> signature; - decodeBase64(signaturebuf.str(), signature); + // missing signature is okay + if (signature_txt.size() > 0) { + decodeBase64(signature_txt, signature); + } - impl_ = new RRSIGImpl(RRType(covered_txt), algorithm, labels, - originalttl, timeexpire, timeinception, tag, - Name(signer_txt), signature); + return (new RRSIGImpl(covered, algorithm, labels, + originalttl, timeexpire, timeinception, + static_cast<uint16_t>(tag), signer, signature)); +} + +/// \brief Constructor from string. +/// +/// The given string must represent a valid RRSIG RDATA. There can be extra +/// space characters at the beginning or end of the text (which are simply +/// ignored), but other extra text, including a new line, will make the +/// construction fail with an exception. +/// +/// The Signer's Name must be absolute since there's no parameter that +/// specifies the origin name; if this is not absolute, \c MissingNameOrigin +/// exception will be thrown. This must not be represented as a quoted +/// string. +/// +/// See the construction that takes \c MasterLexer for other fields. +/// +/// \throw Others Exception from the Name constructor. +/// \throw InvalidRdataText Other general syntax errors. +RRSIG::RRSIG(const std::string& rrsig_str) : + impl_(NULL) +{ + // We use auto_ptr here because if there is an exception in this + // constructor, the destructor is not called and there could be a + // leak of the RRSIGImpl that constructFromLexer() returns. + std::auto_ptr<RRSIGImpl> impl_ptr(NULL); + + try { + std::istringstream iss(rrsig_str); + MasterLexer lexer; + lexer.pushSource(iss); + + impl_ptr.reset(constructFromLexer(lexer, NULL)); + + if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { + isc_throw(InvalidRdataText, "extra input text for RRSIG: " + << rrsig_str); + } + } catch (const MasterLexer::LexerError& ex) { + isc_throw(InvalidRdataText, "Failed to construct RRSIG from '" << + rrsig_str << "': " << ex.what()); + } + + impl_ = impl_ptr.release(); +} + +/// \brief Constructor with a context of MasterLexer. +/// +/// The \c lexer should point to the beginning of valid textual representation +/// of an RRSIG RDATA. The Signer's Name fields can be non absolute if \c +/// origin is non NULL, in which case \c origin is used to make it absolute. +/// This must not be represented as a quoted string. +/// +/// The Original TTL field is a valid decimal representation of an unsigned +/// 32-bit integer. Note that alternate textual representations of \c RRTTL, +/// such as "1H" for 3600 seconds, are not allowed here. +/// +/// \throw MasterLexer::LexerError General parsing error such as missing field. +/// \throw Other Exceptions from the Name constructor if +/// construction of textual fields as these objects fail. +/// +/// \param lexer A \c MasterLexer object parsing a master file for the +/// RDATA to be created +/// \param origin If non NULL, specifies the origin of Signer's Name when +/// it is non absolute. +RRSIG::RRSIG(MasterLexer& lexer, const Name* origin, + MasterLoader::Options, MasterLoaderCallbacks&) : + impl_(constructFromLexer(lexer, origin)) +{ } RRSIG::RRSIG(InputBuffer& buffer, size_t rdata_len) { diff --git a/src/lib/dns/rdata/generic/rrsig_46.h b/src/lib/dns/rdata/generic/rrsig_46.h index b32c17f86b..de72f640d1 100644 --- a/src/lib/dns/rdata/generic/rrsig_46.h +++ b/src/lib/dns/rdata/generic/rrsig_46.h @@ -1,4 +1,4 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2010-2013 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 @@ -18,7 +18,6 @@ #include <dns/name.h> #include <dns/rrtype.h> -#include <dns/rrttl.h> #include <dns/rdata.h> // BEGIN_HEADER_GUARD @@ -32,6 +31,12 @@ struct RRSIGImpl; +/// \brief \c rdata::RRSIG class represents the RRSIG RDATA as defined %in +/// RFC4034. +/// +/// This class implements the basic interfaces inherited from the abstract +/// \c rdata::Rdata class, and provides trivial accessors specific to the +/// RRSIG RDATA. class RRSIG : public Rdata { public: // BEGIN_COMMON_MEMBERS @@ -42,6 +47,9 @@ public: // specialized methods const RRType& typeCovered() const; private: + // helper function for string and lexer constructors + RRSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin); + RRSIGImpl* impl_; }; diff --git a/src/lib/dns/rdata/in_1/dhcid_49.cc b/src/lib/dns/rdata/in_1/dhcid_49.cc index 77451619af..184866c49c 100644 --- a/src/lib/dns/rdata/in_1/dhcid_49.cc +++ b/src/lib/dns/rdata/in_1/dhcid_49.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2013 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 @@ -15,8 +15,6 @@ #include <stdint.h> #include <string.h> -#include <string> - #include <exceptions/exceptions.h> #include <util/buffer.h> @@ -28,53 +26,77 @@ using namespace std; using namespace isc::util; +using namespace isc::util::encode; // BEGIN_ISC_NAMESPACE // BEGIN_RDATA_NAMESPACE +void +DHCID::constructFromLexer(MasterLexer& lexer) { + string digest_txt = lexer.getNextToken(MasterToken::STRING).getString(); + + // Whitespace is allowed within base64 text, so read to the end of input. + string digest_part; + while (true) { + const MasterToken& token = + lexer.getNextToken(MasterToken::STRING, true); + if ((token.getType() == MasterToken::END_OF_FILE) || + (token.getType() == MasterToken::END_OF_LINE)) { + break; + } + token.getString(digest_part); + digest_txt.append(digest_part); + } + lexer.ungetToken(); + + decodeBase64(digest_txt, digest_); +} + /// \brief Constructor from string. /// /// \param dhcid_str A base-64 representation of the DHCID binary data. -/// The data is considered to be opaque, but a sanity check is performed. -/// -/// <b>Exceptions</b> /// -/// \c dhcid_str must be a valid BASE-64 string, otherwise an exception -/// of class \c isc::BadValue will be thrown; -/// the binary data should consist of at leat of 3 octets as per RFC4701: -/// < 2 octets > Identifier type code -/// < 1 octet > Digest type code -/// < n octets > Digest (length depends on digest type) -/// If the data is less than 3 octets (i.e. it cannot contain id type code and -/// digest type code), an exception of class \c InvalidRdataLength is thrown. +/// \throw InvalidRdataText if the string could not be parsed correctly. DHCID::DHCID(const std::string& dhcid_str) { - istringstream iss(dhcid_str); - stringbuf digestbuf; - - iss >> &digestbuf; - isc::util::encode::decodeBase64(digestbuf.str(), digest_); - - // RFC4701 states DNS software should consider the RDATA section to - // be opaque, but there must be at least three bytes in the data: - // < 2 octets > Identifier type code - // < 1 octet > Digest type code - if (digest_.size() < 3) { - isc_throw(InvalidRdataLength, "DHCID length " << digest_.size() << - " too short, need at least 3 bytes"); + try { + std::istringstream iss(dhcid_str); + MasterLexer lexer; + lexer.pushSource(iss); + + constructFromLexer(lexer); + + if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { + isc_throw(InvalidRdataText, "extra input text for DHCID: " + << dhcid_str); + } + } catch (const MasterLexer::LexerError& ex) { + isc_throw(InvalidRdataText, "Failed to construct DHCID from '" << + dhcid_str << "': " << ex.what()); } } +/// \brief Constructor with a context of MasterLexer. +/// +/// The \c lexer should point to the beginning of valid textual representation +/// of a DHCID RDATA. +/// +/// \throw BadValue if the text is not valid base-64. +/// \throw MasterLexer::LexerError General parsing error such as missing field. +/// +/// \param lexer A \c MasterLexer object parsing a master file for the +/// RDATA to be created +DHCID::DHCID(MasterLexer& lexer, const Name*, + MasterLoader::Options, MasterLoaderCallbacks&) { + constructFromLexer(lexer); +} + /// \brief Constructor from wire-format data. /// /// \param buffer A buffer storing the wire format data. /// \param rdata_len The length of the RDATA in bytes -/// -/// <b>Exceptions</b> -/// \c InvalidRdataLength is thrown if \c rdata_len is than minimum of 3 octets DHCID::DHCID(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 3) { - isc_throw(InvalidRdataLength, "DHCID length " << rdata_len << - " too short, need at least 3 bytes"); + if (rdata_len == 0) { + isc_throw(InvalidRdataLength, "Missing DHCID rdata"); } digest_.resize(rdata_len); @@ -112,7 +134,7 @@ DHCID::toWire(AbstractMessageRenderer& renderer) const { /// \return A string representation of \c DHCID. string DHCID::toText() const { - return (isc::util::encode::encodeBase64(digest_)); + return (encodeBase64(digest_)); } /// \brief Compare two instances of \c DHCID RDATA. diff --git a/src/lib/dns/rdata/in_1/dhcid_49.h b/src/lib/dns/rdata/in_1/dhcid_49.h index 90f5fabf94..81041b0db9 100644 --- a/src/lib/dns/rdata/in_1/dhcid_49.h +++ b/src/lib/dns/rdata/in_1/dhcid_49.h @@ -1,4 +1,4 @@ -// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2013 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 @@ -43,6 +43,9 @@ public: const std::vector<uint8_t>& getDigest() const; private: + // helper for string and lexer constructors + void constructFromLexer(MasterLexer& lexer); + /// \brief Private data representation /// /// Opaque data at least 3 octets long as per RFC4701. diff --git a/src/lib/dns/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc index 835aa4825e..8aaebaa183 100644 --- a/src/lib/dns/tests/message_unittest.cc +++ b/src/lib/dns/tests/message_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2010-2013 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 @@ -98,7 +98,7 @@ protected: rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(), RRType::RRSIG(), RRTTL(3600))); rrset_rrsig->addRdata(generic::RRSIG("AAAA 5 3 7200 20100322084538 " - "20100220084538 1 example.com " + "20100220084538 1 example.com. " "FAKEFAKEFAKEFAKE")); rrset_aaaa->addRRsig(rrset_rrsig); } diff --git a/src/lib/dns/tests/rdata_dhcid_unittest.cc b/src/lib/dns/tests/rdata_dhcid_unittest.cc index 8d56c0e7a3..77baccd893 100644 --- a/src/lib/dns/tests/rdata_dhcid_unittest.cc +++ b/src/lib/dns/tests/rdata_dhcid_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2013 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 @@ -12,6 +12,8 @@ // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. +#include <exceptions/exceptions.h> + #include <util/buffer.h> #include <dns/rdataclass.h> #include <util/encode/base64.h> @@ -23,6 +25,7 @@ using isc::UnitTestUtil; using namespace std; +using namespace isc; using namespace isc::dns; using namespace isc::util; using namespace isc::util::encode; @@ -30,25 +33,69 @@ using namespace isc::dns::rdata; namespace { -const string string_dhcid( - "0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA="); - -const in::DHCID rdata_dhcid(string_dhcid); - class Rdata_DHCID_Test : public RdataTest { +protected: + Rdata_DHCID_Test() : + dhcid_txt("0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA="), + rdata_dhcid(dhcid_txt) + {} + + void checkFromText_None(const string& rdata_str) { + checkFromText<in::DHCID, isc::Exception, isc::Exception>( + rdata_str, rdata_dhcid, false, false); + } + + void checkFromText_BadValue(const string& rdata_str) { + checkFromText<in::DHCID, BadValue, BadValue>( + rdata_str, rdata_dhcid, true, true); + } + + void checkFromText_LexerError(const string& rdata_str) { + checkFromText + <in::DHCID, InvalidRdataText, MasterLexer::LexerError>( + rdata_str, rdata_dhcid, true, true); + } + + void checkFromText_BadString(const string& rdata_str) { + checkFromText + <in::DHCID, InvalidRdataText, isc::Exception>( + rdata_str, rdata_dhcid, true, false); + } + + const string dhcid_txt; + const in::DHCID rdata_dhcid; }; -TEST_F(Rdata_DHCID_Test, createFromString) { - const in::DHCID rdata_dhcid2(string_dhcid); - EXPECT_EQ(0, rdata_dhcid2.compare(rdata_dhcid)); -} +TEST_F(Rdata_DHCID_Test, fromText) { + EXPECT_EQ(dhcid_txt, rdata_dhcid.toText()); + + // Space in digest data is OK + checkFromText_None( + "0LIg0LvQtdGB0YMg 0YDQvtC00LjQu9Cw 0YHRjCDRkdC70L7R h9C60LA="); + + // Multi-line digest data is OK, if enclosed in parentheses + checkFromText_None( + "( 0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw\n0YHRjCDRkdC70L7R h9C60LA= )"); -TEST_F(Rdata_DHCID_Test, badBase64) { - EXPECT_THROW(const in::DHCID rdata_dhcid_bad("00"), isc::BadValue); + // Trailing garbage. This should cause only the string constructor + // to fail, but the lexer constructor must be able to continue + // parsing from it. + checkFromText_BadString( + "0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA=" + " ; comment\n" + "AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA="); } -TEST_F(Rdata_DHCID_Test, badLength) { - EXPECT_THROW(const in::DHCID rdata_dhcid_bad("MDA="), InvalidRdataLength); +TEST_F(Rdata_DHCID_Test, badText) { + // missing digest data + checkFromText_LexerError(""); + + // invalid base64 + checkFromText_BadValue("EEeeeeeeEEEeeeeeeGaaahAAAAAAAAHHHHHHHHHHH!="); + + // unterminated multi-line base64 + checkFromText_LexerError( + "( 0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw\n0YHRjCDRkdC70L7R h9C60LA="); } TEST_F(Rdata_DHCID_Test, copy) { @@ -60,17 +107,17 @@ TEST_F(Rdata_DHCID_Test, createFromWire) { EXPECT_EQ(0, rdata_dhcid.compare( *rdataFactoryFromFile(RRType("DHCID"), RRClass("IN"), "rdata_dhcid_fromWire"))); + + InputBuffer buffer(NULL, 0); + EXPECT_THROW(in::DHCID(buffer, 0), InvalidRdataLength); + // TBD: more tests } TEST_F(Rdata_DHCID_Test, createFromLexer) { EXPECT_EQ(0, rdata_dhcid.compare( *test::createRdataUsingLexer(RRType::DHCID(), RRClass::IN(), - string_dhcid))); - - // Exceptions cause NULL to be returned. - EXPECT_FALSE(test::createRdataUsingLexer(RRType::DHCID(), RRClass::IN(), - "00")); + dhcid_txt))); } TEST_F(Rdata_DHCID_Test, toWireRenderer) { @@ -92,13 +139,13 @@ TEST_F(Rdata_DHCID_Test, toWireBuffer) { } TEST_F(Rdata_DHCID_Test, toText) { - EXPECT_EQ(string_dhcid, rdata_dhcid.toText()); + EXPECT_EQ(dhcid_txt, rdata_dhcid.toText()); } TEST_F(Rdata_DHCID_Test, getDHCIDDigest) { - const string string_dhcid1(encodeBase64(rdata_dhcid.getDigest())); + const string dhcid_txt1(encodeBase64(rdata_dhcid.getDigest())); - EXPECT_EQ(string_dhcid, string_dhcid1); + EXPECT_EQ(dhcid_txt, dhcid_txt1); } TEST_F(Rdata_DHCID_Test, compare) { @@ -117,6 +164,6 @@ TEST_F(Rdata_DHCID_Test, compare) { EXPECT_GT(rdata_dhcid3.compare(rdata_dhcid2), 0); // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_dhcid.compare(*rdata_nomatch), bad_cast); + EXPECT_THROW(rdata_dhcid.compare(*rdata_nomatch), bad_cast); } } diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc index 5699259935..20ccfe4994 100644 --- a/src/lib/dns/tests/rdata_opt_unittest.cc +++ b/src/lib/dns/tests/rdata_opt_unittest.cc @@ -84,6 +84,6 @@ TEST_F(Rdata_OPT_Test, compare) { "rdata_opt_fromWire", 2))); // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_opt.compare(*RdataTest::rdata_nomatch), bad_cast); + EXPECT_THROW(rdata_opt.compare(*RdataTest::rdata_nomatch), bad_cast); } } diff --git a/src/lib/dns/tests/rdata_rrsig_unittest.cc b/src/lib/dns/tests/rdata_rrsig_unittest.cc index d758ff390b..2d075ece97 100644 --- a/src/lib/dns/tests/rdata_rrsig_unittest.cc +++ b/src/lib/dns/tests/rdata_rrsig_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2010-2013 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 @@ -36,7 +36,7 @@ using namespace isc::dns::rdata; namespace { class Rdata_RRSIG_Test : public RdataTest { -public: +protected: Rdata_RRSIG_Test() : rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" @@ -46,6 +46,49 @@ public: rdata_rrsig(rrsig_txt) {} + void checkFromText_None(const string& rdata_str) { + checkFromText<generic::RRSIG, isc::Exception, isc::Exception>( + rdata_str, rdata_rrsig, false, false); + } + + void checkFromText_InvalidText(const string& rdata_str) { + checkFromText<generic::RRSIG, InvalidRdataText, InvalidRdataText>( + rdata_str, rdata_rrsig, true, true); + } + + void checkFromText_InvalidType(const string& rdata_str) { + checkFromText<generic::RRSIG, InvalidRRType, InvalidRRType>( + rdata_str, rdata_rrsig, true, true); + } + + void checkFromText_InvalidTime(const string& rdata_str) { + checkFromText<generic::RRSIG, InvalidTime, InvalidTime>( + rdata_str, rdata_rrsig, true, true); + } + + void checkFromText_BadValue(const string& rdata_str) { + checkFromText<generic::RRSIG, BadValue, BadValue>( + rdata_str, rdata_rrsig, true, true); + } + + void checkFromText_LexerError(const string& rdata_str) { + checkFromText + <generic::RRSIG, InvalidRdataText, MasterLexer::LexerError>( + rdata_str, rdata_rrsig, true, true); + } + + void checkFromText_MissingOrigin(const string& rdata_str) { + checkFromText + <generic::RRSIG, MissingNameOrigin, MissingNameOrigin>( + rdata_str, rdata_rrsig, true, true); + } + + void checkFromText_BadString(const string& rdata_str) { + checkFromText + <generic::RRSIG, InvalidRdataText, isc::Exception>( + rdata_str, rdata_rrsig, true, false); + } + const string rrsig_txt; const generic::RRSIG rdata_rrsig; }; @@ -53,52 +96,196 @@ public: TEST_F(Rdata_RRSIG_Test, fromText) { EXPECT_EQ(rrsig_txt, rdata_rrsig.toText()); EXPECT_EQ(isc::dns::RRType::A(), rdata_rrsig.typeCovered()); + + // Missing signature is OK + EXPECT_NO_THROW(const generic::RRSIG sig( + "A 5 4 43200 20100223214617 20100222214617 8496 isc.org.")); + + // Space in signature data is OK + checkFromText_None( + "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz " + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/ " + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU " + "f49t+sXKPzbipN9g+s1ZPiIyofc="); + + // Multi-line signature data is OK, if enclosed in parentheses + checkFromText_None( + "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " + "( evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz\n" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/\n" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU\n" + "f49t+sXKPzbipN9g+s1ZPiIyofc= )"); + + // Trailing garbage. This should cause only the string constructor + // to fail, but the lexer constructor must be able to continue + // parsing from it. + checkFromText_BadString( + "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc= ; comment\n" + "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); +} + +TEST_F(Rdata_RRSIG_Test, badText_missingFields) { + checkFromText_LexerError("A"); + checkFromText_LexerError("A 5"); + checkFromText_LexerError("A 5 4"); + checkFromText_LexerError("A 5 4 43200"); + checkFromText_LexerError("A 5 4 43200 20100223214617"); + checkFromText_LexerError("A 5 4 43200 20100223214617 20100222214617"); + checkFromText_LexerError("A 5 4 43200 20100223214617 20100222214617 " + "8496"); +} + +TEST_F(Rdata_RRSIG_Test, badText_coveredType) { + checkFromText_InvalidType("SPORK"); +} + +TEST_F(Rdata_RRSIG_Test, badText_algorithm) { + checkFromText_InvalidText( + "A 555 4 43200 " + "20100223214617 20100222214617 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); + checkFromText_LexerError( + "A FIVE 4 43200 " + "20100223214617 20100222214617 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); } -TEST_F(Rdata_RRSIG_Test, badText) { - EXPECT_THROW(const generic::RRSIG sig("SPORK"), InvalidRdataText); - EXPECT_THROW(const generic::RRSIG sig("A 555 4 43200 " +TEST_F(Rdata_RRSIG_Test, badText_labels) { + checkFromText_InvalidText( + "A 5 4444 43200 " "20100223214617 20100222214617 8496 isc.org. " "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="), InvalidRdataText); - EXPECT_THROW(const generic::RRSIG sig("A 5 4444 43200 " + "f49t+sXKPzbipN9g+s1ZPiIyofc="); + checkFromText_LexerError( + "A 5 FOUR 43200 " "20100223214617 20100222214617 8496 isc.org. " "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="), InvalidRdataText); - EXPECT_THROW(const generic::RRSIG sig("A 5 4 999999999999 " + "f49t+sXKPzbipN9g+s1ZPiIyofc="); +} + +TEST_F(Rdata_RRSIG_Test, badText_ttl) { + checkFromText_LexerError( + "A 5 4 999999999999 " "20100223214617 20100222214617 8496 isc.org. " "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="), InvalidRdataText); - EXPECT_THROW(const generic::RRSIG sig("A 5 4 43200 " - "20100223 20100227 8496 isc.org. " + "f49t+sXKPzbipN9g+s1ZPiIyofc="); + checkFromText_LexerError( + "A 5 4 TTL " + "20100223214617 20100222214617 8496 isc.org. " "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="), InvalidTime); - EXPECT_THROW(const generic::RRSIG sig("A 5 4 43200 " + "f49t+sXKPzbipN9g+s1ZPiIyofc="); + + // alternate form of TTL is not okay + checkFromText_LexerError( + "A 5 4 12H 20100223214617 20100222214617 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz " + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/ " + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU " + "f49t+sXKPzbipN9g+s1ZPiIyofc="); +} + +TEST_F(Rdata_RRSIG_Test, badText_expiration) { + checkFromText_InvalidTime( + "A 5 4 43200 " + "201002232 20100222214617 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); + checkFromText_InvalidTime( + "A 5 4 43200 " + "EXPIRATION 20100222214617 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); +} + +TEST_F(Rdata_RRSIG_Test, badText_inception) { + checkFromText_InvalidTime( + "A 5 4 43200 " + "20100223214617 20100227 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); + checkFromText_InvalidTime( + "A 5 4 43200 " + "20100223214617 INCEPTION 8496 isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); +} + +TEST_F(Rdata_RRSIG_Test, badText_keytag) { + checkFromText_InvalidText( + "A 5 4 43200 " "20100223214617 20100222214617 999999 isc.org. " "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="), InvalidRdataText); - EXPECT_THROW(const generic::RRSIG sig( + "f49t+sXKPzbipN9g+s1ZPiIyofc="); + checkFromText_LexerError( "A 5 4 43200 " - "20100223214617 20100222214617 8496 isc.org. " - "EEeeeeeeEEEeeeeeeGaaahAAAAAAAAHHHHHHHHHHH!="), - BadValue); // bad base64 input + "20100223214617 20100222214617 TAG isc.org. " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); +} + +TEST_F(Rdata_RRSIG_Test, badText_signer) { + checkFromText_MissingOrigin( + "A 5 4 43200 " + "20100223214617 20100222214617 8496 isc.org " + "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); } -TEST_F(Rdata_RRSIG_Test, DISABLED_badText) { - // this currently fails +TEST_F(Rdata_RRSIG_Test, badText_signature) { + checkFromText_BadValue( + "A 5 4 43200 " + "20100223214617 20100222214617 8496 isc.org. " + "EEeeeeeeEEEeeeeeeGaaahAAAAAAAAHHHHHHHHHHH!="); + // no space between the tag and signer - EXPECT_THROW(generic::RRSIG("A 5 4 43200 20100223214617 20100222214617 " - "8496isc.org. ofc="), InvalidRdataText); + checkFromText_LexerError( + "A 5 4 43200 20100223214617 20100222214617 " + "8496isc.org. ofc="); + + // unterminated multi-line base64 + checkFromText_LexerError( + "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " + "( evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz\n" + "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/\n" + "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU\n" + "f49t+sXKPzbipN9g+s1ZPiIyofc="); } TEST_F(Rdata_RRSIG_Test, createFromLexer) { diff --git a/src/lib/dns/tests/rrcollator_unittest.cc b/src/lib/dns/tests/rrcollator_unittest.cc index e66f87c03a..9123dc5bb3 100644 --- a/src/lib/dns/tests/rrcollator_unittest.cc +++ b/src/lib/dns/tests/rrcollator_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2013 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 @@ -59,10 +59,10 @@ protected: txt_rdata_(createRdata(RRType::TXT(), rrclass_, "test")), sig_rdata1_(createRdata(RRType::RRSIG(), rrclass_, "A 5 3 3600 20000101000000 20000201000000 " - "12345 example.com. FAKE\n")), + "12345 example.com. FAKE")), sig_rdata2_(createRdata(RRType::RRSIG(), rrclass_, "NS 5 3 3600 20000101000000 20000201000000 " - "12345 example.com. FAKE\n")) + "12345 example.com. FAKE")) {} void checkRRset(const Name& expected_name, const RRClass& expected_class, diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc index d16ce3c15b..a605caf62b 100644 --- a/src/lib/dns/tests/rrset_unittest.cc +++ b/src/lib/dns/tests/rrset_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2010-2013 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 @@ -289,7 +289,7 @@ protected: rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(), RRType::RRSIG(), RRTTL(3600))); rrset_rrsig->addRdata(generic::RRSIG("AAAA 5 3 7200 20100322084538 " - "20100220084538 1 example.com " + "20100220084538 1 example.com. " "FAKEFAKEFAKEFAKE")); rrset_aaaa->addRRsig(rrset_rrsig); } |