Commit 5b2b5a2c authored by Xie Jiagui's avatar Xie Jiagui
Browse files

Merge branch 'master' into trac1580

parents 2217a659 af00b019
380. [bug] jinmei
libdns++: miscellaneous bug fixes for the NSECPARAM RDATA
implementation, including incorrect handling for empty salt and
incorrect comparison logic.
(Trac #1638, git 966c129cc3c538841421f1e554167d33ef9bdf25)
379. [bug] jelte
Configuration commands in bindctl now check for list indices if
the 'identifier' argument points to a child element of a list
item. Previously, it was possible to 'get' non-existent values
by leaving out the index, e.g. "config show Auth/listen_on/port,
which should be config show Auth/listen_on[<index>]/port, since
Auth/listen_on is a list. The command without an index will now
show an error. It is still possible to show/set the entire list
("config show Auth/listen_on").
(Trac #1649, git 003ca8597c8d0eb558b1819dbee203fda346ba77)
378. [func] vorner
It possible to start authoritative server or resolver in multiple
It is possible to start authoritative server or resolver in multiple
instances, to use more than one core. Configuration is described in
the guide.
(Trac #1596, git 17f7af0d8a42a0a67a2aade5bc269533efeb840a)
......
......@@ -907,7 +907,7 @@ AC_PATH_PROGS(AWK, gawk awk)
AC_SUBST(AWK)
AC_ARG_ENABLE(man, [AC_HELP_STRING([--enable-man],
[regenerate man pages [default=no]])], enable_man=yes, enable_man=no)
[regenerate man pages [default=no]])], enable_man=$enableval, enable_man=no)
AM_CONDITIONAL(ENABLE_MAN, test x$enable_man != xno)
......
......@@ -216,7 +216,7 @@
"item_optional": true,
"item_default": 0,
"item_title": "Received requests opcode 8",
"item_description": "The number of total request counts whose opcode is8 (reserved)"
"item_description": "The number of total request counts whose opcode is 8 (reserved)"
},
{
"item_name": "opcode.reserved9",
......@@ -224,7 +224,7 @@
"item_optional": true,
"item_default": 0,
"item_title": "Received requests opcode 9",
"item_description": "The number of total request counts whose opcode is9 (reserved)"
"item_description": "The number of total request counts whose opcode is 9 (reserved)"
},
{
"item_name": "opcode.reserved10",
......@@ -232,7 +232,7 @@
"item_optional": true,
"item_default": 0,
"item_title": "Received requests opcode 10",
"item_description": "The number of total request counts whose opcode is10 (reserved)"
"item_description": "The number of total request counts whose opcode is 10 (reserved)"
},
{
"item_name": "opcode.reserved11",
......@@ -240,7 +240,7 @@
"item_optional": true,
"item_default": 0,
"item_title": "Received requests opcode 11",
"item_description": "The number of total request counts whose opcode is11 (reserved)"
"item_description": "The number of total request counts whose opcode is 11 (reserved)"
},
{
"item_name": "opcode.reserved12",
......@@ -248,7 +248,7 @@
"item_optional": true,
"item_default": 0,
"item_title": "Received requests opcode 12",
"item_description": "The number of total request counts whose opcode is12 (reserved)"
"item_description": "The number of total request counts whose opcode is 12 (reserved)"
},
{
"item_name": "opcode.reserved13",
......@@ -256,7 +256,7 @@
"item_optional": true,
"item_default": 0,
"item_title": "Received requests opcode 13",
"item_description": "The number of total request counts whose opcode is13 (reserved)"
"item_description": "The number of total request counts whose opcode is 13 (reserved)"
},
{
"item_name": "opcode.reserved14",
......@@ -264,7 +264,7 @@
"item_optional": true,
"item_default": 0,
"item_title": "Received requests opcode 14",
"item_description": "The number of total request counts whose opcode is14 (reserved)"
"item_description": "The number of total request counts whose opcode is 14 (reserved)"
},
{
"item_name": "opcode.reserved15",
......@@ -272,7 +272,7 @@
"item_optional": true,
"item_default": 0,
"item_title": "Received requests opcode 15",
"item_description": "The number of total request counts whose opcode is15 (reserved)"
"item_description": "The number of total request counts whose opcode is 15 (reserved)"
}
]
}
......
......@@ -23,6 +23,8 @@ EXTRA_DIST += rdata/generic/cname_5.cc
EXTRA_DIST += rdata/generic/cname_5.h
EXTRA_DIST += rdata/generic/detail/nsec_bitmap.cc
EXTRA_DIST += rdata/generic/detail/nsec_bitmap.h
EXTRA_DIST += rdata/generic/detail/nsec3param_common.cc
EXTRA_DIST += rdata/generic/detail/nsec3param_common.h
EXTRA_DIST += rdata/generic/detail/txt_like.h
EXTRA_DIST += rdata/generic/detail/ds_like.h
EXTRA_DIST += rdata/generic/dlv_32769.cc
......@@ -113,6 +115,8 @@ libdns___la_SOURCES += tsigrecord.h tsigrecord.cc
libdns___la_SOURCES += character_string.h character_string.cc
libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
libdns___la_SOURCES += rdata/generic/detail/nsec3param_common.cc
libdns___la_SOURCES += rdata/generic/detail/nsec3param_common.h
libdns___la_SOURCES += rdata/generic/detail/txt_like.h
libdns___la_SOURCES += rdata/generic/detail/ds_like.h
......
// Copyright (C) 2012 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 <exceptions/exceptions.h>
#include <util/encode/hex.h>
#include <util/buffer.h>
#include <dns/exceptions.h>
#include <dns/rdata.h>
#include <dns/rdata/generic/detail/nsec3param_common.h>
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <vector>
#include <stdint.h>
using namespace std;
using namespace isc::util;
using namespace isc::util::encode;
namespace isc {
namespace dns {
namespace rdata {
namespace generic {
namespace detail {
namespace nsec3 {
ParseNSEC3ParamResult
parseNSEC3ParamText(const char* const rrtype_name,
const string& rdata_str, istringstream& iss,
vector<uint8_t>& salt)
{
unsigned int hashalg, flags, iterations;
string iterations_str, salthex;
iss >> hashalg >> flags >> iterations_str >> salthex;
if (iss.bad() || iss.fail()) {
isc_throw(InvalidRdataText, "Invalid " << rrtype_name <<
" text: " << rdata_str);
}
if (hashalg > 0xff) {
isc_throw(InvalidRdataText, rrtype_name <<
" hash algorithm out of range: " << hashalg);
}
if (flags > 0xff) {
isc_throw(InvalidRdataText, rrtype_name << " flags out of range: " <<
flags);
}
// Convert iteration. To reject an invalid case where there's no space
// between iteration and salt, we extract this field as string and convert
// to integer.
try {
iterations = boost::lexical_cast<unsigned int>(iterations_str);
} catch (const boost::bad_lexical_cast&) {
isc_throw(InvalidRdataText, "Bad " << rrtype_name <<
" iteration: " << iterations_str);
}
if (iterations > 0xffff) {
isc_throw(InvalidRdataText, rrtype_name <<
" iterations out of range: " <<
iterations);
}
// Salt is up to 255 bytes, and space is not allowed in the HEX encoding,
// so the encoded string cannot be longer than the double of max length
// of the actual salt.
if (salthex.size() > 255 * 2) {
isc_throw(InvalidRdataText, rrtype_name << " salt is too long: "
<< salthex.size() << " (encoded) bytes");
}
if (salthex != "-") { // "-" means a 0-length salt
decodeHex(salthex, salt);
}
return (ParseNSEC3ParamResult(hashalg, flags, iterations));
}
ParseNSEC3ParamResult
parseNSEC3ParamWire(const char* const rrtype_name,
InputBuffer& buffer,
size_t& rdata_len, std::vector<uint8_t>& salt)
{
// NSEC3/NSEC3PARAM RR must have at least 5 octets:
// hash algorithm(1), flags(1), iteration(2), saltlen(1)
if (rdata_len < 5) {
isc_throw(DNSMessageFORMERR, rrtype_name << " too short, length: "
<< rdata_len);
}
const uint8_t hashalg = buffer.readUint8();
const uint8_t flags = buffer.readUint8();
const uint16_t iterations = buffer.readUint16();
const uint8_t saltlen = buffer.readUint8();
rdata_len -= 5;
if (rdata_len < saltlen) {
isc_throw(DNSMessageFORMERR, rrtype_name <<
" salt length is too large: " <<
static_cast<unsigned int>(saltlen));
}
salt.resize(saltlen);
if (saltlen > 0) {
buffer.readData(&salt[0], saltlen);
rdata_len -= saltlen;
}
return (ParseNSEC3ParamResult(hashalg, flags, iterations));
}
} // end of nsec3
} // end of detail
} // end of generic
} // end of rdata
} // end of dns
} // end of isc
// Copyright (C) 2012 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.
#ifndef __NSEC3PARAM_COMMON_H
#define __NSEC3PARAM_COMMON_H 1
#include <util/buffer.h>
#include <stdint.h>
#include <sstream>
#include <string>
#include <vector>
namespace isc {
namespace dns {
namespace rdata {
namespace generic {
namespace detail {
namespace nsec3 {
/// \file
///
/// This helper module provides some utilities that handle NSEC3 and
/// NSEC3PARAM RDATA. They share the first few fields, and some operations
/// on these fields are sufficiently complicated, so it would make sense to
/// consolidate the processing logic into a single implementation module.
///
/// The functions defined here are essentially private and are only expected
/// to be called from the \c NSEC3 and \c NSEC3PARAM class implementations.
/// \brief Result values of the utilities.
///
/// This structure encapsulates a tuple of NSEC3/NSEC3PARAM algorithm,
/// flags and iterations field values. This is used as the return value
/// of the utility functions defined in this module so the caller can
/// use it for constructing the corresponding RDATA.
struct ParseNSEC3ParamResult {
ParseNSEC3ParamResult(uint8_t param_algorithm, uint8_t param_flags,
uint16_t param_iterations) :
algorithm(param_algorithm), flags(param_flags),
iterations(param_iterations)
{}
const uint8_t algorithm;
const uint8_t flags;
const uint16_t iterations;
};
/// \brief Convert textual representation of NSEC3 parameters.
///
/// This function takes an input string stream that consists of a complete
/// textual representation of an NSEC3 or NSEC3PARAM RDATA and parses it
/// extracting the hash algorithm, flags, iterations, and salt fields.
///
/// The first three fields are returned as the return value of this function.
/// The salt will be stored in the given vector. The vector is expected
/// to be empty, but if not, the existing content will be overridden.
///
/// On successful return the given input stream will reach the end of the
/// salt field.
///
/// \exception isc::BadValue The salt is not a valid hex string.
/// \exception InvalidRdataText The given string is otherwise invalid for
/// NSEC3 or NSEC3PARAM fields.
///
/// \param rrtype_name Either "NSEC3" or "NSEC3PARAM"; used as part of
/// exception messages.
/// \param rdata_str A complete textual string of the RDATA; used as part of
/// exception messages.
/// \param iss Input stream that consists of a complete textual string of
/// the RDATA.
/// \param salt A placeholder for the salt field value of the RDATA.
/// Expected to be empty, but it's not checked (and will be overridden).
///
/// \return The hash algorithm, flags, iterations in the form of
/// ParseNSEC3ParamResult.
ParseNSEC3ParamResult parseNSEC3ParamText(const char* const rrtype_name,
const std::string& rdata_str,
std::istringstream& iss,
std::vector<uint8_t>& salt);
/// \brief Extract NSEC3 parameters from wire-format data.
///
/// This function takes an input buffer that stores wire-format NSEC3 or
/// NSEC3PARAM RDATA and parses it extracting the hash algorithm, flags,
/// iterations, and salt fields.
///
/// The first three fields are returned as the return value of this function.
/// The salt will be stored in the given vector. The vector is expected
/// to be empty, but if not, the existing content will be overridden.
///
/// On successful return the input buffer will point to the end of the
/// salt field; rdata_len will be the length of the rest of RDATA
/// (in the case of a valid NSEC3PARAM, it should be 0).
///
/// \exception DNSMessageFORMERR The wire data is invalid.
///
/// \param rrtype_name Either "NSEC3" or "NSEC3PARAM"; used as part of
/// exception messages.
/// \param buffer An input buffer that stores wire-format RDATA. It must
/// point to the beginning of the data.
/// \param rdata_len The total length of the RDATA.
/// \param salt A placeholder for the salt field value of the RDATA.
/// Expected to be empty, but it's not checked (and will be overridden).
///
/// \return The hash algorithm, flags, iterations in the form of
/// ParseNSEC3ParamResult.
ParseNSEC3ParamResult parseNSEC3ParamWire(const char* const rrtype_name,
isc::util::InputBuffer& buffer,
size_t& rdata_len,
std::vector<uint8_t>& salt);
}
}
}
}
}
}
#endif // __NSEC3PARAM_COMMON_H
// Local Variables:
// mode: c++
// End:
......@@ -12,6 +12,9 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __NSECBITMAP_H
#define __NSECBITMAP_H 1
#include <stdint.h>
#include <sstream>
......@@ -97,6 +100,8 @@ void bitmapsToText(const std::vector<uint8_t>& typebits,
}
}
#endif // __NSECBITMAP_H
// Local Variables:
// mode: c++
// End:
......@@ -17,6 +17,7 @@
#include <string>
#include <sstream>
#include <vector>
#include <cassert>
#include <boost/lexical_cast.hpp>
......@@ -32,12 +33,14 @@
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdata/generic/detail/nsec_bitmap.h>
#include <dns/rdata/generic/detail/nsec3param_common.h>
#include <stdio.h>
#include <time.h>
using namespace std;
using namespace isc::dns::rdata::generic::detail::nsec;
using namespace isc::dns::rdata::generic::detail::nsec3;
using namespace isc::util::encode;
using namespace isc::util;
......@@ -65,42 +68,20 @@ NSEC3::NSEC3(const string& nsec3_str) :
impl_(NULL)
{
istringstream iss(nsec3_str);
unsigned int hashalg, flags, iterations;
string iterations_str, salthex, nexthash;
vector<uint8_t> salt;
const ParseNSEC3ParamResult params =
parseNSEC3ParamText("NSEC3", nsec3_str, iss, salt);
iss >> hashalg >> flags >> iterations_str >> salthex >> nexthash;
// Extract Next hash. It must be an unpadded base32hex string.
string nexthash;
iss >> nexthash;
if (iss.bad() || iss.fail()) {
isc_throw(InvalidRdataText, "Invalid NSEC3 text: " << nsec3_str);
}
if (hashalg > 0xff) {
isc_throw(InvalidRdataText,
"NSEC3 hash algorithm out of range: " << hashalg);
}
if (flags > 0xff) {
isc_throw(InvalidRdataText, "NSEC3 flags out of range: " << flags);
}
// Convert iteration. To reject an invalid case where there's no space
// between iteration and salt, we extract this field as string and convert
// to integer.
try {
iterations = boost::lexical_cast<unsigned int>(iterations_str);
} catch (const boost::bad_lexical_cast&) {
isc_throw(InvalidRdataText, "Bad NSEC3 iteration: " << iterations_str);
assert(!nexthash.empty());
if (*nexthash.rbegin() == '=') {
isc_throw(InvalidRdataText, "NSEC3 hash has padding: " << nsec3_str);
}
if (iterations > 0xffff) {
isc_throw(InvalidRdataText, "NSEC3 iterations out of range: " <<
iterations);
}
vector<uint8_t> salt;
if (salthex != "-") { // "-" means a 0-length salt
decodeHex(salthex, salt);
}
if (salt.size() > 255) {
isc_throw(InvalidRdataText, "NSEC3 salt is too long: "
<< salt.size() << " bytes");
}
vector<uint8_t> next;
decodeBase32Hex(nexthash, next);
if (next.size() > 255) {
......@@ -110,7 +91,8 @@ NSEC3::NSEC3(const string& nsec3_str) :
// For NSEC3 empty bitmap is possible and allowed.
if (iss.eof()) {
impl_ = new NSEC3Impl(hashalg, flags, iterations, salt, next,
impl_ = new NSEC3Impl(params.algorithm, params.flags,
params.iterations, salt, next,
vector<uint8_t>());
return;
}
......@@ -118,36 +100,18 @@ NSEC3::NSEC3(const string& nsec3_str) :
vector<uint8_t> typebits;
buildBitmapsFromText("NSEC3", iss, typebits);
impl_ = new NSEC3Impl(hashalg, flags, iterations, salt, next, typebits);
impl_ = new NSEC3Impl(params.algorithm, params.flags, params.iterations,
salt, next, typebits);
}
NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) {
// NSEC3 RR must have at least 5 octets:
// hash algorithm(1), flags(1), iteration(2), saltlen(1)
if (rdata_len < 5) {
isc_throw(DNSMessageFORMERR, "NSEC3 too short, length: " << rdata_len);
}
const uint8_t hashalg = buffer.readUint8();
const uint8_t flags = buffer.readUint8();
const uint16_t iterations = buffer.readUint16();
const uint8_t saltlen = buffer.readUint8();
rdata_len -= 5;
if (rdata_len < saltlen) {
isc_throw(DNSMessageFORMERR, "NSEC3 salt length is too large: " <<
static_cast<unsigned int>(saltlen));
}
vector<uint8_t> salt(saltlen);
if (saltlen > 0) {
buffer.readData(&salt[0], saltlen);
rdata_len -= saltlen;
}
vector<uint8_t> salt;
const ParseNSEC3ParamResult params =
parseNSEC3ParamWire("NSEC3", buffer, rdata_len, salt);
if (rdata_len < 1) {
isc_throw(DNSMessageFORMERR, "NSEC3 too short to contain hash length, "
"length: " << rdata_len + saltlen + 5);
"length: " << rdata_len + salt.size() + 5);
}
const uint8_t nextlen = buffer.readUint8();
--rdata_len;
......@@ -168,7 +132,8 @@ NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) {
checkRRTypeBitmaps("NSEC3", typebits);
}
impl_ = new NSEC3Impl(hashalg, flags, iterations, salt, next, typebits);
impl_ = new NSEC3Impl(params.algorithm, params.flags, params.iterations,
salt, next, typebits);
}
NSEC3::NSEC3(const NSEC3& source) :
......@@ -256,10 +221,10 @@ compareVectors(const vector<uint8_t>& v1, const vector<uint8_t>& v2,
{
const size_t len1 = v1.size();
const size_t len2 = v2.size();
const size_t cmplen = min(len1, len2);
if (check_length_first && len1 != len2) {
return (len1 - len2);
}
const size_t cmplen = min(len1, len2);
const int cmp = cmplen == 0 ? 0 : memcmp(&v1.at(0), &v2.at(0), cmplen);
if (cmp != 0) {
return (cmp);
......
......@@ -12,22 +12,19 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <boost/lexical_cast.hpp>
#include <util/buffer.h>
#include <util/encode/hex.h>
#include <dns/messagerenderer.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdata/generic/detail/nsec3param_common.h>
#include <boost/lexical_cast.hpp>
#include <stdio.h>
#include <time.h>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
using namespace isc::util;
......@@ -43,9 +40,9 @@ struct NSEC3PARAMImpl {
hashalg_(hashalg), flags_(flags), iterations_(iterations), salt_(salt)
{}
uint8_t hashalg_;
uint8_t flags_;
uint16_t iterations_;
const uint8_t hashalg_;
const uint8_t flags_;
const uint16_t iterations_;
const vector<uint8_t> salt_;
};
......@@ -53,50 +50,26 @@ NSEC3PARAM::NSEC3PARAM(const string& nsec3param_str) :
impl_(NULL)
{
istringstream iss(nsec3param_str);
uint16_t hashalg, flags, iterations;
stringbuf saltbuf;
iss >> hashalg >> flags >> iterations >> &saltbuf;
if (iss.bad() || iss.fail()) {
isc_throw(InvalidRdataText, "Invalid NSEC3PARAM text");
}
if (hashalg > 0xf) {
isc_throw(InvalidRdataText, "NSEC3PARAM hash algorithm out of range");
}
if (flags > 0xff) {
isc_throw(InvalidRdataText, "NSEC3PARAM flags out of range");
}
const string salt_str = saltbuf.str();