</para>
</section>
+ <section id="reservation6-secure">
+ <title>Secure DHCPv6 Authorization in Host Reservation</title>
+
+ <note>Secure DHCPv6 is experimental</note>
+
+ <para>Host reservations are used too in secure DHCPv6 to provide
+ the authorization, i.e., a way the check the association between
+ the public key or the certificate presented in a packet protected
+ by secure DHCPv6 and a particular client.
+ </para>
+
+ <para>A client is configured in a host reservation with the
+ filename of its public key or certificate (the two keywords can
+ be used indifferently: the key type always follows the secure DHCPv6
+ option type). The two
+ <itemizedlist>
+ <listitem><simpara> <command>public-key</command> specifies
+ the name of a file containing the public key.
+ </simpara></listitem>
+ <listitem><simpara> <command>certificate</command> specifies
+ the name of a file containing the certificate.
+ </simpara></listitem>
+ </itemizedlist>
+ The format of the file content must follow the checking operation,
+ e.g., when it is a bit-to-bit compare it must be encoded in DER.
+ </para>
+ </section>
+
<!-- @todo: add support for per IA reservation (that specifies IAID in
the ip-addresses and prefixes) -->
</section>
]
},
+ { "item_name": "secure-Dhcp6",
+ "item_type": "map",
+ "item_optional": true,
+ "item_default": {},
+ "map_item_spec": [
+ {
+ "item_name": "sign-answers",
+ "item_type": "boolean",
+ "item_optional": true;
+ "item_default": false
+ },
+ {
+ "item_name": "signature-algorithm"
+ "item_type": "string",
+ "item_optional": true,
+ "item_default": "RSA"
+ },
+ {
+ "item_name": "hash-algorithm"
+ "item_type": "string",
+ "item_optional": true,
+ "item_default": "SHA-256"
+ },
+ {
+ "item_name": "public-key"
+ "item_type": "string",
+ "item_optional": true,
+ "item_default": ""
+ },
+ {
+ "item_name": "certificate"
+ "item_type": "string",
+ "item_optional": true,
+ "item_default": ""
+ },
+ {
+ "item_name": "timestamp-answers",
+ "item_type": "boolean",
+ "item_optional": true,
+ "item_default": false
+ },
+ {
+ "item_name": "check-signatures",
+ "item_type": "boolean",
+ "item_optional": true,
+ "item_default": false
+ },
+ {
+ "item_name": "check-timestamps",
+ "item_type": "boolean",
+ "item_optional": true,
+ "item_default": false
+ },
+ {
+ "item_name": "check-authorizations",
+ "item_type": "boolean",
+ "item_optional": true,
+ "item_default": false
+ },
+ {
+ "item_name": "validation-policy"
+ "item_type": "string",
+ "item_optional": true,
+ "item_default": "offline"
+ }
+ },
{ "item_name": "renew-timer",
"item_type": "integer",
"item_optional": false,
"item_optional": false,
"item_default": ""
}
+ },
+ {
+ "item_name": "public-key",
+ "item_type": "string",
+ "item_optional": true,
+ "item_default": ""
+ },
+ {
+ "item_name": "certificate",
+ "item_type": "string",
+ "item_optional": true,
+ "item_default": ""
} ]
}
},
/// \exception UnsupportedAlgorithm if the given algorithm
/// is unknown or not supported by the underlying library
/// \exception Badkey if the given key length is bad
- /// \exception InvalidCert if the certification fails to validate
/// \exception LibraryError if there was any unexpected exception
/// in the underlying library
///
CryptoLinkError(file, line, what) {}
};
-/// This exception is thrown when a certification is invalid
-class InvalidCert : public CryptoLinkError {
-public:
- InvalidCert(const char* file, size_t line, const char* what) :
- CryptoLinkError(file, line, what) {}
-};
-
/// This exception is raised when a general error that was not
/// specifically caught is thrown by the underlying library. It
/// is replaced by this one so as not have 'external' exceptions
/// \exception UnsupportedAlgorithm if the given algorithm
/// is unknown or not supported by the underlying library
/// \exception BadKey if the given key length is bad
- /// \exception InvalidCert if the certification fails to validate
/// \exception LibraryError if there was any unexpected exception
/// in the underlying library
/// \param key The key to sign or verify with
EXTRA_DIST += parsers/host_reservation_parser.cc
EXTRA_DIST += parsers/host_reservation_parser.h
EXTRA_DIST += parsers/host_reservations_list_parser.h
+EXTRA_DIST += parsers/sedhcp6_parser.cc
+EXTRA_DIST += parsers/sedhcp6_parser.h
# Define rule to build logging source files from message file
dhcpsrv_messages.h dhcpsrv_messages.cc hosts_messages.h hosts_messages.cc: s-messages
libkea_dhcpsrv_la_SOURCES += parsers/host_reservations_list_parser.h
libkea_dhcpsrv_la_SOURCES += parsers/ifaces_config_parser.cc
libkea_dhcpsrv_la_SOURCES += parsers/ifaces_config_parser.h
-
+libkea_dhcpsrv_la_SOURCES += parsers/sedhcp6_parser.cc
+libkea_dhcpsrv_la_SOURCES += parsers/sedhcp6_parser.h
nodist_libkea_dhcpsrv_la_SOURCES = dhcpsrv_messages.h dhcpsrv_messages.cc
nodist_libkea_dhcpsrv_la_SOURCES += hosts_messages.h hosts_messages.cc
/// Creates an instance of this parser.
///
/// @param param_name Name of the parameter used to access the
- /// configuration.
+ /// configuration.
/// @param ctx Parser context.
///
/// @return Pointer to a DbAccessParser. The caller is responsible for
--- /dev/null
+// Copyright (C) 2015 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 <dhcp/option.h>
+#include <dhcpsrv/dhcpsrv_log.h>
+#include <dhcpsrv/parsers/sedhcp6_parser.h>
+
+#include <boost/foreach.hpp>
+
+#include <map>
+#include <string>
+#include <utility>
+
+using namespace std;
+using namespace isc::data;
+
+namespace isc {
+namespace dhcp {
+
+// Factory function to build the parser
+SeDhcp6Parser::SeDhcp6Parser(const std::string&, const ParserContext& ctx)
+ : values_(), ctx_(ctx)
+{
+}
+
+// Parse the configuration and check that the various keywords are consistent.
+void
+SeDhcp6Parser::build(isc::data::ConstElementPtr config_value) {
+
+ // DHCPv6 only
+ if (ctx_.universe_ != Option::V6) {
+ isc_throw(DhcpConfigError,
+ "secure-Dhcp6 makes sense only for DHCPv6");
+ }
+
+ // To cope with incremental updates, the strategy is:
+ // 1. Take a copy of the stored keyword/value pairs.
+ // 2. Update the copy with the passed keywords.
+ // 3. Perform validation checks on the updated keyword/value pairs.
+ // 4. If all is OK, update the stored keyword/value pairs.
+
+ // 1. Take a copy of the stored keyword/value pairs.
+ std::map<string, string> values_copy = values_;
+
+ // 2. Update the copy with the passed keywords.
+ BOOST_FOREACH(ConfigPair param, config_value->mapValue()) {
+ bool found = false;
+ try {
+ // Booleans
+ if ((param.first == "sign-answers") ||
+ (param.first == "timestamp-answers") ||
+ (param.first == "check-authorizations") ||
+ (param.first == "check-signatures") ||
+ (param.first == "check-timestamps")) {
+ found = true;
+ values_copy[param.first] = (param.second->boolValue() ?
+ "true" : "false");
+ } else if ((param.first == "signature-algorithm") ||
+ (param.first == "hash-algorithm") ||
+ (param.first == "public-key") ||
+ (param.first == "certificate") ||
+ (param.first == "validation-policy")) {
+ found = true;
+ values_copy[param.first] = param.second->stringValue();
+ }
+ } catch (const isc::data::TypeError& ex) {
+ // Append position of the element.
+ isc_throw(isc::data::TypeError, ex.what() << " ("
+ << param.second->getPosition() << ")");
+ }
+ if (!found) {
+ isc_throw(DhcpConfigError,
+ "secure-Dhcp6 parameter not supported: "
+ << param.first << " ("
+ << param.second->getPosition() << ")");
+ }
+ }
+
+ // 3. Perform validation checks on the updated set of keyword/values.
+ //
+ // a. Check if we sign
+ bool sign_answers = false;
+ StringPairMap::const_iterator sign_answers_ptr =
+ values_copy.find("sign-answers");
+ if ((sign_answers_ptr != values_copy.end()) &&
+ (sign_answers_ptr->second == "true")) {
+ sign_answers = true;
+ }
+
+ // b. Check if we can sign
+ string public_key = "";
+ StringPairMap::const_iterator public_key_ptr =
+ values_copy.find("public-key");
+ if (public_key_ptr != values_copy.end()) {
+ public_key = public_key_ptr->second;
+ }
+ string certificate = "";
+ StringPairMap::const_iterator certificate_ptr =
+ values_copy.find("certificate");
+ if (certificate_ptr != values_copy.end()) {
+ certificate = certificate_ptr->second;
+ }
+ if (sign_answers && public_key.empty() && certificate.empty()) {
+ isc_throw(DhcpConfigError,
+ "secure-Dhcp6 requires a public-key or a certificate "
+ "when sign-answers is enabled");
+ }
+ if (!public_key.empty() && !certificate.empty()) {
+ isc_throw(DhcpConfigError,
+ "public-key and certificate cannot be both defined");
+ }
+
+ // c. Check if the signature algorithm is known
+ StringPairMap::const_iterator signature_algorithm_ptr =
+ values_copy.find("signature-algorithm");
+ if ((signature_algorithm_ptr != values_copy.end()) &&
+ (signature_algorithm_ptr->second != "RSA")) {
+ isc_throw(DhcpConfigError, "unknown signature-algorithm: "
+ << signature_algorithm_ptr->second);
+ }
+
+ // d. Check if the hash algorithm is known
+ StringPairMap::const_iterator hash_algorithm_ptr =
+ values_copy.find("hash-algorithm");
+ if ((hash_algorithm_ptr != values_copy.end()) &&
+ (hash_algorithm_ptr->second != "SHA-256") &&
+ (hash_algorithm_ptr->second != "SHA-512")) {
+ isc_throw(DhcpConfigError, "unknown hash-algorithm: "
+ << hash_algorithm_ptr->second);
+ }
+
+ // e. Check if the validation policy is known
+ StringPairMap::const_iterator validation_policy_ptr =
+ values_copy.find("validation-policy");
+ if ((validation_policy_ptr != values_copy.end()) &&
+ (validation_policy_ptr->second != "offline") &&
+ (validation_policy_ptr->second != "online")) {
+ isc_throw(DhcpConfigError, "unknown validation-policy: "
+ << validation_policy_ptr->second);
+ }
+
+ // 4. If all is OK, update the stored keyword/value pairs. We do this by
+ // swapping contents - values_copy is destroyed immediately after the
+ // operation (when the method exits), so we are not interested in its new
+ // value.
+ values_.swap(values_copy);
+}
+
+// Create TODO
+
+// Commit the changes - create a new secure DHCPv6 state with new parameters
+void
+SeDhcp6Parser::commit() {
+ // TODO
+}
+
+}; // namespace dhcp
+}; // namespace isc
--- /dev/null
+// Copyright (C) 2015 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 SEDHCP6_PARSER_H
+#define SEDHCP6_PARSER_H
+
+#include <cc/data.h>
+#include <dhcpsrv/parsers/dhcp_config_parser.h>
+#include <dhcpsrv/parsers/dhcp_parsers.h>
+#include <exceptions/exceptions.h>
+
+#include <string>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Secure DHCPv6 Parameters
+///
+/// This class is the parser for the secure DHCPv6 configuration. This is a
+/// map under the top-level "secure" element, and comprises a map of
+/// strings.
+class SeDhcp6Parser: public DhcpConfigParser {
+public:
+ /// @brief Keyword and associated value
+ typedef std::pair<std::string, std::string> StringPair;
+
+ /// @brief Keyword/value collection of secure DHCPv6 parameters
+ typedef std::map<std::string, std::string> StringPairMap;
+
+ /// @brief Constructor
+ ///
+ /// @param param_name Name of the parameter under which the secure
+ /// DHCPv6 details are held.
+ /// @param ctx Parser context.
+ SeDhcp6Parser(const std::string& param_name, const ParserContext& ctx);
+
+ /// The destructor.
+ virtual ~SeDhcp6Parser()
+ {}
+
+ /// @brief Prepare configuration value.
+ ///
+ /// Parses the set of strings forming the secure DHCPv6 specification and
+ /// checks that all are OK. In particular it checks:
+ ///
+ /// TODO
+ ///
+ /// Once all has been validated, TODO
+ ///
+ /// @param config_value The configuration value for the "secure""
+ /// identifier.
+ ///
+ /// @throw TODO
+ virtual void build(isc::data::ConstElementPtr config_value);
+
+ /// @brief Apply the prepared configuration value to the server.
+ ///
+ /// With the string validated, TODO
+ ///
+ /// This method is expected to be called after \c build(), and only once.
+ /// The result is undefined otherwise.
+ virtual void commit();
+
+ /// @brief Factory method to create parser
+ ///
+ /// Creates an instance of this parser.
+ ///
+ /// @param param_name Name of the parameter used to access the
+ /// configuration.
+ /// @param ctx Parser context.
+ ///
+ /// @return Pointer to a SeDhcp6Parser. The caller is responsible for
+ /// destroying the parser after use.
+ static DhcpConfigParser* factory(const std::string& param_name,
+ const ParserContext& ctx) {
+ return (new SeDhcp6Parser(param_name, ctx));
+ }
+
+protected:
+ /// @brief Get secure DHCPv6 parameters
+ ///
+ /// Used in testing to check that the configuration information has been
+ /// parsed correctly.
+ ///
+ /// @return Reference to the internal map of keyword/value pairs
+ /// representing secure DHCPv6 information. This is valid only
+ /// for so long as the the parser remains in existence.
+ const StringPairMap& getSeDhcp6Parameters() const {
+ return (values_);
+ }
+
+ /// TODO
+
+private:
+
+ std::map<std::string, std::string> values_; ///< Stored parameter values
+
+ ParserContext ctx_; ///< Parser context
+};
+
+}; // namespace dhcp
+}; // namespace isc
+
+
+#endif // SEDHCP6_PARSER_H
libdhcpsrv_unittests_SOURCES += pool_unittest.cc
libdhcpsrv_unittests_SOURCES += schema_mysql_copy.h
libdhcpsrv_unittests_SOURCES += schema_pgsql_copy.h
+libdhcpsrv_unittests_SOURCES += sedhcp6_parser_unittest.cc
libdhcpsrv_unittests_SOURCES += srv_config_unittest.cc
libdhcpsrv_unittests_SOURCES += subnet_unittest.cc
libdhcpsrv_unittests_SOURCES += test_get_callout_handle.cc test_get_callout_handle.h
EXPECT_EQ("somehost.suffix.com.", qualified_name);
- //append suffix but dot
+ //append suffix but dot
ASSERT_NO_THROW(cfg.reset(new D2ClientConfig(true,
isc::asiolink::IOAddress("127.0.0.1"), 477,
isc::asiolink::IOAddress("127.0.0.1"), 478,
EXPECT_EQ("somehost.suffix.com", qualified_name);
- //append no suffix and not dot
+ //append no suffix and not dot
ASSERT_NO_THROW(cfg.reset(new D2ClientConfig(true,
isc::asiolink::IOAddress("127.0.0.1"), 477,
isc::asiolink::IOAddress("127.0.0.1"), 478,
--- /dev/null
+// Copyright (C) 2015 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 <cc/data.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/parsers/sedhcp6_parser.h>
+#include <gtest/gtest.h>
+
+using namespace isc::data;
+using namespace isc::dhcp;
+
+namespace {
+
+/// @brief Test fixture class for @c SeDhcp6Parser
+class SeDhcp6ParserTest : public ::testing::Test {
+protected:
+
+ /// @brief Setup for each test.
+ ///
+ /// Clears the configuration in the @c CfgMgr.
+ virtual void SetUp();
+
+ /// @brief Cleans up after each test.
+ ///
+ /// Clears the configuration in the @c CfgMgr.
+ virtual void TearDown();
+
+};
+
+void
+SeDhcp6ParserTest::SetUp() {
+ CfgMgr::instance().clear();
+}
+
+void
+SeDhcp6ParserTest::TearDown() {
+ CfgMgr::instance().clear();
+}
+
+// This test checks the parser on a basic input
+TEST_F(SeDhcp6ParserTest, dhcpv6Universe) {
+ std::string config = "{ \"sign-answers\": false }";
+
+ ElementPtr config_element = Element::fromJSON(config);
+
+ ParserContextPtr parser_context(new ParserContext(Option::V6));
+
+ SeDhcp6Parser parser("secure-Dhcp6", *parser_context);
+ ASSERT_NO_THROW(parser.build(config_element));
+}
+
+// This test checks the parser requires DHCPv6 context
+TEST_F(SeDhcp6ParserTest, dhcpv4Universe) {
+ std::string config = "{ \"sign-answers\": false }";
+
+ ElementPtr config_element = Element::fromJSON(config);
+
+ ParserContextPtr parser_context(new ParserContext(Option::V4));
+
+ SeDhcp6Parser parser("secure-Dhcp6", *parser_context);
+ ASSERT_THROW(parser.build(config_element), DhcpConfigError);
+}
+
+// This test checks unknown parameters
+TEST_F(SeDhcp6ParserTest, unknownParameters) {
+ std::string config = "{ \"unknown-boolean\": true }";
+
+ ElementPtr config_element = Element::fromJSON(config);
+
+ ParserContextPtr parser_context(new ParserContext(Option::V6));
+
+ SeDhcp6Parser parser("secure-Dhcp6", *parser_context);
+ ASSERT_THROW(parser.build(config_element), DhcpConfigError);
+
+ config = "{ \"unknown-string\": \"foobar\" }";
+ ASSERT_THROW(parser.build(config_element), DhcpConfigError);
+
+ config = "{ \"unknown-integer\": 1234 }";
+ ASSERT_THROW(parser.build(config_element), DhcpConfigError);
+}
+
+// This test checks the boolean parameters
+TEST_F(SeDhcp6ParserTest, booleanParameters) {
+ std::string config = "{ \"sign-answers\": false }";
+
+ ElementPtr config_element = Element::fromJSON(config);
+
+ ParserContextPtr parser_context(new ParserContext(Option::V6));
+
+ SeDhcp6Parser parser("secure-Dhcp6", *parser_context);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"sign-answers\": \"foo\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), TypeError);
+
+ config = "{ \"timestamp-answers\": true }";
+ config_element = Element::fromJSON(config);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"timestamp-answers\": \"foobar\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), TypeError);
+
+ config = "{ \"check-authorizations\": true }";
+ config_element = Element::fromJSON(config);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"check-authorizations\": \"foobar\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), TypeError);
+
+ config = "{ \"check-signatures\": true }";
+ config_element = Element::fromJSON(config);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"check-signatures\": \"foobar\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), TypeError);
+
+ config = "{ \"check-timestamps\": true }";
+ config_element = Element::fromJSON(config);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"check-timestamps\": \"foobar\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), TypeError);
+}
+
+// This test checks string parameters
+TEST_F(SeDhcp6ParserTest, stringParameters) {
+ std::string config = "{ \"public-key\": \"foobar\" }";
+
+ ElementPtr config_element = Element::fromJSON(config);
+
+ ParserContextPtr parser_context(new ParserContext(Option::V6));
+
+ SeDhcp6Parser parser("secure-Dhcp6", *parser_context);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"public-key\": true }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), TypeError);
+
+ config = "{ \"certificate\": \"foobar\" }";
+ config_element = Element::fromJSON(config);
+ SeDhcp6Parser parser2("secure-Dhcp6", *parser_context);
+ ASSERT_NO_THROW(parser2.build(config_element));
+
+ config = "{ \"certificate\": false }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser2.build(config_element), TypeError);
+
+ // other string parameters have constrainted values
+}
+
+// This test checks algorithm values
+TEST_F(SeDhcp6ParserTest, algorithms) {
+ std::string config = "{ \"signature-algorithm\": \"RSA\" }";
+
+ ElementPtr config_element = Element::fromJSON(config);
+
+ ParserContextPtr parser_context(new ParserContext(Option::V6));
+
+ SeDhcp6Parser parser("secure-Dhcp6", *parser_context);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"signature-algorithm\": \"DSA\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), DhcpConfigError);
+
+ config = "{ \"hash-algorithm\": \"SHA-256\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"hash-algorithm\": \"SHA-512\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"hash-algorithm\": \"MD5\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), DhcpConfigError);
+
+ // Verify the default
+}
+
+// This test checks enabled signing of answers
+TEST_F(SeDhcp6ParserTest, signing) {
+ std::string config = "{ \"sign-answers\": false }";
+
+ ElementPtr config_element = Element::fromJSON(config);
+
+ ParserContextPtr parser_context(new ParserContext(Option::V6));
+
+ SeDhcp6Parser parser("secure-Dhcp6", *parser_context);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ // Not public key and certificate at the same time
+ // Need real files!
+ config = "{ \"public-key\": \"my-pub-key\","
+ " \"certificate\": \"my-certificate\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), DhcpConfigError);
+
+ // Either public key or certificate when signing is enabled
+ config = "{ \"sign-answers\": true }";
+ config_element = Element::fromJSON(config);
+ SeDhcp6Parser parser2("secure-Dhcp6", *parser_context);
+ ASSERT_THROW(parser2.build(config_element), DhcpConfigError);
+
+ config = "{ \"sign-answers\": true,"
+ " \"public-key\": \"my-pub-key\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_NO_THROW(parser2.build(config_element));
+
+ config = "{ \"sign-answers\": true,"
+ " \"certificate\": \"my-certificate\" }";
+ config_element = Element::fromJSON(config);
+ SeDhcp6Parser parser3("secure-Dhcp6", *parser_context);
+ ASSERT_NO_THROW(parser3.build(config_element));
+}
+
+// This test checks the parsing of validation policy syntax
+TEST_F(SeDhcp6ParserTest, validationPolicy) {
+ std::string config = "{ \"validation-policy\": \"offline\" }";
+
+ ElementPtr config_element = Element::fromJSON(config);
+
+ ParserContextPtr parser_context(new ParserContext(Option::V6));
+
+ SeDhcp6Parser parser("secure-Dhcp6", *parser_context);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"validation-policy\": \"online\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_NO_THROW(parser.build(config_element));
+
+ config = "{ \"validation-policy\": \"forever\" }";
+ config_element = Element::fromJSON(config);
+ ASSERT_THROW(parser.build(config_element), DhcpConfigError);
+}
+
+} // end of anonymous namespace