Browse Source

[5110] D2 TSIG key list now uses bison parsing and SimpleParsers

src/bin/d2/d2_cfg_mgr.cc
    D2CfgMgr::parseElement() - now handles tsig-keys

src/bin/d2/d2_config.h
src/bin/d2/d2_config.cc
    TSIGKeyInfoParser and TSIGKeyInfoListParser now
    derive from SimpleParser

src/bin/d2/d2_lexer.ll
    Added algoritm, digest-bits, secret regexps

src/bin/d2/d2_parser.yy
    Added ALGORITHM, DIGEST_BITS, SECRET tokens
    Added rules for "tsig-keys"

src/bin/d2/parser_context.h
src/bin/d2/parser_context.cc
    Added contexts: TSIG_KEYS, ALGORITHM, DIGEST_BITS, SECRET

src/bin/d2/tests/d2_cfg_mgr_unittests.cc
    Revamped TSIG key tests

src/bin/d2/tests/testdata/d2_cfg_tests.json
    changed appropriate logic-errors to syntax-errors
Thomas Markwalder 8 years ago
parent
commit
4647edb247

+ 9 - 14
src/bin/d2/d2_cfg_mgr.cc

@@ -264,11 +264,17 @@ D2CfgMgr::parseElement(const std::string& element_id,
             (element_id == "ncr-format") ||
             (element_id == "port")  ||
             (element_id == "dns-server-timeout"))  {
-            // global scalar params require nothing extra
+            // global scalar params require nothing extra be done
+        } else if (element_id == "tsig-keys") {
+            TSIGKeyInfoListParser parser;
+            getD2CfgContext()->setKeys(parser.parse(element));
         } else {
             // not something we handle here
             return (false);
         }
+    } catch (const D2CfgError& ex) {
+        // Should already have a specific error and postion info
+        throw ex;
     } catch (const std::exception& ex) {
         isc_throw(D2CfgError, "element: " << element_id << " : "  << ex.what()
                               << element->getPosition());
@@ -297,6 +303,7 @@ D2CfgMgr::buildParams(isc::data::ConstElementPtr params_config) {
     dhcp_ddns::NameChangeProtocol ncr_protocol = dhcp_ddns::NCR_UDP;
     dhcp_ddns::NameChangeFormat ncr_format = dhcp_ddns::FMT_JSON;
 
+    // Assumes that params_config has had defaults added
     BOOST_FOREACH(isc::dhcp::ConfigPair param, params_config->mapValue()) {
         std::string entry(param.first);
         isc::data::ConstElementPtr value(param.second);
@@ -358,16 +365,7 @@ D2CfgMgr::createConfigParser(const std::string& config_id,
 
     // Create parser instance based on element_id.
     isc::dhcp::ParserPtr parser;
-    if ((config_id.compare("port") == 0) ||
-        (config_id.compare("dns-server-timeout") == 0)) {
-        parser.reset(new isc::dhcp::Uint32Parser(config_id,
-                                                 context->getUint32Storage()));
-    } else if ((config_id.compare("ip-address") == 0) ||
-        (config_id.compare("ncr-protocol") == 0) ||
-        (config_id.compare("ncr-format") == 0)) {
-        parser.reset(new isc::dhcp::StringParser(config_id,
-                                                 context->getStringStorage()));
-    } else if (config_id ==  "forward-ddns") {
+    if (config_id ==  "forward-ddns") {
         parser.reset(new DdnsDomainListMgrParser("forward-ddns",
                                                  context->getForwardMgr(),
                                                  context->getKeys()));
@@ -375,9 +373,6 @@ D2CfgMgr::createConfigParser(const std::string& config_id,
         parser.reset(new DdnsDomainListMgrParser("reverse-ddns",
                                                  context->getReverseMgr(),
                                                  context->getKeys()));
-    } else if (config_id ==  "tsig-keys") {
-        parser.reset(new TSIGKeyInfoListParser("tsig-key-list",
-                                               context->getKeys()));
     } else {
         isc_throw(NotImplemented,
                   "parser error: D2CfgMgr parameter not supported : "

+ 7 - 0
src/bin/d2/d2_cfg_mgr.h

@@ -71,6 +71,13 @@ public:
         return (keys_);
     }
 
+    /// @brief Sets the may of TSIG keys
+    ///
+    /// @param new of TSIG keys
+    void setKeys(const TSIGKeyInfoMapPtr& keys) {
+        keys_ = keys;
+    }
+
 protected:
     /// @brief Copy constructor for use by derivations in clone().
     D2CfgContext(const D2CfgContext& rhs);

+ 102 - 171
src/bin/d2/d2_config.cc

@@ -336,121 +336,106 @@ DdnsDomainListMgr::matchDomain(const std::string& fqdn, DdnsDomainPtr& domain) {
 
 // *********************** TSIGKeyInfoParser  *************************
 
-TSIGKeyInfoParser::TSIGKeyInfoParser(const std::string& entry_name,
-                                     TSIGKeyInfoMapPtr keys)
-    : entry_name_(entry_name), keys_(keys), local_scalars_() {
-    if (!keys_) {
-        isc_throw(D2CfgError, "TSIGKeyInfoParser ctor:"
-                  " key storage cannot be null");
-    }
-}
-
-TSIGKeyInfoParser::~TSIGKeyInfoParser() {
-}
-
-void
-TSIGKeyInfoParser::build(isc::data::ConstElementPtr key_config) {
-    isc::dhcp::ConfigPair config_pair;
-    // For each element in the key configuration:
-    // 1. Create a parser for the element.
-    // 2. Invoke the parser's build method passing in the element's
-    // configuration.
-    // 3. Invoke the parser's commit method to store the element's parsed
-    // data to the parser's local storage.
-    BOOST_FOREACH (config_pair, key_config->mapValue()) {
-        isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
-                                                       config_pair.second->
-                                                       getPosition()));
-        parser->build(config_pair.second);
-        parser->commit();
-    }
-
+TSIGKeyInfoPtr
+TSIGKeyInfoParser::parse(isc::data::ConstElementPtr key_config) {
     std::string name;
     std::string algorithm;
     uint32_t digestbits = 0;
     std::string secret;
-    std::map<std::string, isc::data::Element::Position> pos;
 
-    // Fetch the key's parsed scalar values from parser's local storage.
-    // Only digestbits is optional and doesn't throw when missing
-    try {
-        pos["name"] = local_scalars_.getParam("name", name);
-        pos["algorithm"] = local_scalars_.getParam("algorithm", algorithm);
-        pos["digest-bits"] = local_scalars_.getParam("digest-bits", digestbits,
-                                                     DCfgContextBase::OPTIONAL);
-        pos["secret"] = local_scalars_.getParam("secret", secret);
-    } catch (const std::exception& ex) {
-        isc_throw(D2CfgError, "TSIG Key incomplete : " << ex.what()
-                  << " (" << key_config->getPosition() << ")");
+    isc::data::ConstElementPtr name_elem;
+    isc::data::ConstElementPtr algo_elem;
+    isc::data::ConstElementPtr bits_elem;
+    isc::data::ConstElementPtr secret_elem;
+
+    BOOST_FOREACH(isc::dhcp::ConfigPair param, key_config->mapValue()) {
+        std::string entry(param.first);
+        isc::data::ConstElementPtr value(param.second);
+        try {
+            if (entry == "name") {
+                name = value->stringValue();
+                if (name.empty()) {
+                    isc_throw(D2CfgError, "tsig-key: name cannot be blank"
+                              << " (" << value->getPosition() << ")");
+                }
+                name_elem = value;
+            } else if (entry == "algorithm") {
+                algorithm = value->stringValue();
+                // Algorithm must be valid.
+                try {
+                    TSIGKeyInfo::stringToAlgorithmName(algorithm);
+                } catch (const std::exception& ex) {
+                    isc_throw(D2CfgError, "tsig-key : " << ex.what()
+                        << " (" << value->getPosition() << ")");
+                }
+                algo_elem = value;
+            } else if (entry == "digest-bits") {
+                digestbits = value->intValue();
+                bits_elem = value;
+            } else if (entry == "secret") {
+                secret = value->stringValue();
+                // Secret cannot be blank.
+                // Cryptolink lib doesn't offer any way to validate these.
+                // As long as it isn't blank we'll accept it. If the content
+                // is bad, the call to TSIGKeyInfo::remakeKey() made in
+                // the TSIGKeyInfo ctor below will throw.
+                if (secret.empty()) {
+                    isc_throw(D2CfgError, "tsig-key: secret cannot be blank ("
+                              << value->getPosition() << ")");
+                }
+                secret_elem = value;
+            } else {
+                isc_throw(D2CfgError, "tsig-key: unsupported parameter '"
+                          << entry << " (" << value->getPosition() << ")");
+            }
+        } catch (const isc::data::TypeError&) {
+            isc_throw(D2CfgError,
+                      "tsig-key: invalid value type specified for parameter '"
+                      << entry << " (" << value->getPosition() << ")");
+        }
     }
 
-    // Name cannot be blank.
-    if (name.empty()) {
-        isc_throw(D2CfgError, "TSIG key must specify name (" << pos["name"] << ")");
+    if (!name_elem) {
+        isc_throw(D2CfgError, "tsig-key: must specify name"
+                  << " (" << key_config->getPosition() << ")");
     }
 
-    // Currently, the premise is that key storage is always empty prior to
-    // parsing so we are always adding keys never replacing them. Duplicates
-    // are not allowed and should be flagged as a configuration error.
-    if (keys_->find(name) != keys_->end()) {
-        isc_throw(D2CfgError, "Duplicate TSIG key name specified : " << name
-                              << " (" << pos["name"] << ")");
+    if (!algo_elem) {
+        isc_throw(D2CfgError,
+                  "tsig-key: must specify algorithm"
+                  << " (" << key_config->getPosition() << ")");
     }
 
-    // Algorithm must be valid.
-    try {
-        TSIGKeyInfo::stringToAlgorithmName(algorithm);
-    } catch (const std::exception& ex) {
-        isc_throw(D2CfgError, "TSIG key : " << ex.what() << " (" << pos["algorithm"] << ")");
+    if (!secret_elem) {
+        isc_throw(D2CfgError,
+                  "tsig-key: must specify secret"
+                  << " (" << key_config->getPosition() << ")");
     }
 
-    // Not zero Digestbits must be an integral number of octets, greater
-    // than 80 and the half of the full length
+    // Non-zero digest-bits must be an integral number of octets, greater
+    // than 80 and at least half of the algorithm key length.
     if (digestbits > 0) {
-      if ((digestbits % 8) != 0) {
-          isc_throw(D2CfgError, "Invalid TSIG key digest_bits specified : " <<
-                                digestbits << " (" << pos["digest-bits"] << ")");
-      }
-      if (digestbits < 80) {
-          isc_throw(D2CfgError, "TSIG key digest_bits too small : " <<
-                                digestbits << " (" << pos["digest-bits"] << ")");
-      }
-      if (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA224_STR)) {
-          if (digestbits < 112) {
-              isc_throw(D2CfgError, "TSIG key digest_bits too small : " <<
-                                    digestbits << " (" << pos["digest-bits"]
-                                    << ")");
-          }
-      } else if (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA256_STR)) {
-          if (digestbits < 128) {
-              isc_throw(D2CfgError, "TSIG key digest_bits too small : " <<
-                                    digestbits << " (" << pos["digest-bits"]
-                                    << ")");
-          }
-      } else if (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA384_STR)) {
-          if (digestbits < 192) {
-              isc_throw(D2CfgError, "TSIG key digest_bits too small : " <<
-                                    digestbits << " (" << pos["digest-bits"]
-                                    << ")");
-          }
-      } else if (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA512_STR)) {
-          if (digestbits < 256) {
-              isc_throw(D2CfgError, "TSIG key digest_bits too small : " <<
-                                    digestbits << " (" << pos["digest-bits"]
-                                    << ")");
-          }
-      }
-    }
-
-    // Secret cannot be blank.
-    // Cryptolink lib doesn't offer any way to validate these. As long as it
-    // isn't blank we'll accept it.  If the content is bad, the call to in
-    // TSIGKeyInfo::remakeKey() made in the TSIGKeyInfo ctor will throw.
-    // We'll deal with that below.
-    if (secret.empty()) {
-        isc_throw(D2CfgError, "TSIG key must specify secret (" << pos["secret"] << ")");
+        if ((digestbits % 8) != 0) {
+            isc_throw(D2CfgError,
+                      "tsig-key: digest bits must be a multiple of 8"
+                       << " (" << bits_elem->getPosition() << ")");
+        }
+
+        if ((digestbits < 80) ||
+            (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA224_STR)
+             && (digestbits < 112)) ||
+            (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA256_STR)
+             && (digestbits < 128)) ||
+            (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA384_STR)
+             && (digestbits < 192)) ||
+            (boost::iequals(algorithm, TSIGKeyInfo::HMAC_SHA512_STR)
+                   && (digestbits < 256))) {
+                isc_throw(D2CfgError, "tsig-key: digest-bits too small : "
+                          << " (" << bits_elem->getPosition() << ")");
+        }
     }
 
+
     // Everything should be valid, so create the key instance.
     // It is possible for the asiodns::dns::TSIGKey create to fail such as
     // with an invalid secret content.
@@ -458,88 +443,34 @@ TSIGKeyInfoParser::build(isc::data::ConstElementPtr key_config) {
     try {
         key_info.reset(new TSIGKeyInfo(name, algorithm, secret, digestbits));
     } catch (const std::exception& ex) {
-        isc_throw(D2CfgError, ex.what() << " (" << key_config->getPosition() << ")");
-
+        isc_throw(D2CfgError, ex.what() << " ("
+                  << key_config->getPosition() << ")");
     }
 
-    // Add the new TSIGKeyInfo to the key storage.
-    (*keys_)[name]=key_info;
-}
-
-isc::dhcp::ParserPtr
-TSIGKeyInfoParser::createConfigParser(const std::string& config_id,
-                                      const isc::data::Element::Position& pos) {
-    DhcpConfigParser* parser = NULL;
-    // Based on the configuration id of the element, create the appropriate
-    // parser. Scalars are set to use the parser's local scalar storage.
-    if ((config_id == "name")  ||
-        (config_id == "algorithm") ||
-        (config_id == "secret")) {
-        parser = new isc::dhcp::StringParser(config_id,
-                                             local_scalars_.getStringStorage());
-    } else if (config_id == "digest-bits") {
-        parser = new isc::dhcp::Uint32Parser(config_id,
-                                             local_scalars_.getUint32Storage());
-    } else {
-        isc_throw(NotImplemented,
-                  "parser error: TSIGKeyInfo parameter not supported: "
-                  << config_id << " (" << pos << ")");
-    }
-
-    // Return the new parser instance.
-    return (isc::dhcp::ParserPtr(parser));
-}
-
-void
-TSIGKeyInfoParser::commit() {
+    return (key_info);
 }
 
 // *********************** TSIGKeyInfoListParser  *************************
 
-TSIGKeyInfoListParser::TSIGKeyInfoListParser(const std::string& list_name,
-                                       TSIGKeyInfoMapPtr keys)
-    :list_name_(list_name), keys_(keys), local_keys_(new TSIGKeyInfoMap()),
-     parsers_() {
-    if (!keys_) {
-        isc_throw(D2CfgError, "TSIGKeyInfoListParser ctor:"
-                  " key storage cannot be null");
-    }
-}
-
-TSIGKeyInfoListParser::~TSIGKeyInfoListParser() {
-}
-
-void
-TSIGKeyInfoListParser::
-build(isc::data::ConstElementPtr key_list) {
-    int i = 0;
+TSIGKeyInfoMapPtr
+TSIGKeyInfoListParser::parse(isc::data::ConstElementPtr key_list) {
+    TSIGKeyInfoMapPtr keys(new TSIGKeyInfoMap());
     isc::data::ConstElementPtr key_config;
-    // For each key element in the key list:
-    // 1. Create a parser for the key element.
-    // 2. Invoke the parser's build method passing in the key's
-    // configuration.
-    // 3. Add the parser to a local collection of parsers.
     BOOST_FOREACH(key_config, key_list->listValue()) {
-        // Create a name for the parser based on its position in the list.
-        std::string entry_name = boost::lexical_cast<std::string>(i++);
-        isc::dhcp::ParserPtr parser(new TSIGKeyInfoParser(entry_name,
-                                                            local_keys_));
-        parser->build(key_config);
-        parsers_.push_back(parser);
-    }
-
-    // Now that we know we have a valid list, commit that list to the
-    // area given to us during construction (i.e. to the d2 context).
-    *keys_ = *local_keys_;
-}
+        TSIGKeyInfoParser key_parser;
+        TSIGKeyInfoPtr key = key_parser.parse(key_config);
+
+        // Duplicates are not allowed and should be flagged as an error.
+        if (keys->find(key->getName()) != keys->end()) {
+            isc_throw(D2CfgError, "Duplicate TSIG key name specified : "
+                      << key->getName()
+                      << " (" << getPosition("name", key_config) << ")");
+        }
 
-void
-TSIGKeyInfoListParser::commit() {
-    // Invoke commit on each server parser. This will cause each one to
-    // create it's server instance and commit it to storage.
-    BOOST_FOREACH(isc::dhcp::ParserPtr parser, parsers_) {
-        parser->commit();
+        (*keys)[key->getName()] = key;
     }
+
+    return (keys);
 }
 
 // *********************** DnsServerInfoParser  *************************

+ 16 - 85
src/bin/d2/d2_config.h

@@ -9,6 +9,7 @@
 
 #include <asiolink/io_service.h>
 #include <cc/data.h>
+#include <cc/simple_parser.h>
 #include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <dns/tsig.h>
 #include <exceptions/exceptions.h>
@@ -731,69 +732,25 @@ typedef boost::shared_ptr<DScalarContext> DScalarContextPtr;
 ///
 /// This class parses the configuration element "tsig-key" defined in
 /// src/bin/d2/dhcp-ddns.spec and creates an instance of a TSIGKeyInfo.
-class TSIGKeyInfoParser : public  isc::dhcp::DhcpConfigParser {
+class TSIGKeyInfoParser : public  isc::data::SimpleParser { 
 public:
     /// @brief Constructor
-    ///
-    /// @param entry_name is an arbitrary label assigned to this configuration
-    /// definition. Since servers are specified in a list this value is likely
-    /// be something akin to "key:0", set during parsing.
-    /// @param keys is a pointer to the storage area to which the parser
-    /// should commit the newly created TSIGKeyInfo instance.
-    TSIGKeyInfoParser(const std::string& entry_name, TSIGKeyInfoMapPtr keys);
-
+    TSIGKeyInfoParser(){};    
+    
     /// @brief Destructor
-    virtual ~TSIGKeyInfoParser();
+    virtual ~TSIGKeyInfoParser(){};
 
     /// @brief Performs the actual parsing of the given  "tsig-key" element.
     ///
     /// Parses a configuration for the elements needed to instantiate a
     /// TSIGKeyInfo, validates those entries, creates a TSIGKeyInfo instance
-    /// then attempts to add to a list of keys
     ///
     /// @param key_config is the "tsig-key" configuration to parse
-    virtual void build(isc::data::ConstElementPtr key_config);
-
-    /// @brief Creates a parser for the given "tsig-key" member element id.
-    ///
-    /// The key elements currently supported are(see dhcp-ddns.spec):
-    ///   1. name
-    ///   2. algorithm
-    ///   3. digestbits
-    ///   4. secret
-    ///
-    /// @param config_id is the "item_name" for a specific member element of
-    /// the "tsig-key" specification.
-    /// @param pos position within the configuration text (or file) of element
-    /// to be parsed.  This is passed for error messaging.
-    ///
-    /// @return returns a pointer to newly created parser.
     ///
-    /// @throw D2CfgError if configuration contains an unknown parameter
-    virtual isc::dhcp::ParserPtr
-    createConfigParser(const std::string& config_id,
-                       const isc::data::Element::Position& pos =
-                       isc::data::Element::ZERO_POSITION());
-
-    /// @brief Commits the TSIGKeyInfo configuration
-    /// Currently this method is a NOP, as the key instance is created and
-    /// then added to a local list of keys in build().
-    virtual void commit();
+    /// @return pointer to the new TSIGKeyInfo instance
+    TSIGKeyInfoPtr parse(isc::data::ConstElementPtr key_config);
 
 private:
-    /// @brief Arbitrary label assigned to this parser instance.
-    /// Since servers are specified in a list this value is likely be something
-    /// akin to "key:0", set during parsing.  Primarily here for diagnostics.
-    std::string entry_name_;
-
-    /// @brief Pointer to the storage area to which the parser should commit
-    /// the newly created TSIGKeyInfo instance. This is given to us as a
-    /// constructor argument by an upper level.
-    TSIGKeyInfoMapPtr keys_;
-
-    /// @brief Local storage area for scalar parameter values. Use to hold
-    /// data until time to commit.
-    DScalarContext local_scalars_;
 };
 
 /// @brief Parser for a list of TSIGKeyInfos
@@ -801,53 +758,27 @@ private:
 /// This class parses a list of "tsig-key" configuration elements.
 /// (see src/bin/d2/dhcp-ddns.spec). The TSIGKeyInfo instances are added
 /// to the given storage upon commit.
-class TSIGKeyInfoListParser : public isc::dhcp::DhcpConfigParser {
+class TSIGKeyInfoListParser : public isc::data::SimpleParser {
 public:
-
     /// @brief Constructor
-    ///
-    /// @param list_name is an arbitrary label assigned to this parser instance.
-    /// @param keys is a pointer to the storage area to which the parser
-    /// should commit the newly created TSIGKeyInfo instance.
-    TSIGKeyInfoListParser(const std::string& list_name, TSIGKeyInfoMapPtr keys);
+    TSIGKeyInfoListParser(){};
 
     /// @brief Destructor
-    virtual ~TSIGKeyInfoListParser();
+    virtual ~TSIGKeyInfoListParser(){};
 
     /// @brief Performs the parsing of the given list "tsig-key" elements.
     ///
+    /// Creates an emtpy TSIGKeyInfoMap
+    ///
     /// It iterates over each key entry in the list:
     ///   1. Instantiate a TSIGKeyInfoParser for the entry
-    ///   2. Pass the element configuration to the parser's build method
-    ///   3. Add the parser instance to local storage
-    ///
-    /// The net effect is to parse all of the key entries in the list
-    /// prepping them for commit.
+    ///   2. Pass the element configuration to the parser's parse method
+    ///   3. Add the new TSIGKeyInfo instance to the key map
     ///
     /// @param key_list_config is the list of "tsig_key" elements to parse.
-    virtual void build(isc::data::ConstElementPtr key_list_config);
-
-    /// @brief Commits the list of TSIG keys
     ///
-    /// Iterates over the internal list of TSIGKeyInfoParsers, invoking
-    /// commit on each one.  Then commits the local list of keys to
-    /// storage.
-    virtual void commit();
-
-private:
-    /// @brief Arbitrary label assigned to this parser instance.
-    std::string list_name_;
-
-    /// @brief Pointer to the storage area to which the parser should commit
-    /// the list of newly created TSIGKeyInfo instances. This is given to us
-    /// as a constructor argument by an upper level.
-    TSIGKeyInfoMapPtr keys_;
-
-    /// @brief Local storage area to which individual key parsers commit.
-    TSIGKeyInfoMapPtr local_keys_;
-
-    /// @brief Local storage of TSIGKeyInfoParser instances
-    isc::dhcp::ParserCollection parsers_;
+    /// @return a map containing the TSIGKeyInfo instances 
+    TSIGKeyInfoMapPtr parse(isc::data::ConstElementPtr key_list_config);
 };
 
 /// @brief Parser for  DnsServerInfo

File diff suppressed because it is too large
+ 645 - 555
src/bin/d2/d2_lexer.cc


+ 28 - 0
src/bin/d2/d2_lexer.ll

@@ -267,6 +267,33 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
+\"algorithm\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::TSIG_KEYS:
+        return isc::d2::D2Parser::make_ALGORITHM(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("algorithm", driver.loc_);
+    }
+}
+
+\"digest-bits\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::TSIG_KEYS:
+        return isc::d2::D2Parser::make_DIGEST_BITS(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("digest-bits", driver.loc_);
+    }
+}
+
+\"secret\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::TSIG_KEYS:
+        return isc::d2::D2Parser::make_SECRET(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("secret", driver.loc_);
+    }
+}
+
 
 \"Logging\" {
     switch(driver.ctx_) {
@@ -307,6 +334,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 \"name\" {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::LOGGERS:
+    case isc::d2::D2ParserContext::TSIG_KEYS:
         return isc::d2::D2Parser::make_NAME(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("name", driver.loc_);

File diff suppressed because it is too large
+ 390 - 261
src/bin/d2/d2_parser.cc


+ 79 - 45
src/bin/d2/d2_parser.h

@@ -363,20 +363,23 @@ namespace isc { namespace d2 {
         TOKEN_FORWARD_DDNS = 276,
         TOKEN_REVERSE_DDNS = 277,
         TOKEN_TSIG_KEYS = 278,
-        TOKEN_LOGGING = 279,
-        TOKEN_LOGGERS = 280,
-        TOKEN_NAME = 281,
-        TOKEN_OUTPUT_OPTIONS = 282,
-        TOKEN_OUTPUT = 283,
-        TOKEN_DEBUGLEVEL = 284,
-        TOKEN_SEVERITY = 285,
-        TOKEN_TOPLEVEL_JSON = 286,
-        TOKEN_TOPLEVEL_DHCPDDNS = 287,
-        TOKEN_SUB_DHCPDDNS = 288,
-        TOKEN_STRING = 289,
-        TOKEN_INTEGER = 290,
-        TOKEN_FLOAT = 291,
-        TOKEN_BOOLEAN = 292
+        TOKEN_ALGORITHM = 279,
+        TOKEN_DIGEST_BITS = 280,
+        TOKEN_SECRET = 281,
+        TOKEN_LOGGING = 282,
+        TOKEN_LOGGERS = 283,
+        TOKEN_NAME = 284,
+        TOKEN_OUTPUT_OPTIONS = 285,
+        TOKEN_OUTPUT = 286,
+        TOKEN_DEBUGLEVEL = 287,
+        TOKEN_SEVERITY = 288,
+        TOKEN_TOPLEVEL_JSON = 289,
+        TOKEN_TOPLEVEL_DHCPDDNS = 290,
+        TOKEN_SUB_DHCPDDNS = 291,
+        TOKEN_STRING = 292,
+        TOKEN_INTEGER = 293,
+        TOKEN_FLOAT = 294,
+        TOKEN_BOOLEAN = 295
       };
     };
 
@@ -581,6 +584,18 @@ namespace isc { namespace d2 {
 
     static inline
     symbol_type
+    make_ALGORITHM (const location_type& l);
+
+    static inline
+    symbol_type
+    make_DIGEST_BITS (const location_type& l);
+
+    static inline
+    symbol_type
+    make_SECRET (const location_type& l);
+
+    static inline
+    symbol_type
     make_LOGGING (const location_type& l);
 
     static inline
@@ -840,12 +855,12 @@ namespace isc { namespace d2 {
     enum
     {
       yyeof_ = 0,
-      yylast_ = 126,     ///< Last index in yytable_.
-      yynnts_ = 69,  ///< Number of nonterminal symbols.
+      yylast_ = 159,     ///< Last index in yytable_.
+      yynnts_ = 82,  ///< Number of nonterminal symbols.
       yyfinal_ = 8, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 38  ///< Number of tokens.
+      yyntokens_ = 41  ///< Number of tokens.
     };
 
 
@@ -891,9 +906,9 @@ namespace isc { namespace d2 {
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37
+      35,    36,    37,    38,    39,    40
     };
-    const unsigned int user_token_number_max_ = 292;
+    const unsigned int user_token_number_max_ = 295;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -926,24 +941,24 @@ namespace isc { namespace d2 {
   {
       switch (other.type_get ())
     {
-      case 43: // value
-      case 70: // ncr_protocol_value
+      case 46: // value
+      case 73: // ncr_protocol_value
         value.copy< ElementPtr > (other.value);
         break;
 
-      case 37: // "boolean"
+      case 40: // "boolean"
         value.copy< bool > (other.value);
         break;
 
-      case 36: // "floating point"
+      case 39: // "floating point"
         value.copy< double > (other.value);
         break;
 
-      case 35: // "integer"
+      case 38: // "integer"
         value.copy< int64_t > (other.value);
         break;
 
-      case 34: // "constant string"
+      case 37: // "constant string"
         value.copy< std::string > (other.value);
         break;
 
@@ -964,24 +979,24 @@ namespace isc { namespace d2 {
     (void) v;
       switch (this->type_get ())
     {
-      case 43: // value
-      case 70: // ncr_protocol_value
+      case 46: // value
+      case 73: // ncr_protocol_value
         value.copy< ElementPtr > (v);
         break;
 
-      case 37: // "boolean"
+      case 40: // "boolean"
         value.copy< bool > (v);
         break;
 
-      case 36: // "floating point"
+      case 39: // "floating point"
         value.copy< double > (v);
         break;
 
-      case 35: // "integer"
+      case 38: // "integer"
         value.copy< int64_t > (v);
         break;
 
-      case 34: // "constant string"
+      case 37: // "constant string"
         value.copy< std::string > (v);
         break;
 
@@ -1061,24 +1076,24 @@ namespace isc { namespace d2 {
     // Type destructor.
     switch (yytype)
     {
-      case 43: // value
-      case 70: // ncr_protocol_value
+      case 46: // value
+      case 73: // ncr_protocol_value
         value.template destroy< ElementPtr > ();
         break;
 
-      case 37: // "boolean"
+      case 40: // "boolean"
         value.template destroy< bool > ();
         break;
 
-      case 36: // "floating point"
+      case 39: // "floating point"
         value.template destroy< double > ();
         break;
 
-      case 35: // "integer"
+      case 38: // "integer"
         value.template destroy< int64_t > ();
         break;
 
-      case 34: // "constant string"
+      case 37: // "constant string"
         value.template destroy< std::string > ();
         break;
 
@@ -1105,24 +1120,24 @@ namespace isc { namespace d2 {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 43: // value
-      case 70: // ncr_protocol_value
+      case 46: // value
+      case 73: // ncr_protocol_value
         value.move< ElementPtr > (s.value);
         break;
 
-      case 37: // "boolean"
+      case 40: // "boolean"
         value.move< bool > (s.value);
         break;
 
-      case 36: // "floating point"
+      case 39: // "floating point"
         value.move< double > (s.value);
         break;
 
-      case 35: // "integer"
+      case 38: // "integer"
         value.move< int64_t > (s.value);
         break;
 
-      case 34: // "constant string"
+      case 37: // "constant string"
         value.move< std::string > (s.value);
         break;
 
@@ -1184,7 +1199,8 @@ namespace isc { namespace d2 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -1322,6 +1338,24 @@ namespace isc { namespace d2 {
   }
 
   D2Parser::symbol_type
+  D2Parser::make_ALGORITHM (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_ALGORITHM, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_DIGEST_BITS (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_DIGEST_BITS, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_SECRET (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_SECRET, l);
+  }
+
+  D2Parser::symbol_type
   D2Parser::make_LOGGING (const location_type& l)
   {
     return symbol_type (token::TOKEN_LOGGING, l);
@@ -1408,7 +1442,7 @@ namespace isc { namespace d2 {
 
 #line 14 "d2_parser.yy" // lalr1.cc:392
 } } // isc::d2
-#line 1412 "d2_parser.h" // lalr1.cc:392
+#line 1446 "d2_parser.h" // lalr1.cc:392
 
 
 

+ 84 - 3
src/bin/d2/d2_parser.yy

@@ -64,6 +64,9 @@ using namespace std;
   FORWARD_DDNS "forward-ddns"
   REVERSE_DDNS "reverse-ddns"
   TSIG_KEYS "tsig-keys"
+  ALGORITHM "algorithm"
+  DIGEST_BITS "digest-bits"
+  SECRET "secret"
 
   LOGGING "Logging"
   LOGGERS "loggers"
@@ -310,13 +313,91 @@ reverse_ddns : REVERSE_DDNS {
     ctx.leave();
 };
 
-tsig_keys : TSIG_KEYS {
+// --- tsig-keys ----------------------------------------
+// "tsig-keys" : [ ... ]
+tsig_keys: TSIG_KEYS {
+    ElementPtr l(new ListElement(ctx.loc2pos(@1)));
+    ctx.stack_.back()->set("tsig-keys", l);
+    ctx.stack_.push_back(l);
+    ctx.enter(ctx.TSIG_KEYS);
+} COLON LSQUARE_BRACKET tsig_keys_list RSQUARE_BRACKET {
+    ctx.stack_.pop_back();
+    ctx.leave();
+};
+
+tsig_keys_list: %empty
+              | not_empty_tsig_keys_list
+              ;
+
+not_empty_tsig_keys_list: tsig_key
+                        | not_empty_tsig_keys_list COMMA tsig_key
+                        ;
+
+tsig_key: LCURLY_BRACKET {
+    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+    ctx.stack_.back()->add(m);
+    ctx.stack_.push_back(m);
+} tsig_key_params RCURLY_BRACKET {
+    ctx.stack_.pop_back();
+};
+
+tsig_key_params: tsig_key_param 
+               | tsig_key_params COMMA tsig_key_param
+               ;
+
+tsig_key_param: tsig_key_name
+              | tsig_key_algorithm
+              | tsig_key_digest_bits
+              | tsig_key_secret
+              | unknown_map_entry
+              ;
+
+tsig_key_name: NAME {
     ctx.enter(ctx.NO_KEYWORD);
-} COLON value {
-    ctx.stack_.back()->set("tsig-keys", $4);
+} COLON STRING {
+    if ($4 == "") {
+        error(@3, "name cannot be blank");
+    } 
+    ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
+    ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
+    ctx.stack_.back()->set("name", name);
     ctx.leave();
 };
 
+tsig_key_algorithm: ALGORITHM {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    if ($4 == "") {
+        error(@3, "algorithm cannot be blank");
+    } 
+    ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
+    ctx.stack_.back()->set("algorithm", elem);
+    ctx.leave();
+};
+
+tsig_key_digest_bits: DIGEST_BITS COLON INTEGER {
+    if ($3 < 0 || ($3 > 0  && ($3 % 8 != 0))) {
+        error(@3, "digest-bits must either be zero or a positive, multiple of eight");
+    } 
+    ElementPtr elem(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("digest-bits", elem);
+};
+
+tsig_key_secret: SECRET {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    if ($4 == "") {
+        error(@3, "secret cannot be blank");
+    } 
+    ElementPtr elem(new StringElement($4, ctx.loc2pos(@4)));
+    ctx.stack_.back()->set("secret", elem);
+    ctx.leave();
+};
+
+
+// --- end of tsig-keys ---------------------------------
+
+
 dhcp6_json_object: DHCP6 {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON value {

+ 2 - 0
src/bin/d2/parser_context.cc

@@ -123,6 +123,8 @@ D2ParserContext::contextName()
         return ("toplevel");
     case DHCPDDNS:
         return ("DhcpDdns");
+    case TSIG_KEYS:
+        return ("tsig-keys");
     case LOGGING:
         return ("Logging");
     case LOGGERS:

+ 14 - 2
src/bin/d2/parser_context.h

@@ -156,6 +156,18 @@ public:
         ///< Used while parsing content of DhcpDdns.
         DHCPDDNS,
 
+        ///< Used while parsing content of tsig-keys
+        TSIG_KEYS,
+
+        ///< Used while parsing content of DhcpDdns/tsig-keys/algorithm
+        ALGORITHM,
+
+        ///< Used while parsing content of DhcpDdns/tsig-keys/digest-bits
+        DIGEST_BITS,
+
+        ///< Used while parsing content of DhcpDdns/tsig-keys/secret
+        SECRET,
+
         ///< Used while parsing content of Logging
         LOGGING,
 
@@ -165,10 +177,10 @@ public:
         /// Used while parsing Logging/loggers/output_options structures.
         OUTPUT_OPTIONS,
 
-        /// Used while parsing Dhcp6/dhcp-ddns/ncr-protocol
+        /// Used while parsing DhcpDdns/ncr-protocol
         NCR_PROTOCOL,
 
-        /// Used while parsing Dhcp6/dhcp-ddns/ncr-format
+        /// Used while parsing DhcpDdns/ncr-format
         NCR_FORMAT
 
     } ParserContext;

+ 44 - 60
src/bin/d2/tests/d2_cfg_mgr_unittests.cc

@@ -266,27 +266,33 @@ public:
 
     /// @brief Constructor
     TSIGKeyInfoTest() {
-        reset();
     }
 
     /// @brief Destructor
     ~TSIGKeyInfoTest() {
     }
 
-    /// @brief Wipe out the current storage and parser and replace
-    /// them with new ones.
-    void reset() {
-        keys_.reset(new TSIGKeyInfoMap());
-        parser_.reset(new TSIGKeyInfoParser("test", keys_));
+    /// @brief Pointer to the current parser instance.
+    TSIGKeyInfoParser parser_;
+};
+
+/// @brief Test fixture class for testing DnsServerInfo parsing.
+class TSIGKeyInfoListTest : public ConfigParseTest {
+public:
+
+    /// @brief Constructor
+    TSIGKeyInfoListTest() {
     }
 
-    /// @brief Storage for "committing" keys.
-    TSIGKeyInfoMapPtr keys_;
+    /// @brief Destructor
+    ~TSIGKeyInfoListTest() {
+    }
 
     /// @brief Pointer to the current parser instance.
-    isc::dhcp::ParserPtr parser_;
+    TSIGKeyInfoListParser parser_;
 };
 
+
 /// @brief Test fixture class for testing DnsServerInfo parsing.
 class DnsServerInfoTest : public ConfigParseTest {
 public:
@@ -574,7 +580,7 @@ TEST_F(TSIGKeyInfoTest, invalidEntry) {
     ASSERT_TRUE(fromJSON(config));
 
     // Verify that build fails on blank name.
-    EXPECT_THROW(parser_->build(config_set_), D2CfgError);
+    EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
 
     // Config with a blank algorithm entry.
     config = "{"
@@ -586,7 +592,7 @@ TEST_F(TSIGKeyInfoTest, invalidEntry) {
     ASSERT_TRUE(fromJSON(config));
 
     // Verify that build fails on blank algorithm.
-    EXPECT_THROW(parser_->build(config_set_), D2CfgError);
+    EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
 
     // Config with an invalid algorithm entry.
     config = "{"
@@ -598,7 +604,7 @@ TEST_F(TSIGKeyInfoTest, invalidEntry) {
     ASSERT_TRUE(fromJSON(config));
 
     // Verify that build fails on blank algorithm.
-    EXPECT_THROW(parser_->build(config_set_), D2CfgError);
+    EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
 
     // Config with a blank secret entry.
     config = "{"
@@ -610,7 +616,7 @@ TEST_F(TSIGKeyInfoTest, invalidEntry) {
     ASSERT_TRUE(fromJSON(config));
 
     // Verify that build fails blank secret
-    EXPECT_THROW(parser_->build(config_set_), D2CfgError);
+    EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
 
     // Config with an invalid secret entry.
     config = "{"
@@ -622,7 +628,7 @@ TEST_F(TSIGKeyInfoTest, invalidEntry) {
     ASSERT_TRUE(fromJSON(config));
 
     // Verify that build fails an invalid secret
-    EXPECT_THROW(parser_->build(config_set_), D2CfgError);
+    EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
 }
 
 /// @brief Verifies that TSIGKeyInfo parsing creates a proper TSIGKeyInfo
@@ -639,17 +645,9 @@ TEST_F(TSIGKeyInfoTest, validEntry) {
 
     // Verify that it builds and commits without throwing.
     //ASSERT_NO_THROW(parser_->build(config_set_));
-    (parser_->build(config_set_));
-    ASSERT_NO_THROW(parser_->commit());
-
-    // Verify the correct number of keys are present
-    int count =  keys_->size();
-    EXPECT_EQ(1, count);
-
-    // Find the key and retrieve it.
-    TSIGKeyInfoMap::iterator gotit = keys_->find("d2_key_one");
-    ASSERT_TRUE(gotit != keys_->end());
-    TSIGKeyInfoPtr& key = gotit->second;
+    TSIGKeyInfoPtr key;
+    ASSERT_NO_THROW(key = parser_.parse(config_set_));
+    ASSERT_TRUE(key);
 
     // Verify the key contents.
     EXPECT_TRUE(checkKey(key, "d2_key_one", "HMAC-MD5",
@@ -658,7 +656,7 @@ TEST_F(TSIGKeyInfoTest, validEntry) {
 
 /// @brief Verifies that attempting to parse an invalid list of TSIGKeyInfo
 /// entries is detected.
-TEST_F(TSIGKeyInfoTest, invalidTSIGKeyList) {
+TEST_F(TSIGKeyInfoListTest, invalidTSIGKeyList) {
     // Construct a list of keys with an invalid key entry.
     std::string config = "["
 
@@ -681,20 +679,15 @@ TEST_F(TSIGKeyInfoTest, invalidTSIGKeyList) {
 
     ASSERT_TRUE(fromJSON(config));
 
-    // Create the list parser.
-    isc::dhcp::ParserPtr parser;
-    ASSERT_NO_THROW(parser.reset(new TSIGKeyInfoListParser("test", keys_)));
-
-    // Verify that the list builds without errors.
-    EXPECT_THROW(parser->build(config_set_), D2CfgError);
+    // Verify that the list builds with errors.
+    EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
 }
 
 /// @brief Verifies that attempting to parse an invalid list of TSIGKeyInfo
 /// entries is detected.
-TEST_F(TSIGKeyInfoTest, duplicateTSIGKey) {
+TEST_F(TSIGKeyInfoListTest, duplicateTSIGKey) {
     // Construct a list of keys with an invalid key entry.
     std::string config = "["
-
                          " { \"name\": \"key1\" , "
                          "   \"algorithm\": \"HMAC-MD5\" ,"
                          " \"digest-bits\": 120 , "
@@ -713,17 +706,13 @@ TEST_F(TSIGKeyInfoTest, duplicateTSIGKey) {
 
     ASSERT_TRUE(fromJSON(config));
 
-    // Create the list parser.
-    isc::dhcp::ParserPtr parser;
-    ASSERT_NO_THROW(parser.reset(new TSIGKeyInfoListParser("test", keys_)));
-
     // Verify that the list builds without errors.
-    EXPECT_THROW(parser->build(config_set_), D2CfgError);
+    EXPECT_THROW(parser_.parse(config_set_), D2CfgError);
 }
 
 /// @brief Verifies a valid list of TSIG Keys parses correctly.
 /// Also verifies that all of the supported algorithm names work.
-TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
+TEST_F(TSIGKeyInfoListTest, validTSIGKeyList) {
     // Construct a valid list of keys.
     std::string config = "["
 
@@ -760,22 +749,17 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
                          " ]";
 
     ASSERT_TRUE(fromJSON(config));
-
-    // Verify that the list builds and commits without errors.
-    // Create the list parser.
-    isc::dhcp::ParserPtr parser;
-    ASSERT_NO_THROW(parser.reset(new TSIGKeyInfoListParser("test", keys_)));
-    ASSERT_NO_THROW(parser->build(config_set_));
-    ASSERT_NO_THROW(parser->commit());
+    TSIGKeyInfoMapPtr keys;
+    ASSERT_NO_THROW(keys = parser_.parse(config_set_));
 
     std::string ref_secret = "dGhpcyBrZXkgd2lsbCBtYXRjaA==";
     // Verify the correct number of keys are present
-    int count =  keys_->size();
+    int count =  keys->size();
     ASSERT_EQ(6, count);
 
     // Find the 1st key and retrieve it.
-    TSIGKeyInfoMap::iterator gotit = keys_->find("key1");
-    ASSERT_TRUE(gotit != keys_->end());
+    TSIGKeyInfoMap::iterator gotit = keys->find("key1");
+    ASSERT_TRUE(gotit != keys->end());
     TSIGKeyInfoPtr& key = gotit->second;
 
     // Verify the key contents.
@@ -783,8 +767,8 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
                          ref_secret, 80));
 
     // Find the 2nd key and retrieve it.
-    gotit = keys_->find("key2");
-    ASSERT_TRUE(gotit != keys_->end());
+    gotit = keys->find("key2");
+    ASSERT_TRUE(gotit != keys->end());
     key = gotit->second;
 
     // Verify the key contents.
@@ -792,8 +776,8 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
                          ref_secret, 80));
 
     // Find the 3rd key and retrieve it.
-    gotit = keys_->find("key3");
-    ASSERT_TRUE(gotit != keys_->end());
+    gotit = keys->find("key3");
+    ASSERT_TRUE(gotit != keys->end());
     key = gotit->second;
 
     // Verify the key contents.
@@ -801,8 +785,8 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
                          ref_secret, 128));
 
     // Find the 4th key and retrieve it.
-    gotit = keys_->find("key4");
-    ASSERT_TRUE(gotit != keys_->end());
+    gotit = keys->find("key4");
+    ASSERT_TRUE(gotit != keys->end());
     key = gotit->second;
 
     // Verify the key contents.
@@ -810,8 +794,8 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
                          ref_secret, 112));
 
     // Find the 5th key and retrieve it.
-    gotit = keys_->find("key5");
-    ASSERT_TRUE(gotit != keys_->end());
+    gotit = keys->find("key5");
+    ASSERT_TRUE(gotit != keys->end());
     key = gotit->second;
 
     // Verify the key contents.
@@ -819,8 +803,8 @@ TEST_F(TSIGKeyInfoTest, validTSIGKeyList) {
                          ref_secret, 192));
 
     // Find the 6th key and retrieve it.
-    gotit = keys_->find("key6");
-    ASSERT_TRUE(gotit != keys_->end());
+    gotit = keys->find("key6");
+    ASSERT_TRUE(gotit != keys->end());
     key = gotit->second;
 
     // Verify the key contents.

+ 7 - 7
src/bin/d2/tests/testdata/d2_cfg_tests.json

@@ -334,7 +334,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, blank key name",
-"logic-error" : true,
+"syntax-error" : "<string>:1.95: name cannot be blank",
 "data" :
     {
     "forward-ddns" : {},
@@ -377,7 +377,7 @@
 #----- D2.tsig-keys, algorithm tests
 
 ,{
-"description" : "D2.tsig-keys, all valid algorthms",
+"description" : "D2.tsig-keys, all valid algorithms",
 "data" :
     {
     "forward-ddns" : {},
@@ -439,7 +439,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, blank algorithm",
-"logic-error" : true,
+"syntax-error" : "<string>:1.75: algorithm cannot be blank",
 "data" :
     {
     "forward-ddns" : {},
@@ -476,7 +476,7 @@
 
 #----- D2.tsig-keys, digest-bits tests
 ,{
-"description" : "D2.tsig-keys, all valid algorthms",
+"description" : "D2.tsig-keys, all valid algorthims",
 "data" :
     {
     "forward-ddns" : {},
@@ -526,7 +526,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, invalid digest-bits",
-"logic-error" : true,
+"syntax-error" : "<string>:1.104-105: digest-bits must either be zero or a positive, multiple of eight",
 "data" :
     {
     "forward-ddns" : {},
@@ -538,7 +538,7 @@
             "algorithm" : "HMAC-MD5",
             "digest-bits" : 84,
             "secret" : "LSWXnfkKZjdPJI5QxlpnfQ=="
-            },
+            }
         ]
     }
 }
@@ -684,7 +684,7 @@
 #-----
 ,{
 "description" : "D2.tsig-keys, blank secret",
-"logic-error" : true,
+"syntax-error" : "<string>:1.118: secret cannot be blank",
 "data" :
     {
     "forward-ddns" : {},