Commit 3784b469 authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[3432] TSIGKeyInfo now creates and owns a dns::TSIGKey

d2::TSIGKeyInfo now has an instance member for a dns::TSIGKey
instance, which is created during the TSIGKeyInfo's construction.
parent a00bfe54
......@@ -29,14 +29,56 @@ namespace d2 {
// *********************** TSIGKeyInfo *************************
const char* TSIGKeyInfo::MD5_STR = "MD5";
const char* TSIGKeyInfo::SHA1_STR = "SHA1";
const char* TSIGKeyInfo::SHA224_STR = "SHA224";
const char* TSIGKeyInfo::SHA256_STR = "SHA256";
const char* TSIGKeyInfo::SHA384_STR = "SHA384";
const char* TSIGKeyInfo::SHA512_STR = "SHA512";
TSIGKeyInfo::TSIGKeyInfo(const std::string& name, const std::string& algorithm,
const std::string& secret)
:name_(name), algorithm_(algorithm), secret_(secret) {
:name_(name), algorithm_(algorithm), secret_(secret), tsig_key_() {
remakeKey();
}
TSIGKeyInfo::~TSIGKeyInfo() {
}
const dns::Name&
TSIGKeyInfo::stringToAlgorithmName(const std::string& algorithm_id) {
if (boost::iequals(algorithm_id, MD5_STR)) {
return (dns::TSIGKey::HMACMD5_NAME());
}
if (boost::iequals(algorithm_id, SHA1_STR)) {
return (dns::TSIGKey::HMACSHA1_NAME());
}
if (boost::iequals(algorithm_id, SHA224_STR)) {
return (dns::TSIGKey::HMACSHA224_NAME());
}
if (boost::iequals(algorithm_id, SHA256_STR)) {
return (dns::TSIGKey::HMACSHA256_NAME());
}
if (boost::iequals(algorithm_id, SHA384_STR)) {
return (dns::TSIGKey::HMACSHA384_NAME());
}
if (boost::iequals(algorithm_id, SHA512_STR)) {
return (dns::TSIGKey::HMACSHA512_NAME());
}
isc_throw(BadValue, "Unknown TSIG Key algorithm:" << algorithm_id);
}
void
TSIGKeyInfo::remakeKey() {
try {
tsig_key_.reset(new dns::TSIGKey(dns::Name(name_),
stringToAlgorithmName(algorithm_),
secret_.c_str(), secret_.size()));
} catch (const std::exception& ex) {
isc_throw(D2CfgError, "Cannot make TSIGKey: " << ex.what());
}
}
// *********************** DnsServerInfo *************************
......@@ -212,9 +254,6 @@ TSIGKeyInfoParser::build(isc::data::ConstElementPtr key_config) {
local_scalars_.getParam("algorithm", algorithm);
local_scalars_.getParam("secret", secret);
// @todo Validation here is very superficial. This will expand as TSIG
// Key use is more fully implemented.
// Name cannot be blank.
if (name.empty()) {
isc_throw(D2CfgError, "TSIG Key Info must specify name");
......@@ -265,9 +304,6 @@ TSIGKeyInfoParser::createConfigParser(const std::string& config_id) {
void
TSIGKeyInfoParser::commit() {
/// @todo if at some point TSIG keys need some form of runtime resource
/// initialization, such as creating some sort of hash instance in
/// crytpolib. Once TSIG is fully implemented under Trac #3432 we'll know.
}
// *********************** TSIGKeyInfoListParser *************************
......
......@@ -19,6 +19,7 @@
#include <d2/d2_asio.h>
#include <d2/d_cfg_mgr.h>
#include <dhcpsrv/dhcp_parsers.h>
#include <dns/tsig.h>
#include <exceptions/exceptions.h>
#include <boost/foreach.hpp>
......@@ -145,22 +146,39 @@ public:
/// @brief Represents a TSIG Key.
///
/// Currently, this is simple storage class containing the basic attributes of
/// a TSIG Key. It is intended primarily as a reference for working with
/// actual keys and may eventually be replaced by isc::dns::TSIGKey. TSIG Key
/// functionality at this stage is strictly limited to configuration parsing.
/// @todo full functionality for using TSIG during DNS updates will be added
/// in a future release.
/// Acts as both a storage class containing the basic attributes which
/// describe a TSIG Key, as well as owning and providing access to an
/// instance of the actual key (@ref isc::dns::TSIGKey) that can be used
/// by the IO layer for signing and verifying messages.
///
class TSIGKeyInfo {
public:
/// @brief Defines string values for the supported TSIG algorithms
//@{
static const char* MD5_STR;
static const char* SHA1_STR;
static const char* SHA256_STR;
static const char* SHA224_STR;
static const char* SHA384_STR;
static const char* SHA512_STR;
//}@
/// @brief Constructor
///
/// @param name the unique label used to identify this key
/// @param algorithm the name of the encryption alogirthm this key uses.
/// (@todo This will be a fixed list of choices)
/// @param algorithm the id of the encryption alogirthm this key uses.
/// Currently supported values are (case insensitive):
/// -# "MD5"
/// -# "SHA1"
/// -# "SHA224"
/// -# "SHA256"
/// -# "SHA384"
/// -# "SHA512"
///
/// @param secret the secret component of this key
/// @throw D2CfgError if values supplied are invalid:
/// name cannot be blank, algorithm must be a supported value,
/// secret cannot be blank
TSIGKeyInfo(const std::string& name, const std::string& algorithm,
const std::string& secret);
......@@ -174,7 +192,7 @@ public:
return (name_);
}
/// @brief Getter which returns the key's algorithm.
/// @brief Getter which returns the key's algorithm string ID
///
/// @return returns the algorithm as as std::string.
const std::string getAlgorithm() const {
......@@ -188,18 +206,55 @@ public:
return (secret_);
}
/// @brief Getter which returns the TSIG key used to sign and verify
/// messages
///
/// @return const pointer reference to dns::TSIGKey.
const dns::TSIGKeyPtr& getTSIGKey() const {
return (tsig_key_);
}
/// @brief Converts algorithm id to dns::TSIGKey algorithm dns::Name
///
/// @param algorithm_id string value to translate into an algorithm name.
/// Currently supported values are (case insensitive):
/// -# "MD5"
/// -# "SHA1"
/// -# "SHA224"
/// -# "SHA256"
/// -# "SHA384"
/// -# "SHA512"
///
/// @return const reference to a dns::Name containing the alogorithm name
/// @throw BadValue if ID isn't recognized.
static const dns::Name& stringToAlgorithmName(const std::string&
algorithm_id);
private:
/// @brief Creates the actual TSIG key instance member
///
/// Replaces this tsig_key member with a key newly created using the key
/// name, algorithm id, and secret.
/// This method is currently only called by the constructor, however it
/// could be called post-construction should keys ever support expiration.
///
/// @throw D2CfgError with an explanation if the key could not be created.
void remakeKey();
/// @brief The name of the key.
///
/// This value is the unique identifier that domains use to
/// to specify which TSIG key they need.
std::string name_;
/// @brief The algorithm that should be used for this key.
/// @brief The string ID of the algorithm that should be used for this key.
std::string algorithm_;
/// @brief The secret value component of this key.
std::string secret_;
/// @brief The actual TSIG key.
dns::TSIGKeyPtr tsig_key_;
};
/// @brief Defines a pointer for TSIGKeyInfo instances.
......
......@@ -145,6 +145,11 @@ bool checkKey(TSIGKeyInfoPtr key, const char* name,
result = false;
}
if (!key->getTSIGKey()) {
EXPECT_TRUE (key->getTSIGKey());
return false;
}
return (result);
}
......@@ -256,7 +261,7 @@ TEST_F(TSIGKeyInfoTest, invalidEntry) {
// Config with a blank name entry.
std::string config = "{"
" \"name\": \"\" , "
" \"algorithm\": \"md5\" , "
" \"algorithm\": \"MD5\" , "
" \"secret\": \"0123456789\" "
"}";
ASSERT_TRUE(fromJSON(config));
......@@ -276,10 +281,23 @@ TEST_F(TSIGKeyInfoTest, invalidEntry) {
// Verify that build fails on blank algorithm.
EXPECT_THROW(parser_->build(config_set_), D2CfgError);
// Config with an invalid algorithm entry.
config = "{"
" \"name\": \"d2_key_one\" , "
" \"algorithm\": \"bogus\" , "
" \"secret\": \"0123456789\" "
"}";
ASSERT_TRUE(fromJSON(config));
// Verify that build fails on blank algorithm.
EXPECT_THROW(parser_->build(config_set_), D2CfgError);
// Config with a blank secret entry.
config = "{"
" \"name\": \"d2_key_one\" , "
" \"algorithm\": \"md5\" , "
" \"algorithm\": \"MD5\" , "
" \"secret\": \"\" "
"}";
......@@ -295,7 +313,7 @@ TEST_F(TSIGKeyInfoTest, validEntry) {
// Valid entries for TSIG key, all items are required.
std::string config = "{"
" \"name\": \"d2_key_one\" , "
" \"algorithm\": \"md5\" , "
" \"algorithm\": \"MD5\" , "
" \"secret\": \"0123456789\" "
"}";
ASSERT_TRUE(fromJSON(config));
......@@ -314,7 +332,7 @@ TEST_F(TSIGKeyInfoTest, validEntry) {
TSIGKeyInfoPtr& key = gotit->second;
// Verify the key contents.
EXPECT_TRUE(checkKey(key, "d2_key_one", "md5", "0123456789"));
EXPECT_TRUE(checkKey(key, "d2_key_one", "MD5", "0123456789"));
}
/// @brief Verifies that attempting to parse an invalid list of TSIGKeyInfo
......@@ -324,7 +342,7 @@ TEST_F(TSIGKeyInfoTest, invalidTSIGKeyList) {
std::string config = "["
" { \"name\": \"key1\" , "
" \"algorithm\": \"algo1\" ,"
" \"algorithm\": \"MD5\" ,"
" \"secret\": \"secret11\" "
" },"
" { \"name\": \"key2\" , "
......@@ -332,7 +350,7 @@ TEST_F(TSIGKeyInfoTest, invalidTSIGKeyList) {
" \"secret\": \"secret12\" "
" },"
" { \"name\": \"key3\" , "
" \"algorithm\": \"algo3\" ,"
" \"algorithm\": \"MD5\" ,"
" \"secret\": \"secret13\" "
" }"
" ]";
......@@ -354,15 +372,15 @@ TEST_F(TSIGKeyInfoTest, duplicateTSIGKey) {
std::string config = "["
" { \"name\": \"key1\" , "
" \"algorithm\": \"algo1\" ,"
" \"algorithm\": \"MD5\" ,"
" \"secret\": \"secret11\" "
" },"
" { \"name\": \"key2\" , "
" \"algorithm\": \"algo2\" ,"
" \"algorithm\": \"MD5\" ,"
" \"secret\": \"secret12\" "
" },"
" { \"name\": \"key1\" , "
" \"algorithm\": \"algo3\" ,"
" \"algorithm\": \"MD5\" ,"
" \"secret\": \"secret13\" "
" }"
" ]";
......@@ -378,21 +396,34 @@ TEST_F(TSIGKeyInfoTest, duplicateTSIGKey) {
}
/// @brief Verifies a valid list of TSIG Keys parses correctly.
/// Also verifies that all of the supported algorithm names work.
TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
// Construct a valid list of keys.
std::string config = "["
" { \"name\": \"key1\" , "
" \"algorithm\": \"algo1\" ,"
" \"algorithm\": \"MD5\" ,"
" \"secret\": \"secret1\" "
" },"
" { \"name\": \"key2\" , "
" \"algorithm\": \"algo2\" ,"
" \"algorithm\": \"SHA1\" ,"
" \"secret\": \"secret2\" "
" },"
" { \"name\": \"key3\" , "
" \"algorithm\": \"algo3\" ,"
" \"algorithm\": \"SHA256\" ,"
" \"secret\": \"secret3\" "
" },"
" { \"name\": \"key4\" , "
" \"algorithm\": \"SHA224\" ,"
" \"secret\": \"secret4\" "
" },"
" { \"name\": \"key5\" , "
" \"algorithm\": \"SHA384\" ,"
" \"secret\": \"secret5\" "
" },"
" { \"name\": \"key6\" , "
" \"algorithm\": \"SHA512\" ,"
" \"secret\": \"secret6\" "
" }"
" ]";
......@@ -407,7 +438,7 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
// Verify the correct number of keys are present
int count = keys_->size();
ASSERT_EQ(3, count);
ASSERT_EQ(6, count);
// Find the 1st key and retrieve it.
TSIGKeyInfoMap::iterator gotit = keys_->find("key1");
......@@ -415,7 +446,7 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
TSIGKeyInfoPtr& key = gotit->second;
// Verify the key contents.
EXPECT_TRUE(checkKey(key, "key1", "algo1", "secret1"));
EXPECT_TRUE(checkKey(key, "key1", TSIGKeyInfo::MD5_STR, "secret1"));
// Find the 2nd key and retrieve it.
gotit = keys_->find("key2");
......@@ -423,7 +454,7 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
key = gotit->second;
// Verify the key contents.
EXPECT_TRUE(checkKey(key, "key2", "algo2", "secret2"));
EXPECT_TRUE(checkKey(key, "key2", TSIGKeyInfo::SHA1_STR, "secret2"));
// Find the 3rd key and retrieve it.
gotit = keys_->find("key3");
......@@ -431,7 +462,31 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
key = gotit->second;
// Verify the key contents.
EXPECT_TRUE(checkKey(key, "key3", "algo3", "secret3"));
EXPECT_TRUE(checkKey(key, "key3", TSIGKeyInfo::SHA256_STR, "secret3"));
// Find the 4th key and retrieve it.
gotit = keys_->find("key4");
ASSERT_TRUE(gotit != keys_->end());
key = gotit->second;
// Verify the key contents.
EXPECT_TRUE(checkKey(key, "key4", TSIGKeyInfo::SHA224_STR, "secret4"));
// Find the 5th key and retrieve it.
gotit = keys_->find("key5");
ASSERT_TRUE(gotit != keys_->end());
key = gotit->second;
// Verify the key contents.
EXPECT_TRUE(checkKey(key, "key5", TSIGKeyInfo::SHA384_STR, "secret5"));
// Find the 6th key and retrieve it.
gotit = keys_->find("key6");
ASSERT_TRUE(gotit != keys_->end());
key = gotit->second;
// Verify the key contents.
EXPECT_TRUE(checkKey(key, "key6", TSIGKeyInfo::SHA512_STR, "secret6"));
}
/// @brief Tests the enforcement of data validation when parsing DnsServerInfos.
......@@ -743,8 +798,8 @@ TEST_F(DdnsDomainTest, DdnsDomainListParsing) {
ASSERT_TRUE(fromJSON(config));
// Add keys to key map so key validation passes.
addKey("d2_key.tmark.org", "algo1", "secret1");
addKey("d2_key.billcat.net", "algo2", "secret2");
addKey("d2_key.tmark.org", "MD5", "secret1");
addKey("d2_key.billcat.net", "MD5", "secret2");
// Create the list parser
isc::dhcp::ParserPtr list_parser;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment