EXTRA_DIST += rdata/generic/spf_99.h
EXTRA_DIST += rdata/generic/sshfp_44.cc
EXTRA_DIST += rdata/generic/sshfp_44.h
+EXTRA_DIST += rdata/generic/tlsa_52.cc
+EXTRA_DIST += rdata/generic/tlsa_52.h
EXTRA_DIST += rdata/generic/txt_16.cc
EXTRA_DIST += rdata/generic/txt_16.h
EXTRA_DIST += rdata/generic/minfo_14.cc
'10': 'null', '11': 'wks', '19': 'x25', '21': 'rt', '22': 'nsap',
'23': 'nsap-ptr', '24': 'sig', '20': 'isdn', '25': 'key', '26': 'px',
'27': 'gpos', '29': 'loc', '36': 'kx', '37': 'cert', '42': 'apl',
- '45': 'ipseckey', '52': 'tlsa', '55': 'hip', '103': 'unspec',
+ '45': 'ipseckey', '55': 'hip', '103': 'unspec',
'104': 'nid', '105': 'l32', '106': 'l64', '107': 'lp', '249': 'tkey',
'253': 'mailb', '256': 'uri', '257': 'caa'
}
--- /dev/null
+// Copyright (C) 2014 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
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+struct TLSAImpl {
+ // straightforward representation of TLSA RDATA fields
+ TLSAImpl(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const vector<uint8_t>& data) :
+ certificate_usage_(certificate_usage),
+ selector_(selector),
+ matching_type_(matching_type),
+ data_(data)
+ {}
+
+ uint8_t certificate_usage_;
+ uint8_t selector_;
+ uint8_t matching_type_;
+ const vector<uint8_t> data_;
+};
+
+// helper function for string and lexer constructors
+TLSAImpl*
+TLSA::constructFromLexer(MasterLexer& lexer) {
+ const uint32_t certificate_usage =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (certificate_usage > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA certificate usage field out of range");
+ }
+
+ const uint32_t selector =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (selector > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA selector field out of range");
+ }
+
+ const uint32_t matching_type =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (matching_type > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA matching type field out of range");
+ }
+
+ std::string certificate_assoc_data;
+ std::string data_substr;
+ 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(data_substr);
+ certificate_assoc_data.append(data_substr);
+ }
+ lexer.ungetToken();
+
+ vector<uint8_t> data;
+ // If certificate association data is missing, it's OK. See the API
+ // documentation of the constructor.
+ if (certificate_assoc_data.size() > 0) {
+ try {
+ decodeHex(certificate_assoc_data, data);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText,
+ "Bad TLSA certificate association data: " << e.what());
+ }
+ }
+
+ return (new TLSAImpl(certificate_usage, selector, matching_type, data));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid TLSA 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 Certificate Usage, Selector and Matching Type fields must be
+/// within their valid ranges, but are not constrained to the values
+/// defined in RFC6698.
+///
+/// The Certificate Association Data Field field may be absent, but if
+/// present it must contain a valid hex encoding of the data. Whitespace
+/// is allowed in the hex text.
+///
+/// \throw InvalidRdataText if any fields are missing, out of their
+/// valid ranges, or are incorrect, or Certificate Association Data is
+/// not a valid hex string.
+///
+/// \param tlsa_str A string containing the RDATA to be created
+TLSA::TLSA(const string& tlsa_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 TLSAImpl that constructFromLexer() returns.
+ std::auto_ptr<TLSAImpl> impl_ptr(NULL);
+
+ try {
+ std::istringstream ss(tlsa_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for TLSA: "
+ << tlsa_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct TLSA from '" <<
+ tlsa_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 TLSA RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdataText Fields are out of their valid range, or are
+/// incorrect, or Certificate Association Data is not a valid hex string.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+TLSA::TLSA(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer))
+{
+}
+
+/// \brief Constructor from InputBuffer.
+///
+/// The passed buffer must contain a valid TLSA RDATA.
+///
+/// The Certificate Usage, Selector and Matching Type fields must be
+/// within their valid ranges, but are not constrained to the values
+/// defined in RFC6698. It is okay for the certificate association data
+/// to be missing (see the description of the constructor from string).
+TLSA::TLSA(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len < 3) {
+ isc_throw(InvalidRdataLength, "TLSA record too short");
+ }
+
+ const uint8_t certificate_usage = buffer.readUint8();
+ const uint8_t selector = buffer.readUint8();
+ const uint8_t matching_type = buffer.readUint8();
+
+ vector<uint8_t> data;
+ rdata_len -= 3;
+ if (rdata_len > 0) {
+ data.resize(rdata_len);
+ buffer.readData(&data[0], rdata_len);
+ }
+
+ impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data);
+}
+
+TLSA::TLSA(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const std::string& certificate_assoc_data) :
+ impl_(NULL)
+{
+ vector<uint8_t> data;
+ try {
+ decodeHex(certificate_assoc_data, data);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText,
+ "Bad TLSA certificate association data: " << e.what());
+ }
+
+ impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data);
+}
+
+TLSA::TLSA(const TLSA& other) :
+ Rdata(), impl_(new TLSAImpl(*other.impl_))
+{}
+
+TLSA&
+TLSA::operator=(const TLSA& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TLSAImpl* newimpl = new TLSAImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TLSA::~TLSA() {
+ delete impl_;
+}
+
+void
+TLSA::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint8(impl_->certificate_usage_);
+ buffer.writeUint8(impl_->selector_);
+ buffer.writeUint8(impl_->matching_type_);
+
+ if (!impl_->data_.empty()) {
+ buffer.writeData(&impl_->data_[0],
+ impl_->data_.size());
+ }
+}
+
+void
+TLSA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint8(impl_->certificate_usage_);
+ renderer.writeUint8(impl_->selector_);
+ renderer.writeUint8(impl_->matching_type_);
+
+ if (!impl_->data_.empty()) {
+ renderer.writeData(&impl_->data_[0],
+ impl_->data_.size());
+ }
+}
+
+string
+TLSA::toText() const {
+ return (lexical_cast<string>(static_cast<int>(impl_->certificate_usage_)) + " " +
+ lexical_cast<string>(static_cast<int>(impl_->selector_)) + " " +
+ lexical_cast<string>(static_cast<int>(impl_->matching_type_)) +
+ (impl_->data_.empty() ? "" :
+ " " + encodeHex(impl_->data_)));
+}
+
+int
+TLSA::compare(const Rdata& other) const {
+ const TLSA& other_tlsa = dynamic_cast<const TLSA&>(other);
+
+ if (impl_->certificate_usage_ < other_tlsa.impl_->certificate_usage_) {
+ return (-1);
+ } else if (impl_->certificate_usage_ >
+ other_tlsa.impl_->certificate_usage_) {
+ return (1);
+ }
+
+ if (impl_->selector_ < other_tlsa.impl_->selector_) {
+ return (-1);
+ } else if (impl_->selector_ > other_tlsa.impl_->selector_) {
+ return (1);
+ }
+
+ if (impl_->matching_type_ < other_tlsa.impl_->matching_type_) {
+ return (-1);
+ } else if (impl_->matching_type_ >
+ other_tlsa.impl_->matching_type_) {
+ return (1);
+ }
+
+ const size_t this_len = impl_->data_.size();
+ const size_t other_len = other_tlsa.impl_->data_.size();
+ const size_t cmplen = min(this_len, other_len);
+
+ if (cmplen > 0) {
+ const int cmp = memcmp(&impl_->data_[0],
+ &other_tlsa.impl_->data_[0],
+ cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ }
+
+ if (this_len == other_len) {
+ return (0);
+ } else if (this_len < other_len) {
+ return (-1);
+ } else {
+ return (1);
+ }
+}
+
+uint8_t
+TLSA::getCertificateUsage() const {
+ return (impl_->certificate_usage_);
+}
+
+uint8_t
+TLSA::getSelector() const {
+ return (impl_->selector_);
+}
+
+uint8_t
+TLSA::getMatchingType() const {
+ return (impl_->matching_type_);
+}
+
+const std::vector<uint8_t>&
+TLSA::getData() const {
+ return (impl_->data_);
+}
+
+size_t
+TLSA::getDataLength() const {
+ return (impl_->data_.size());
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
--- /dev/null
+// Copyright (C) 2014 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
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// BEGIN_HEADER_GUARD
+
+#include <stdint.h>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+#include <string>
+#include <vector>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+struct TLSAImpl;
+
+class TLSA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+
+ TLSA(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const std::string& certificate_assoc_data);
+ TLSA& operator=(const TLSA& source);
+ ~TLSA();
+
+ ///
+ /// Specialized methods
+ ///
+ uint8_t getCertificateUsage() const;
+ uint8_t getSelector() const;
+ uint8_t getMatchingType() const;
+ const std::vector<uint8_t>& getData() const;
+ size_t getDataLength() const;
+
+private:
+ TLSAImpl* constructFromLexer(MasterLexer& lexer);
+
+ TLSAImpl* impl_;
+};
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
+// END_HEADER_GUARD
+
+// Local Variables:
+// mode: c++
+// End:
run_unittests_SOURCES += rdata_rrsig_unittest.cc
run_unittests_SOURCES += rdata_rp_unittest.cc
run_unittests_SOURCES += rdata_srv_unittest.cc
+run_unittests_SOURCES += rdata_tlsa_unittest.cc
run_unittests_SOURCES += rdata_minfo_unittest.cc
run_unittests_SOURCES += rdata_tsig_unittest.cc
run_unittests_SOURCES += rdata_naptr_unittest.cc
--- /dev/null
+// Copyright (C) 2014 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
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <algorithm>
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <boost/algorithm/string.hpp>
+
+using isc::UnitTestUtil;
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+
+namespace {
+class Rdata_TLSA_Test : public RdataTest {
+protected:
+ Rdata_TLSA_Test() :
+ tlsa_txt("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971"),
+ rdata_tlsa(tlsa_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::TLSA, isc::Exception, isc::Exception>(
+ rdata_str, rdata_tlsa, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::TLSA, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_tlsa, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::TLSA, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_tlsa, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::TLSA, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_tlsa, true, false);
+ }
+
+ const string tlsa_txt;
+ const generic::TLSA rdata_tlsa;
+};
+
+const uint8_t rdata_tlsa_wiredata[] = {
+ // certificate usage
+ 0x00,
+ // selector
+ 0x00,
+ // matching type
+ 0x01,
+ // certificate association data
+ 0xd2, 0xab, 0xde, 0x24, 0x0d, 0x7c, 0xd3, 0xee,
+ 0x6b, 0x4b, 0x28, 0xc5, 0x4d, 0xf0, 0x34, 0xb9,
+ 0x79, 0x83, 0xa1, 0xd1, 0x6e, 0x8a, 0x41, 0x0e,
+ 0x45, 0x61, 0xcb, 0x10, 0x66, 0x18, 0xe9, 0x71
+};
+
+TEST_F(Rdata_TLSA_Test, createFromText) {
+ // Basic test
+ checkFromText_None(tlsa_txt);
+
+ // With different spacing
+ checkFromText_None("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971");
+
+ // Combination of lowercase and uppercase
+ checkFromText_None("0 0 1 D2ABDE240D7CD3EE6B4B28C54DF034B9"
+ "7983a1d16e8a410e4561cb106618e971");
+
+ // spacing in the certificate association data field
+ checkFromText_None("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9"
+ " 7983a1d16e8a410e4561cb106618e971");
+
+ // multi-line certificate association data field
+ checkFromText_None("0 0 1 ( d2abde240d7cd3ee6b4b28c54df034b9\n"
+ " 7983a1d16e8a410e4561cb106618e971 )");
+
+ // string constructor throws if there's extra text,
+ // but lexer constructor doesn't
+ checkFromText_BadString(tlsa_txt + "\n" + tlsa_txt);
+}
+
+TEST_F(Rdata_TLSA_Test, fields) {
+ // Some of these may not be RFC conformant, but we relax the check
+ // in our code to work with other field values that may show up in
+ // the future.
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("1 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("2 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("3 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("128 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("255 0 1 12ab"));
+
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 1 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 2 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 3 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 128 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 255 1 12ab"));
+
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 2 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 3 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 128 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 255 12ab"));
+
+ // > 255 would be broken
+ EXPECT_THROW(const generic::TLSA rdata_tlsa("256 0 1 12ab"),
+ InvalidRdataText);
+ EXPECT_THROW(const generic::TLSA rdata_tlsa("0 256 1 12ab"),
+ InvalidRdataText);
+ EXPECT_THROW(const generic::TLSA rdata_tlsa("0 0 256 12ab"),
+ InvalidRdataText);
+}
+
+TEST_F(Rdata_TLSA_Test, badText) {
+ checkFromText_LexerError("1");
+ checkFromText_LexerError("ONE 2 3 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("1 TWO 3 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("1 2 THREE 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText("1 2 3 BAABAABLACKSHEEP");
+ checkFromText_InvalidText(tlsa_txt + " extra text");
+
+ // yes, these are redundant to the last test cases in the .fields
+ // test
+ checkFromText_InvalidText(
+ "2345 1 2 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText(
+ "3 1234 4 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText(
+ "5 6 1234 123456789abcdef67890123456789abcdef67890");
+
+ // negative values are trapped in the lexer rather than the
+ // constructor
+ checkFromText_LexerError("-2 0 1 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("0 -2 1 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("0 0 -2 123456789abcdef67890123456789abcdef67890");
+}
+
+TEST_F(Rdata_TLSA_Test, copyAndAssign) {
+ // Copy construct
+ generic::TLSA rdata_tlsa2(rdata_tlsa);
+ EXPECT_EQ(0, rdata_tlsa.compare(rdata_tlsa2));
+
+ // Assignment, mainly to confirm it doesn't cause disruption.
+ rdata_tlsa2 = rdata_tlsa;
+ EXPECT_EQ(0, rdata_tlsa.compare(rdata_tlsa2));
+}
+
+TEST_F(Rdata_TLSA_Test, createFromWire) {
+ // Basic test
+ EXPECT_EQ(0, rdata_tlsa.compare(
+ *rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire")));
+ // Combination of lowercase and uppercase
+ EXPECT_EQ(0, rdata_tlsa.compare(
+ *rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire2")));
+ // certificate_usage=0, selector=0, matching_type=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire3.wire"));
+
+ // certificate_usage=255, selector=0, matching_type=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire4.wire"));
+
+ // certificate_usage=0, selector=255, matching_type=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire5.wire"));
+
+ // certificate_usage=0, selector=0, matching_type=255
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire6.wire"));
+
+ // certificate_usage=3, selector=1, matching_type=2
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire7.wire"));
+
+ // short certificate association data
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire8.wire"));
+
+ // certificate association data is shorter than rdata len
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire9"),
+ InvalidBufferPosition);
+
+ // certificate association data is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire10"),
+ InvalidBufferPosition);
+
+ // all RDATA is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire11"),
+ InvalidBufferPosition);
+}
+
+TEST_F(Rdata_TLSA_Test, createFromParams) {
+ const generic::TLSA rdata_tlsa2(
+ 0, 0, 1, "d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971");
+ EXPECT_EQ(0, rdata_tlsa2.compare(rdata_tlsa));
+}
+
+TEST_F(Rdata_TLSA_Test, toText) {
+ EXPECT_TRUE(boost::iequals(tlsa_txt, rdata_tlsa.toText()));
+
+ const string tlsa_txt2("3 2 1");
+ const generic::TLSA rdata_tlsa2(tlsa_txt2);
+ EXPECT_TRUE(boost::iequals(tlsa_txt2, rdata_tlsa2.toText()));
+
+ const generic::TLSA rdata_tlsa3("3 2 1 ");
+ EXPECT_TRUE(boost::iequals(tlsa_txt2, rdata_tlsa3.toText()));
+}
+
+TEST_F(Rdata_TLSA_Test, toWire) {
+ this->obuffer.clear();
+ rdata_tlsa.toWire(this->obuffer);
+
+ EXPECT_EQ(sizeof (rdata_tlsa_wiredata),
+ this->obuffer.getLength());
+
+ EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+ this->obuffer.getData(),
+ this->obuffer.getLength(),
+ rdata_tlsa_wiredata, sizeof(rdata_tlsa_wiredata));
+}
+
+TEST_F(Rdata_TLSA_Test, compare) {
+ const generic::TLSA rdata_tlsa2("0 0 0");
+ EXPECT_EQ(-1, rdata_tlsa2.compare(rdata_tlsa));
+ EXPECT_EQ(1, rdata_tlsa.compare(rdata_tlsa2));
+}
+
+TEST_F(Rdata_TLSA_Test, getCertificateUsage) {
+ EXPECT_EQ(0, rdata_tlsa.getCertificateUsage());
+}
+
+TEST_F(Rdata_TLSA_Test, getSelector) {
+ EXPECT_EQ(0, rdata_tlsa.getSelector());
+}
+
+TEST_F(Rdata_TLSA_Test, getMatchingType) {
+ EXPECT_EQ(1, rdata_tlsa.getMatchingType());
+}
+
+TEST_F(Rdata_TLSA_Test, getDataLength) {
+ EXPECT_EQ(32, rdata_tlsa.getDataLength());
+}
+
+TEST_F(Rdata_TLSA_Test, emptyCertificateAssociationDataFromWire) {
+ const uint8_t rdf_wiredata[] = {
+ // certificate usage
+ 0x03,
+ // selector
+ 0x01,
+ // matching type
+ 0x02,
+ };
+
+ const generic::TLSA rdf =
+ dynamic_cast<const generic::TLSA&>
+ (*rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire12"));
+
+ EXPECT_EQ(3, rdf.getCertificateUsage());
+ EXPECT_EQ(1, rdf.getSelector());
+ EXPECT_EQ(2, rdf.getMatchingType());
+ EXPECT_EQ(0, rdf.getDataLength());
+
+ this->obuffer.clear();
+ rdf.toWire(this->obuffer);
+
+ EXPECT_EQ(3, this->obuffer.getLength());
+
+ EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+ this->obuffer.getData(),
+ this->obuffer.getLength(),
+ rdf_wiredata, sizeof(rdf_wiredata));
+}
+
+TEST_F(Rdata_TLSA_Test, emptyCertificateAssociationDataFromString) {
+ const generic::TLSA rdata_tlsa2("3 2 1");
+ const uint8_t rdata_tlsa2_wiredata[] = {
+ // certificate usage
+ 0x03,
+ // selector
+ 0x02,
+ // matching type
+ 0x01
+ };
+
+ EXPECT_EQ(3, rdata_tlsa2.getCertificateUsage());
+ EXPECT_EQ(2, rdata_tlsa2.getSelector());
+ EXPECT_EQ(1, rdata_tlsa2.getMatchingType());
+ EXPECT_EQ(0, rdata_tlsa2.getDataLength());
+
+ this->obuffer.clear();
+ rdata_tlsa2.toWire(this->obuffer);
+
+ EXPECT_EQ(3, this->obuffer.getLength());
+
+ EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+ this->obuffer.getData(),
+ this->obuffer.getLength(),
+ rdata_tlsa2_wiredata, sizeof(rdata_tlsa2_wiredata));
+}
+}
/rdata_sshfp_fromWire6.wire
/rdata_sshfp_fromWire7.wire
/rdata_sshfp_fromWire8.wire
+/rdata_tlsa_fromWire3.wire
+/rdata_tlsa_fromWire4.wire
+/rdata_tlsa_fromWire5.wire
+/rdata_tlsa_fromWire6.wire
+/rdata_tlsa_fromWire7.wire
+/rdata_tlsa_fromWire8.wire
/rdata_tsig_fromWire1.wire
/rdata_tsig_fromWire2.wire
/rdata_tsig_fromWire3.wire
BUILT_SOURCES += rdata_soa_toWireUncompressed.wire
BUILT_SOURCES += rdata_txt_fromWire2.wire rdata_txt_fromWire3.wire
BUILT_SOURCES += rdata_txt_fromWire4.wire rdata_txt_fromWire5.wire
+BUILT_SOURCES += rdata_tlsa_fromWire3.wire rdata_tlsa_fromWire4.wire
+BUILT_SOURCES += rdata_tlsa_fromWire5.wire rdata_tlsa_fromWire6.wire
+BUILT_SOURCES += rdata_tlsa_fromWire7.wire rdata_tlsa_fromWire8.wire
BUILT_SOURCES += rdata_tsig_fromWire1.wire rdata_tsig_fromWire2.wire
BUILT_SOURCES += rdata_tsig_fromWire3.wire rdata_tsig_fromWire4.wire
BUILT_SOURCES += rdata_tsig_fromWire5.wire rdata_tsig_fromWire6.wire
EXTRA_DIST += rrcode32_fromWire1 rrcode32_fromWire2
EXTRA_DIST += rrset_toWire1 rrset_toWire2
EXTRA_DIST += rrset_toWire3 rrset_toWire4
+EXTRA_DIST += rdata_tlsa_fromWire rdata_tlsa_fromWire2
+EXTRA_DIST += rdata_tlsa_fromWire3.spec rdata_tlsa_fromWire4.spec
+EXTRA_DIST += rdata_tlsa_fromWire5.spec rdata_tlsa_fromWire6.spec
+EXTRA_DIST += rdata_tlsa_fromWire7.spec rdata_tlsa_fromWire8.spec
+EXTRA_DIST += rdata_tlsa_fromWire9 rdata_tlsa_fromWire10
+EXTRA_DIST += rdata_tlsa_fromWire11 rdata_tlsa_fromWire12
EXTRA_DIST += rdata_tsig_fromWire1.spec rdata_tsig_fromWire2.spec
EXTRA_DIST += rdata_tsig_fromWire3.spec rdata_tsig_fromWire4.spec
EXTRA_DIST += rdata_tsig_fromWire5.spec rdata_tsig_fromWire6.spec
--- /dev/null
+# TLSA RDATA, RDLEN=35
+0023
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=...
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
--- /dev/null
+# Test where certificate association data is missing.
+
+# TLSA RDATA, RDLEN=35
+0023
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=(missing)
+00 00 01
--- /dev/null
+# Test where RDATA is completely missing
+
+# TLSA RDATA, RDLEN=35
+0023
--- /dev/null
+# TLSA RDATA, RDLEN=3
+0003
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=(none)
+03 01 02
--- /dev/null
+# TLSA RDATA, RDLEN=35
+0023
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=...
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983A1D16E8A410E4561CB106618E971
--- /dev/null
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_usage: 0
--- /dev/null
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_usage: 255
--- /dev/null
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+selector: 255
--- /dev/null
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+matching_type: 255
--- /dev/null
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_usage: 3
+selector: 1
+matching_type: 2
--- /dev/null
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_association_data: '0123'
--- /dev/null
+# Test where certificate association data length is smaller than what
+# RDATA length indicates.
+
+# TLSA RDATA, RDLEN=64
+0040
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=(32 bytes)
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
'srv' : 33, 'naptr' : 35, 'kx' : 36, 'cert' : 37, 'a6' : 38,
'dname' : 39, 'opt' : 41, 'apl' : 42, 'ds' : 43, 'sshfp' : 44,
'ipseckey' : 45, 'rrsig' : 46, 'nsec' : 47, 'dnskey' : 48,
- 'dhcid' : 49, 'nsec3' : 50, 'nsec3param' : 51, 'hip' : 55,
+ 'dhcid' : 49, 'nsec3' : 50, 'nsec3param' : 51, 'tlsa' : 52, 'hip' : 55,
'spf' : 99, 'unspec' : 103, 'tkey' : 249, 'tsig' : 250,
'dlv' : 32769, 'ixfr' : 251, 'axfr' : 252, 'mailb' : 253,
'maila' : 254, 'any' : 255 }
f.write('# Tag=%d Signer=%s and Signature\n' % (self.tag, self.signer))
f.write('%04x %s %s\n' % (self.tag, name_wire, sig_wire))
+class TLSA(RR):
+ '''Implements rendering TLSA RDATA in the test data format.
+
+ Configurable parameters are as follows (see the description of the
+ same name of attribute for the default value):
+ - certificate_usage (int): The certificate usage field value.
+ - selector (int): The selector field value.
+ - matching_type (int): The matching type field value.
+ - certificate_association_data (string): The certificate association data.
+ '''
+ certificate_usage = 0
+ selector = 0
+ matching_type = 1
+ certificate_association_data = 'd2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971'
+ def dump(self, f):
+ if self.rdlen is None:
+ self.rdlen = 2 + (len(self.certificate_association_data) / 2)
+ else:
+ self.rdlen = int(self.rdlen)
+ self.dump_header(f, self.rdlen)
+ f.write('# CERTIFICATE_USAGE=%d SELECTOR=%d MATCHING_TYPE=%d CERTIFICATE_ASSOCIATION_DATA=%s\n' %\
+ (self.certificate_usage, self.selector, self.matching_type,\
+ self.certificate_association_data))
+ f.write('%02x %02x %02x %s\n' % (self.certificate_usage, self.selector, self.matching_type,\
+ self.certificate_association_data))
+
class TSIG(RR):
'''Implements rendering TSIG RDATA in the test data format.