split configuration into pieces
Change-Id: I3039a3e15d9637e05b0f9678a7141258fb49e983
diff --git a/src/ca-module.hpp b/src/ca-module.hpp
index 5a3da6a..e98638b 100644
--- a/src/ca-module.hpp
+++ b/src/ca-module.hpp
@@ -21,7 +21,7 @@
#ifndef NDNCERT_CA_MODULE_HPP
#define NDNCERT_CA_MODULE_HPP
-#include "configuration.hpp"
+#include "detail/ca-configuration.hpp"
#include "detail/crypto-helpers.hpp"
#include "detail/ca-storage.hpp"
diff --git a/src/configuration.cpp b/src/configuration.cpp
deleted file mode 100644
index a56f490..0000000
--- a/src/configuration.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2017-2020, Regents of the University of California.
- *
- * This file is part of ndncert, a certificate management system based on NDN.
- *
- * ndncert is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received copies of the GNU General Public License along with
- * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndncert authors and contributors.
- */
-
-#include "configuration.hpp"
-#include "identity-challenge/challenge-module.hpp"
-#include "name-assignment/assignment-func.hpp"
-#include <ndn-cxx/util/io.hpp>
-#include <boost/filesystem.hpp>
-
-namespace ndn {
-namespace ndncert {
-
-// Parse CA Configuration file
-const std::string CONFIG_CA_PREFIX = "ca-prefix";
-const std::string CONFIG_CA_INFO = "ca-info";
-const std::string CONFIG_MAX_VALIDITY_PERIOD = "max-validity-period";
-const std::string CONFIG_MAX_SUFFIX_LENGTH = "max-suffix-length";
-const std::string CONFIG_PROBE_PARAMETERS = "probe-parameters";
-const std::string CONFIG_PROBE_PARAMETER = "probe-parameter-key";
-const std::string CONFIG_SUPPORTED_CHALLENGES = "supported-challenges";
-const std::string CONFIG_CHALLENGE = "challenge";
-const std::string CONFIG_CERTIFICATE = "certificate";
-const std::string CONFIG_REDIRECTION = "redirect-to";
-const std::string CONFIG_NAME_ASSIGNMENT = "name-assignment";
-
-void
-CaProfile::parse(const JsonSection& configJson)
-{
- // CA prefix
- m_caPrefix = Name(configJson.get(CONFIG_CA_PREFIX, ""));
- if (m_caPrefix.empty()) {
- NDN_THROW(std::runtime_error("Cannot parse ca-prefix from the config file"));
- }
- // CA info
- m_caInfo = configJson.get(CONFIG_CA_INFO, "");
- // CA max validity period
- m_maxValidityPeriod = time::seconds(configJson.get(CONFIG_MAX_VALIDITY_PERIOD, 86400));
- // CA max suffix length
- m_maxSuffixLength = nullopt;
- auto maxSuffixLength = configJson.get_optional<size_t>(CONFIG_MAX_SUFFIX_LENGTH);
- if (maxSuffixLength) {
- m_maxSuffixLength = *maxSuffixLength;
- }
- // probe parameter keys
- m_probeParameterKeys.clear();
- auto probeParametersJson = configJson.get_child_optional(CONFIG_PROBE_PARAMETERS);
- if (probeParametersJson) {
- for (const auto& item : *probeParametersJson) {
- auto probeParameter = item.second.get(CONFIG_PROBE_PARAMETER, "");
- probeParameter = boost::algorithm::to_lower_copy(probeParameter);
- if (probeParameter == "") {
- NDN_THROW(std::runtime_error("Probe parameter key cannot be empty."));
- }
- m_probeParameterKeys.push_back(probeParameter);
- }
- }
- // supported challenges
- m_supportedChallenges.clear();
- auto challengeListJson = configJson.get_child_optional(CONFIG_SUPPORTED_CHALLENGES);
- if (challengeListJson) {
- for (const auto& item : *challengeListJson) {
- auto challengeType = item.second.get(CONFIG_CHALLENGE, "");
- challengeType = boost::algorithm::to_lower_copy(challengeType);
- if (challengeType == "") {
- NDN_THROW(std::runtime_error("Challenge type canont be empty."));
- }
- if (!ChallengeModule::isChallengeSupported(challengeType)) {
- NDN_THROW(std::runtime_error("Challenge " + challengeType + " is not supported."));
- }
- m_supportedChallenges.push_back(challengeType);
- }
- }
- // anchor certificate
- m_cert = nullptr;
- auto certificateStr = configJson.get(CONFIG_CERTIFICATE, "");
- if (certificateStr != "") {
- std::istringstream ss(certificateStr);
- m_cert = io::load<security::Certificate>(ss);
- }
-}
-
-JsonSection
-CaProfile::toJson() const
-{
- JsonSection caItem;
- caItem.put(CONFIG_CA_PREFIX, m_caPrefix.toUri());
- caItem.put(CONFIG_CA_INFO, m_caInfo);
- caItem.put(CONFIG_MAX_VALIDITY_PERIOD, m_maxValidityPeriod.count());
- if (m_maxSuffixLength) {
- caItem.put(CONFIG_MAX_SUFFIX_LENGTH, *m_maxSuffixLength);
- }
- if (!m_probeParameterKeys.empty()) {
- JsonSection probeParametersJson;
- for (const auto& key : m_probeParameterKeys) {
- JsonSection keyJson;
- keyJson.put(CONFIG_PROBE_PARAMETER, key);
- probeParametersJson.push_back(std::make_pair("", keyJson));
- }
- caItem.add_child("", probeParametersJson);
- }
- if (!m_supportedChallenges.empty()) {
- JsonSection challengeListJson;
- for (const auto& challenge : m_supportedChallenges) {
- JsonSection challengeJson;
- challengeJson.put(CONFIG_CHALLENGE, challenge);
- challengeListJson.push_back(std::make_pair("", challengeJson));
- }
- caItem.add_child("", challengeListJson);
- }
- if (m_cert != nullptr) {
- std::stringstream ss;
- io::save(*m_cert, ss);
- caItem.put("certificate", ss.str());
- }
- return caItem;
-}
-
-namespace ca {
-
-void
-CaConfig::load(const std::string& fileName)
-{
- JsonSection configJson;
- try {
- boost::property_tree::read_json(fileName, configJson);
- }
- catch (const std::exception& error) {
- NDN_THROW(std::runtime_error("Failed to parse configuration file " + fileName + ", " + error.what()));
- }
- if (configJson.begin() == configJson.end()) {
- NDN_THROW(std::runtime_error("No JSON configuration found in file: " + fileName));
- }
- m_caItem.parse(configJson);
- if (m_caItem.m_supportedChallenges.size() == 0) {
- NDN_THROW(std::runtime_error("At least one challenge should be specified."));
- }
- // parse redirection section if appears
- m_redirection = nullopt;
- auto redirectionItems = configJson.get_child_optional(CONFIG_REDIRECTION);
- if (redirectionItems) {
- for (const auto& item : *redirectionItems) {
- auto caPrefixStr = item.second.get(CONFIG_CA_PREFIX, "");
- auto caCertStr = item.second.get(CONFIG_CERTIFICATE, "");
- if (caCertStr == "") {
- NDN_THROW(std::runtime_error("Redirect-to item's ca-prefix or certificate cannot be empty."));
- }
- std::istringstream ss(caCertStr);
- auto caCert = io::load<security::Certificate>(ss);
- if (!m_redirection) {
- m_redirection = std::vector<std::shared_ptr<security::Certificate>>();
- }
- m_redirection->push_back(caCert);
- }
- }
- //parse name assignment if appears
- m_nameAssignmentFuncs.clear();
- auto nameAssignmentItems = configJson.get_child_optional(CONFIG_NAME_ASSIGNMENT);
- if (nameAssignmentItems) {
- for (const auto& item : *nameAssignmentItems) {
- auto func = NameAssignmentFunc::createNameAssignmentFunc(item.first, item.second.data());
- if (func == nullptr) {
- NDN_THROW(std::runtime_error("Error on creating name assignment function"));
- }
- m_nameAssignmentFuncs.push_back(std::move(func));
- }
- }
-}
-
-} // namespace ca
-
-namespace requester {
-
-void
-ProfileStorage::load(const std::string& fileName)
-{
- JsonSection configJson;
- try {
- boost::property_tree::read_json(fileName, configJson);
- }
- catch (const std::exception& error) {
- NDN_THROW(std::runtime_error("Failed to parse configuration file " + fileName + ", " + error.what()));
- }
- if (configJson.begin() == configJson.end()) {
- NDN_THROW(std::runtime_error("No JSON configuration found in file: " + fileName));
- }
- load(configJson);
-}
-
-void
-ProfileStorage::load(const JsonSection& configSection)
-{
- m_caItems.clear();
- auto caList = configSection.get_child("ca-list");
- for (auto item : caList) {
- CaProfile caItem;
- caItem.parse(item.second);
- if (caItem.m_cert == nullptr) {
- NDN_THROW(std::runtime_error("No CA certificate is loaded from JSON configuration."));
- }
- m_caItems.push_back(std::move(caItem));
- }
-}
-
-void
-ProfileStorage::save(const std::string& fileName) const
-{
- JsonSection configJson;
- for (const auto& caItem : m_caItems) {
- configJson.push_back(std::make_pair("", caItem.toJson()));
- }
- std::stringstream ss;
- boost::property_tree::write_json(ss, configJson);
- std::ofstream configFile;
- configFile.open(fileName);
- configFile << ss.str();
- configFile.close();
-}
-
-void
-ProfileStorage::removeCaProfile(const Name& caName)
-{
- m_caItems.remove_if([&](const CaProfile& item) { return item.m_caPrefix == caName; });
-}
-
-void
-ProfileStorage::addCaProfile(const CaProfile& profile)
-{
- for (auto& item : m_caItems) {
- if (item.m_caPrefix == profile.m_caPrefix) {
- item = profile;
- return;
- }
- }
- m_caItems.push_back(profile);
-}
-
-const std::list<CaProfile>&
-ProfileStorage::getCaItems() const
-{
- return m_caItems;
-}
-
-} // namespace requester
-} // namespace ndncert
-} // namespace ndn
diff --git a/src/configuration.hpp b/src/configuration.hpp
deleted file mode 100644
index 4e466e2..0000000
--- a/src/configuration.hpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2017-2020, Regents of the University of California.
- *
- * This file is part of ndncert, a certificate management system based on NDN.
- *
- * ndncert is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received copies of the GNU General Public License along with
- * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndncert authors and contributors.
- */
-
-#ifndef NDNCERT_CONFIGURATION_HPP
-#define NDNCERT_CONFIGURATION_HPP
-
-#include "detail/ca-request-state.hpp"
-#include "name-assignment/assignment-func.hpp"
-
-namespace ndn {
-namespace ndncert {
-
-struct CaProfile {
-public:
- /**
- * Parse the configuration json and modify current struct to the result.
- * @param configJson the configuration json to parse
- */
- void
- parse(const JsonSection& configJson);
-
- /**
- * @return the JSON representation of this profile.
- */
- JsonSection
- toJson() const;
-
-public:
- /**
- * CA Name prefix (without /CA suffix).
- */
- Name m_caPrefix;
- /**
- * CA Information.
- * Default: "".
- */
- std::string m_caInfo;
- /**
- * A list of parameter-keys for PROBE.
- * Default: empty list.
- */
- std::list<std::string> m_probeParameterKeys;
- /**
- * Maximum allowed validity period of the certificate being requested.
- * The value is in the unit of second.
- * Default: one day (86400 seconds).
- */
- time::seconds m_maxValidityPeriod;
- /**
- * Maximum allowed suffix length of requested name.
- * E.g., When its value is 2, at most 2 name components can be assigned after m_caPrefix.
- * Default: none.
- */
- optional<size_t> m_maxSuffixLength = nullopt;
- /**
- * A list of supported challenges. Only CA side will have m_supportedChallenges.
- * Default: empty list.
- */
- std::list<std::string> m_supportedChallenges;
- /**
- * CA's certificate. Only Client side will have m_cert.
- * Default: nullptr.
- */
- std::shared_ptr<security::Certificate> m_cert;
-
-private:
- void
- parseProbeParameters(const JsonSection& section);
-
- void
- parseChallengeList(const JsonSection& configSection);
-};
-
-namespace ca {
-
-/**
- * @brief CA's configuration on NDNCERT.
- * @sa https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.3#213-ca-profile
- *
- * The format of CA configuration in JSON
- * {
- * "ca-prefix": "",
- * "ca-info": "",
- * "max-validity-period": "",
- * "max-suffix-length": "",
- * "probe-parameters":
- * [
- * {"probe-parameter-key": ""},
- * {"probe-parameter-key": ""}
- * ]
- * "supported-challenges":
- * [
- * {"challenge": ""},
- * {"challenge": ""}
- * ]
- * }
- */
-class CaConfig
-{
-public:
- /**
- * Load CA configuration from the file.
- * @throw std::runtime_error when config file cannot be correctly parsed.
- */
- void
- load(const std::string& fileName);
-
-public:
- CaProfile m_caItem;
- /**
- * Used for CA redirection
- * @sa https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.3-PROBE-Extensions#probe-extension-for-redirection
- */
- optional<std::vector<std::shared_ptr<security::Certificate>>> m_redirection = nullopt;
- /**
- * Name Assignment Functions
- */
- std::vector<std::unique_ptr<NameAssignmentFunc>> m_nameAssignmentFuncs;
-};
-
-} // namespace ca
-
-namespace requester {
-
-/**
- * @brief Represents Client configuration
- * @sa https://github.com/named-data/ndncert/wiki/Client-Configuration-Sample
- */
-class ProfileStorage
-{
-public:
- /**
- * @throw std::runtime_error when config file cannot be correctly parsed.
- */
- void
- load(const std::string& fileName);
-
- /**
- * @throw std::runtime_error when config file cannot be correctly parsed.
- */
- void
- load(const JsonSection& configSection);
-
- void
- save(const std::string& fileName) const;
-
- void
- removeCaProfile(const Name& caName);
-
- /**
- * Be cautious. This will add a new trust anchor for requesters.
- */
- void
- addCaProfile(const CaProfile& profile);
-
- const std::list<CaProfile>&
- getCaItems() const;
-
-private:
- std::list<CaProfile> m_caItems;
-};
-
-} // namespace requester
-} // namespace ndncert
-} // namespace ndn
-
-#endif // NDNCERT_CONFIGURATION_HPP
diff --git a/src/detail/ca-configuration.cpp b/src/detail/ca-configuration.cpp
new file mode 100644
index 0000000..b88352b
--- /dev/null
+++ b/src/detail/ca-configuration.cpp
@@ -0,0 +1,82 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2017-2020, Regents of the University of California.
+ *
+ * This file is part of ndncert, a certificate management system based on NDN.
+ *
+ * ndncert is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndncert authors and contributors.
+ */
+
+#include "detail/ca-configuration.hpp"
+#include "identity-challenge/challenge-module.hpp"
+#include "name-assignment/assignment-func.hpp"
+#include <ndn-cxx/util/io.hpp>
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace ndncert {
+namespace ca {
+
+void
+CaConfig::load(const std::string& fileName)
+{
+ JsonSection configJson;
+ try {
+ boost::property_tree::read_json(fileName, configJson);
+ }
+ catch (const std::exception& error) {
+ NDN_THROW(std::runtime_error("Failed to parse configuration file " + fileName + ", " + error.what()));
+ }
+ if (configJson.begin() == configJson.end()) {
+ NDN_THROW(std::runtime_error("No JSON configuration found in file: " + fileName));
+ }
+ m_caItem.parse(configJson);
+ if (m_caItem.m_supportedChallenges.size() == 0) {
+ NDN_THROW(std::runtime_error("At least one challenge should be specified."));
+ }
+ // parse redirection section if appears
+ m_redirection = nullopt;
+ auto redirectionItems = configJson.get_child_optional(CONFIG_REDIRECTION);
+ if (redirectionItems) {
+ for (const auto& item : *redirectionItems) {
+ auto caPrefixStr = item.second.get(CONFIG_CA_PREFIX, "");
+ auto caCertStr = item.second.get(CONFIG_CERTIFICATE, "");
+ if (caCertStr == "") {
+ NDN_THROW(std::runtime_error("Redirect-to item's ca-prefix or certificate cannot be empty."));
+ }
+ std::istringstream ss(caCertStr);
+ auto caCert = io::load<security::Certificate>(ss);
+ if (!m_redirection) {
+ m_redirection = std::vector<std::shared_ptr<security::Certificate>>();
+ }
+ m_redirection->push_back(caCert);
+ }
+ }
+ // parse name assignment if appears
+ m_nameAssignmentFuncs.clear();
+ auto nameAssignmentItems = configJson.get_child_optional(CONFIG_NAME_ASSIGNMENT);
+ if (nameAssignmentItems) {
+ for (const auto& item : *nameAssignmentItems) {
+ auto func = NameAssignmentFunc::createNameAssignmentFunc(item.first, item.second.data());
+ if (func == nullptr) {
+ NDN_THROW(std::runtime_error("Error on creating name assignment function"));
+ }
+ m_nameAssignmentFuncs.push_back(std::move(func));
+ }
+ }
+}
+
+} // namespace ca
+} // namespace ndncert
+} // namespace ndn
diff --git a/src/detail/ca-configuration.hpp b/src/detail/ca-configuration.hpp
new file mode 100644
index 0000000..da170b9
--- /dev/null
+++ b/src/detail/ca-configuration.hpp
@@ -0,0 +1,79 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2017-2020, Regents of the University of California.
+ *
+ * This file is part of ndncert, a certificate management system based on NDN.
+ *
+ * ndncert is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndncert authors and contributors.
+ */
+
+#ifndef NDNCERT_DETAIL_CA_CONFIGURATION_HPP
+#define NDNCERT_DETAIL_CA_CONFIGURATION_HPP
+
+#include "detail/ca-profile.hpp"
+
+namespace ndn {
+namespace ndncert {
+namespace ca {
+
+/**
+ * @brief CA's configuration on NDNCERT.
+ * @sa https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.3
+ *
+ * The format of CA configuration in JSON
+ * {
+ * "ca-prefix": "",
+ * "ca-info": "",
+ * "max-validity-period": "",
+ * "max-suffix-length": "",
+ * "probe-parameters":
+ * [
+ * {"probe-parameter-key": ""},
+ * {"probe-parameter-key": ""}
+ * ]
+ * "supported-challenges":
+ * [
+ * {"challenge": ""},
+ * {"challenge": ""}
+ * ]
+ * }
+ */
+class CaConfig
+{
+public:
+ /**
+ * Load CA configuration from the file.
+ * @throw std::runtime_error when config file cannot be correctly parsed.
+ */
+ void
+ load(const std::string& fileName);
+
+public:
+ CaProfile m_caItem;
+ /**
+ * Used for CA redirection
+ * @sa https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.3-PROBE-Extensions#probe-extension-for-redirection
+ */
+ optional<std::vector<std::shared_ptr<security::Certificate>>> m_redirection = nullopt;
+ /**
+ * Name Assignment Functions
+ */
+ std::vector<std::unique_ptr<NameAssignmentFunc>> m_nameAssignmentFuncs;
+};
+
+} // namespace ca
+} // namespace ndncert
+} // namespace ndn
+
+#endif // NDNCERT_DETAIL_CA_CONFIGURATION_HPP
diff --git a/src/detail/ca-profile.cpp b/src/detail/ca-profile.cpp
new file mode 100644
index 0000000..4599e06
--- /dev/null
+++ b/src/detail/ca-profile.cpp
@@ -0,0 +1,123 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2017-2020, Regents of the University of California.
+ *
+ * This file is part of ndncert, a certificate management system based on NDN.
+ *
+ * ndncert is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndncert authors and contributors.
+ */
+
+#include "detail/ca-profile.hpp"
+#include "identity-challenge/challenge-module.hpp"
+#include "name-assignment/assignment-func.hpp"
+#include <ndn-cxx/util/io.hpp>
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace ndncert {
+
+void
+CaProfile::parse(const JsonSection& configJson)
+{
+ // CA prefix
+ m_caPrefix = Name(configJson.get(CONFIG_CA_PREFIX, ""));
+ if (m_caPrefix.empty()) {
+ NDN_THROW(std::runtime_error("Cannot parse ca-prefix from the config file"));
+ }
+ // CA info
+ m_caInfo = configJson.get(CONFIG_CA_INFO, "");
+ // CA max validity period
+ m_maxValidityPeriod = time::seconds(configJson.get(CONFIG_MAX_VALIDITY_PERIOD, 86400));
+ // CA max suffix length
+ m_maxSuffixLength = nullopt;
+ auto maxSuffixLength = configJson.get_optional<size_t>(CONFIG_MAX_SUFFIX_LENGTH);
+ if (maxSuffixLength) {
+ m_maxSuffixLength = *maxSuffixLength;
+ }
+ // probe parameter keys
+ m_probeParameterKeys.clear();
+ auto probeParametersJson = configJson.get_child_optional(CONFIG_PROBE_PARAMETERS);
+ if (probeParametersJson) {
+ for (const auto& item : *probeParametersJson) {
+ auto probeParameter = item.second.get(CONFIG_PROBE_PARAMETER, "");
+ probeParameter = boost::algorithm::to_lower_copy(probeParameter);
+ if (probeParameter == "") {
+ NDN_THROW(std::runtime_error("Probe parameter key cannot be empty."));
+ }
+ m_probeParameterKeys.push_back(probeParameter);
+ }
+ }
+ // supported challenges
+ m_supportedChallenges.clear();
+ auto challengeListJson = configJson.get_child_optional(CONFIG_SUPPORTED_CHALLENGES);
+ if (challengeListJson) {
+ for (const auto& item : *challengeListJson) {
+ auto challengeType = item.second.get(CONFIG_CHALLENGE, "");
+ challengeType = boost::algorithm::to_lower_copy(challengeType);
+ if (challengeType == "") {
+ NDN_THROW(std::runtime_error("Challenge type canont be empty."));
+ }
+ if (!ChallengeModule::isChallengeSupported(challengeType)) {
+ NDN_THROW(std::runtime_error("Challenge " + challengeType + " is not supported."));
+ }
+ m_supportedChallenges.push_back(challengeType);
+ }
+ }
+ // anchor certificate
+ m_cert = nullptr;
+ auto certificateStr = configJson.get(CONFIG_CERTIFICATE, "");
+ if (certificateStr != "") {
+ std::istringstream ss(certificateStr);
+ m_cert = io::load<security::Certificate>(ss);
+ }
+}
+
+JsonSection
+CaProfile::toJson() const
+{
+ JsonSection caItem;
+ caItem.put(CONFIG_CA_PREFIX, m_caPrefix.toUri());
+ caItem.put(CONFIG_CA_INFO, m_caInfo);
+ caItem.put(CONFIG_MAX_VALIDITY_PERIOD, m_maxValidityPeriod.count());
+ if (m_maxSuffixLength) {
+ caItem.put(CONFIG_MAX_SUFFIX_LENGTH, *m_maxSuffixLength);
+ }
+ if (!m_probeParameterKeys.empty()) {
+ JsonSection probeParametersJson;
+ for (const auto& key : m_probeParameterKeys) {
+ JsonSection keyJson;
+ keyJson.put(CONFIG_PROBE_PARAMETER, key);
+ probeParametersJson.push_back(std::make_pair("", keyJson));
+ }
+ caItem.add_child("", probeParametersJson);
+ }
+ if (!m_supportedChallenges.empty()) {
+ JsonSection challengeListJson;
+ for (const auto& challenge : m_supportedChallenges) {
+ JsonSection challengeJson;
+ challengeJson.put(CONFIG_CHALLENGE, challenge);
+ challengeListJson.push_back(std::make_pair("", challengeJson));
+ }
+ caItem.add_child("", challengeListJson);
+ }
+ if (m_cert != nullptr) {
+ std::stringstream ss;
+ io::save(*m_cert, ss);
+ caItem.put("certificate", ss.str());
+ }
+ return caItem;
+}
+
+} // namespace ndncert
+} // namespace ndn
diff --git a/src/detail/ca-profile.hpp b/src/detail/ca-profile.hpp
new file mode 100644
index 0000000..c67f5dc
--- /dev/null
+++ b/src/detail/ca-profile.hpp
@@ -0,0 +1,100 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2017-2020, Regents of the University of California.
+ *
+ * This file is part of ndncert, a certificate management system based on NDN.
+ *
+ * ndncert is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndncert authors and contributors.
+ */
+
+#ifndef NDNCERT_DETAIL_CA_PROFILE_HPP
+#define NDNCERT_DETAIL_CA_PROFILE_HPP
+
+#include "name-assignment/assignment-func.hpp"
+
+namespace ndn {
+namespace ndncert {
+
+// used in parsing CA configuration file and Client CA profile storage file
+const std::string CONFIG_CA_PREFIX = "ca-prefix";
+const std::string CONFIG_CA_INFO = "ca-info";
+const std::string CONFIG_MAX_VALIDITY_PERIOD = "max-validity-period";
+const std::string CONFIG_MAX_SUFFIX_LENGTH = "max-suffix-length";
+const std::string CONFIG_PROBE_PARAMETERS = "probe-parameters";
+const std::string CONFIG_PROBE_PARAMETER = "probe-parameter-key";
+const std::string CONFIG_SUPPORTED_CHALLENGES = "supported-challenges";
+const std::string CONFIG_CHALLENGE = "challenge";
+const std::string CONFIG_CERTIFICATE = "certificate";
+const std::string CONFIG_REDIRECTION = "redirect-to";
+const std::string CONFIG_NAME_ASSIGNMENT = "name-assignment";
+
+struct CaProfile
+{
+public:
+ /**
+ * Parse the configuration json and modify current struct to the result.
+ * @param configJson the configuration json to parse
+ */
+ void
+ parse(const JsonSection& configJson);
+
+ /**
+ * @return the JSON representation of this profile.
+ */
+ JsonSection
+ toJson() const;
+
+public:
+ /**
+ * CA Name prefix (without /CA suffix).
+ */
+ Name m_caPrefix;
+ /**
+ * CA Information.
+ * Default: "".
+ */
+ std::string m_caInfo;
+ /**
+ * A list of parameter-keys for PROBE.
+ * Default: empty list.
+ */
+ std::list<std::string> m_probeParameterKeys;
+ /**
+ * Maximum allowed validity period of the certificate being requested.
+ * The value is in the unit of second.
+ * Default: one day (86400 seconds).
+ */
+ time::seconds m_maxValidityPeriod;
+ /**
+ * Maximum allowed suffix length of requested name.
+ * E.g., When its value is 2, at most 2 name components can be assigned after m_caPrefix.
+ * Default: none.
+ */
+ optional<size_t> m_maxSuffixLength = nullopt;
+ /**
+ * A list of supported challenges. Only CA side will have m_supportedChallenges.
+ * Default: empty list.
+ */
+ std::list<std::string> m_supportedChallenges;
+ /**
+ * CA's certificate. Only Client side will have m_cert.
+ * Default: nullptr.
+ */
+ std::shared_ptr<security::Certificate> m_cert;
+};
+
+} // namespace ndncert
+} // namespace ndn
+
+#endif // NDNCERT_DETAIL_CA_PROFILE_HPP
diff --git a/src/detail/error-encoder.hpp b/src/detail/error-encoder.hpp
index 99d9dd8..67fe80f 100644
--- a/src/detail/error-encoder.hpp
+++ b/src/detail/error-encoder.hpp
@@ -21,7 +21,7 @@
#ifndef NDNCERT_DETAIL_ERROR_ENCODER_HPP
#define NDNCERT_DETAIL_ERROR_ENCODER_HPP
-#include "configuration.hpp"
+#include "detail/ca-profile.hpp"
namespace ndn {
namespace ndncert {
diff --git a/src/detail/info-encoder.hpp b/src/detail/info-encoder.hpp
index 03adfd8..7f9180e 100644
--- a/src/detail/info-encoder.hpp
+++ b/src/detail/info-encoder.hpp
@@ -21,7 +21,7 @@
#ifndef NDNCERT_DETAIL_INFO_ENCODER_HPP
#define NDNCERT_DETAIL_INFO_ENCODER_HPP
-#include "configuration.hpp"
+#include "detail/ca-profile.hpp"
namespace ndn {
namespace ndncert {
diff --git a/src/detail/profile-storage.cpp b/src/detail/profile-storage.cpp
new file mode 100644
index 0000000..f880d1b
--- /dev/null
+++ b/src/detail/profile-storage.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2017-2020, Regents of the University of California.
+ *
+ * This file is part of ndncert, a certificate management system based on NDN.
+ *
+ * ndncert is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndncert authors and contributors.
+ */
+
+#include "detail/profile-storage.hpp"
+#include "identity-challenge/challenge-module.hpp"
+#include "name-assignment/assignment-func.hpp"
+#include <ndn-cxx/util/io.hpp>
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace ndncert {
+namespace requester {
+
+void
+ProfileStorage::load(const std::string& fileName)
+{
+ JsonSection configJson;
+ try {
+ boost::property_tree::read_json(fileName, configJson);
+ }
+ catch (const std::exception& error) {
+ NDN_THROW(std::runtime_error("Failed to parse configuration file " + fileName + ", " + error.what()));
+ }
+ if (configJson.begin() == configJson.end()) {
+ NDN_THROW(std::runtime_error("No JSON configuration found in file: " + fileName));
+ }
+ load(configJson);
+}
+
+void
+ProfileStorage::load(const JsonSection& configSection)
+{
+ m_caItems.clear();
+ auto caList = configSection.get_child("ca-list");
+ for (auto item : caList) {
+ CaProfile caItem;
+ caItem.parse(item.second);
+ if (caItem.m_cert == nullptr) {
+ NDN_THROW(std::runtime_error("No CA certificate is loaded from JSON configuration."));
+ }
+ m_caItems.push_back(std::move(caItem));
+ }
+}
+
+void
+ProfileStorage::save(const std::string& fileName) const
+{
+ JsonSection configJson;
+ for (const auto& caItem : m_caItems) {
+ configJson.push_back(std::make_pair("", caItem.toJson()));
+ }
+ std::stringstream ss;
+ boost::property_tree::write_json(ss, configJson);
+ std::ofstream configFile;
+ configFile.open(fileName);
+ configFile << ss.str();
+ configFile.close();
+}
+
+void
+ProfileStorage::removeCaProfile(const Name& caName)
+{
+ m_caItems.remove_if([&](const CaProfile& item) { return item.m_caPrefix == caName; });
+}
+
+void
+ProfileStorage::addCaProfile(const CaProfile& profile)
+{
+ for (auto& item : m_caItems) {
+ if (item.m_caPrefix == profile.m_caPrefix) {
+ item = profile;
+ return;
+ }
+ }
+ m_caItems.push_back(profile);
+}
+
+const std::list<CaProfile>&
+ProfileStorage::getCaItems() const
+{
+ return m_caItems;
+}
+
+} // namespace requester
+} // namespace ndncert
+} // namespace ndn
diff --git a/src/detail/profile-storage.hpp b/src/detail/profile-storage.hpp
new file mode 100644
index 0000000..0f8d1ce
--- /dev/null
+++ b/src/detail/profile-storage.hpp
@@ -0,0 +1,73 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2017-2020, Regents of the University of California.
+ *
+ * This file is part of ndncert, a certificate management system based on NDN.
+ *
+ * ndncert is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ndncert, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndncert authors and contributors.
+ */
+
+#ifndef NDNCERT_CONFIGURATION_HPP
+#define NDNCERT_CONFIGURATION_HPP
+
+#include "detail/ca-profile.hpp"
+#include "name-assignment/assignment-func.hpp"
+
+namespace ndn {
+namespace ndncert {
+namespace requester {
+
+/**
+ * @brief Represents Client configuration
+ * @sa https://github.com/named-data/ndncert/wiki/Client-Configuration-Sample
+ */
+class ProfileStorage
+{
+public:
+ /**
+ * @throw std::runtime_error when config file cannot be correctly parsed.
+ */
+ void
+ load(const std::string& fileName);
+
+ /**
+ * @throw std::runtime_error when config file cannot be correctly parsed.
+ */
+ void
+ load(const JsonSection& configSection);
+
+ void
+ save(const std::string& fileName) const;
+
+ void
+ removeCaProfile(const Name& caName);
+
+ /**
+ * Be cautious. This will add a new trust anchor for requesters.
+ */
+ void
+ addCaProfile(const CaProfile& profile);
+
+ const std::list<CaProfile>&
+ getCaItems() const;
+
+private:
+ std::list<CaProfile> m_caItems;
+};
+
+} // namespace requester
+} // namespace ndncert
+} // namespace ndn
+
+#endif // NDNCERT_CONFIGURATION_HPP
diff --git a/src/requester-request-state.hpp b/src/requester-request-state.hpp
index c142a34..9c67409 100644
--- a/src/requester-request-state.hpp
+++ b/src/requester-request-state.hpp
@@ -23,7 +23,7 @@
#include "detail/ca-request-state.hpp"
#include "detail/crypto-helpers.hpp"
-#include "configuration.hpp"
+#include "detail/profile-storage.hpp"
namespace ndn {
namespace ndncert {