123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- // 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
- // 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 <string>
- #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 SSHFPImpl {
- // straightforward representation of SSHFP RDATA fields
- SSHFPImpl(uint8_t algorithm, uint8_t fingerprint_type,
- vector<uint8_t>& fingerprint) :
- algorithm_(algorithm),
- fingerprint_type_(fingerprint_type),
- fingerprint_(fingerprint)
- {}
- uint8_t algorithm_;
- uint8_t fingerprint_type_;
- const vector<uint8_t> fingerprint_;
- };
- // helper function for string and lexer constructors
- SSHFPImpl*
- SSHFP::constructFromLexer(MasterLexer& lexer) {
- const uint32_t algorithm =
- lexer.getNextToken(MasterToken::NUMBER).getNumber();
- if (algorithm > 255) {
- isc_throw(InvalidRdataText, "SSHFP algorithm number out of range");
- }
- const uint32_t fingerprint_type =
- lexer.getNextToken(MasterToken::NUMBER).getNumber();
- if (fingerprint_type > 255) {
- isc_throw(InvalidRdataText, "SSHFP fingerprint type out of range");
- }
- const MasterToken& token = lexer.getNextToken(MasterToken::STRING, true);
- vector<uint8_t> fingerprint;
- if ((token.getType() != MasterToken::END_OF_FILE) &&
- (token.getType() != MasterToken::END_OF_LINE)) {
- decodeHex(token.getString(), fingerprint);
- }
- return (new SSHFPImpl(algorithm, fingerprint_type, fingerprint));
- }
- /// \brief Constructor from string.
- ///
- /// The given string must represent a valid SSHFP 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 Algorithm and Fingerprint Type fields must be within their valid
- /// ranges, but are not contrained to the values defined in RFC4255.
- ///
- /// The Fingerprint field may be absent, but if present it must contain a
- /// valid hex encoding of the fingerprint.
- ///
- /// \throw InvalidRdataText if any fields are missing, out of their valid
- /// ranges, or incorrect.
- ///
- /// \param sshfp_str A string containing the RDATA to be created
- SSHFP::SSHFP(const string& sshfp_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 SSHFPImpl that constructFromLexer() returns.
- std::auto_ptr<SSHFPImpl> impl_ptr(NULL);
- try {
- std::istringstream ss(sshfp_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 SSHFP: "
- << sshfp_str);
- }
- } catch (const MasterLexer::LexerError& ex) {
- isc_throw(InvalidRdataText, "Failed to construct SSHFP from '" <<
- sshfp_str << "': " << ex.what());
- } catch (const isc::BadValue& e) {
- isc_throw(InvalidRdataText,
- "Bad SSHFP fingerprint: " << e.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 SSHFP RDATA.
- ///
- /// \throw MasterLexer::LexerError General parsing error such as missing field.
- /// \throw InvalidRdataText Fields are out of their valid range, or are
- /// incorrect.
- /// \throw BadValue Fingerprint is not a valid hex string.
- ///
- /// \param lexer A \c MasterLexer object parsing a master file for the
- /// RDATA to be created
- SSHFP::SSHFP(MasterLexer& lexer, const Name*,
- MasterLoader::Options, MasterLoaderCallbacks&) :
- impl_(NULL)
- {
- impl_ = constructFromLexer(lexer);
- }
- /// \brief Constructor from InputBuffer.
- ///
- /// The passed buffer must contain a valid SSHFP RDATA.
- ///
- /// The Algorithm and Fingerprint Type fields are not checked for unknown
- /// values. It is okay for the fingerprint data to be missing (see the
- /// description of the constructor from string).
- SSHFP::SSHFP(InputBuffer& buffer, size_t rdata_len) {
- if (rdata_len < 2) {
- isc_throw(InvalidRdataLength, "SSHFP record too short");
- }
- const uint8_t algorithm = buffer.readUint8();
- const uint8_t fingerprint_type = buffer.readUint8();
- vector<uint8_t> fingerprint;
- rdata_len -= 2;
- if (rdata_len > 0) {
- fingerprint.resize(rdata_len);
- buffer.readData(&fingerprint[0], rdata_len);
- }
- impl_ = new SSHFPImpl(algorithm, fingerprint_type, fingerprint);
- }
- SSHFP::SSHFP(uint8_t algorithm, uint8_t fingerprint_type,
- const string& fingerprint_txt) :
- impl_(NULL)
- {
- vector<uint8_t> fingerprint;
- try {
- decodeHex(fingerprint_txt, fingerprint);
- } catch (const isc::BadValue& e) {
- isc_throw(InvalidRdataText, "Bad SSHFP fingerprint: " << e.what());
- }
- impl_ = new SSHFPImpl(algorithm, fingerprint_type, fingerprint);
- }
- SSHFP::SSHFP(const SSHFP& other) :
- Rdata(), impl_(new SSHFPImpl(*other.impl_))
- {}
- SSHFP::~SSHFP() {
- delete impl_;
- }
- void
- SSHFP::toWire(OutputBuffer& buffer) const {
- buffer.writeUint8(impl_->algorithm_);
- buffer.writeUint8(impl_->fingerprint_type_);
- if (!impl_->fingerprint_.empty()) {
- buffer.writeData(&impl_->fingerprint_[0],
- impl_->fingerprint_.size());
- }
- }
- void
- SSHFP::toWire(AbstractMessageRenderer& renderer) const {
- renderer.writeUint8(impl_->algorithm_);
- renderer.writeUint8(impl_->fingerprint_type_);
- if (!impl_->fingerprint_.empty()) {
- renderer.writeData(&impl_->fingerprint_[0],
- impl_->fingerprint_.size());
- }
- }
- string
- SSHFP::toText() const {
- return (lexical_cast<string>(static_cast<int>(impl_->algorithm_)) + " " +
- lexical_cast<string>(static_cast<int>(impl_->fingerprint_type_)) +
- (impl_->fingerprint_.empty() ? "" :
- " " + encodeHex(impl_->fingerprint_)));
- }
- int
- SSHFP::compare(const Rdata& other) const {
- const SSHFP& other_sshfp = dynamic_cast<const SSHFP&>(other);
- if (impl_->algorithm_ < other_sshfp.impl_->algorithm_) {
- return (-1);
- } else if (impl_->algorithm_ > other_sshfp.impl_->algorithm_) {
- return (1);
- }
- if (impl_->fingerprint_type_ < other_sshfp.impl_->fingerprint_type_) {
- return (-1);
- } else if (impl_->fingerprint_type_ >
- other_sshfp.impl_->fingerprint_type_) {
- return (1);
- }
- const size_t this_len = impl_->fingerprint_.size();
- const size_t other_len = other_sshfp.impl_->fingerprint_.size();
- const size_t cmplen = min(this_len, other_len);
- if (cmplen > 0) {
- const int cmp = memcmp(&impl_->fingerprint_[0],
- &other_sshfp.impl_->fingerprint_[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
- SSHFP::getAlgorithmNumber() const {
- return (impl_->algorithm_);
- }
- uint8_t
- SSHFP::getFingerprintType() const {
- return (impl_->fingerprint_type_);
- }
- size_t
- SSHFP::getFingerprintLen() const {
- return (impl_->fingerprint_.size());
- }
- // END_RDATA_NAMESPACE
- // END_ISC_NAMESPACE
|