add redirection to CA config

Change-Id: I945bf6ac7aaac89bc7328b69caf566f2477edaf1
diff --git a/ca.conf.sample b/ca.conf.sample
index cdc2aab..ebb3320 100644
--- a/ca.conf.sample
+++ b/ca.conf.sample
@@ -7,10 +7,21 @@
   [
     {"probe-parameter-key": "email"},
     {"probe-parameter-key": "uid"}
-  ]
+  ],
   "supported-challenges":
   [
     { "challenge": "pin" },
     { "challenge": "email" }
+  ],
+  "redirect-to":
+  [
+    {
+      "ca-prefix": "/example/site1",
+      "certificate": "Bv0CJAcsCANuZG4IBXNpdGUxCANLRVkICBG8IvRjFf8XCARzZWxmCAn9AAABWcgU2aUUCRgBAhkEADbugBX9AU8wggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAES9Cb9iANUNYmwt5bjwNW1mZgjzIkDJb6FTCdiYWnkMMIVxh2YDllphoWDEAPS6kqJczzCuhnGYpZCp9tTaYKGxZMGwEDHB0HGwgDbmRuCAVzaXRlMQgDS0VZCAgRvCL0YxX/F/0A/Sb9AP4PMTk3MDAxMDFUMDAwMDAw/QD/DzIwMzcwMTE3VDIxMjg0NhdIMEYCIQDXkR1hF3GiP7yLXq+0JBJfi9QC+hhAu/1Bykx+MWz6RAIhANwelBTxxZr2C5bD15mjfhWudK4I1tOb4b/9xWCHyM7F"
+    },
+    {
+      "ca-prefix": "/example/site2",
+      "certificate": "Bv0CJAcsCANuZG4IBXNpdGUxCANLRVkICBG8IvRjFf8XCARzZWxmCAn9AAABWcgU2aUUCRgBAhkEADbugBX9AU8wggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAES9Cb9iANUNYmwt5bjwNW1mZgjzIkDJb6FTCdiYWnkMMIVxh2YDllphoWDEAPS6kqJczzCuhnGYpZCp9tTaYKGxZMGwEDHB0HGwgDbmRuCAVzaXRlMQgDS0VZCAgRvCL0YxX/F/0A/Sb9AP4PMTk3MDAxMDFUMDAwMDAw/QD/DzIwMzcwMTE3VDIxMjg0NhdIMEYCIQDXkR1hF3GiP7yLXq+0JBJfi9QC+hhAu/1Bykx+MWz6RAIhANwelBTxxZr2C5bD15mjfhWudK4I1tOb4b/9xWCHyM7F"
+    }
   ]
 }
diff --git a/src/configuration.cpp b/src/configuration.cpp
index c4f2c72..18b71a0 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -71,7 +71,7 @@
   }
   // anchor certificate
   m_cert = nullptr;
-  auto certificateStr = configJson.get("certificate", "");
+  auto certificateStr = configJson.get(CONFIG_CERTIFICATE, "");
   if (certificateStr != "") {
     std::istringstream ss(certificateStr);
     m_cert = io::load<security::v2::Certificate>(ss);
@@ -129,17 +129,24 @@
   if (m_caItem.m_supportedChallenges.size() == 0) {
     BOOST_THROW_EXCEPTION(std::runtime_error("At least one challenge should be specified."));
   }
-}
-
-void
-CaConfig::save(const std::string& fileName) const
-{
-  std::stringstream ss;
-  boost::property_tree::write_json(ss, m_caItem.toJson());
-  std::ofstream configFile;
-  configFile.open(fileName);
-  configFile << ss.str();
-  configFile.close();
+  // parse redirection section if appears
+  m_redirection = boost::none;
+  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 (caPrefixStr == "" || caCertStr == "") {
+        BOOST_THROW_EXCEPTION(std::runtime_error("Redirect-to item's ca-prefix or certificate cannot be empty."));
+      }
+      std::istringstream ss(caCertStr);
+      auto caCert = io::load<security::v2::Certificate>(ss);
+      if (!m_redirection) {
+        m_redirection = RedirectionItems();
+      }
+      m_redirection->push_back(std::make_tuple(Name(caPrefixStr), caCert));
+    }
+  }
 }
 
 void
diff --git a/src/configuration.hpp b/src/configuration.hpp
index 7f4f8a4..e1706e7 100644
--- a/src/configuration.hpp
+++ b/src/configuration.hpp
@@ -131,11 +131,14 @@
   void
   load(const std::string& fileName);
 
-  void
-  save(const std::string& fileName) const;
-
   CaConfigItem m_caItem;
   /**
+   * Used for CA redirection as specified in
+   * https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.3-PROBE-Extensions#probe-extension-for-redirection
+   */
+  using RedirectionItems = std::vector<std::tuple<Name, std::shared_ptr<security::v2::Certificate>>>;
+  boost::optional<RedirectionItems> m_redirection;
+  /**
    * NameAssignmentFunc Callback function
    */
   NameAssignmentFunc m_nameAssignmentFunc;
diff --git a/src/ndncert-common.hpp b/src/ndncert-common.hpp
index ec77188..43f59d8 100644
--- a/src/ndncert-common.hpp
+++ b/src/ndncert-common.hpp
@@ -113,11 +113,14 @@
 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_MAX_SUFFIX_LENGTH = "max-suffix-length";
+const std::string CONFIG_CERTIFICATE = "certificate";
+const std::string CONFIG_REDIRECTION = "redirect-to";
+
 
 // NDNCERT Status Enum
 enum class Status : uint16_t {
diff --git a/tests/unit-tests/config-files/config-ca-5 b/tests/unit-tests/config-files/config-ca-5
new file mode 100644
index 0000000..531be55
--- /dev/null
+++ b/tests/unit-tests/config-files/config-ca-5
@@ -0,0 +1,21 @@
+{
+  "ca-prefix": "/ndn",
+  "ca-info": "unsupported challenge",
+  "max-validity-period": "86400",
+  "max-suffix-length": 3,
+  "probe-parameters":
+  [
+      { "probe-parameter-key": "full name" }
+  ],
+  "supported-challenges":
+  [
+      { "challenge": "pin" }
+  ],
+  "redirect-to":
+  [
+      {
+        "ca-prefix": "/ndn/edu/ucla",
+        "certificate": "Bv0CJAcsCANuZG4IBXNpdGUxCANLRVkICBG8IvRjFf8XCARzZWxmCAn9AAABWcgU2aUUCRgBAhkEADbugBX9AU8wggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAES9Cb9iANUNYmwt5bjwNW1mZgjzIkDJb6FTCdiYWnkMMIVxh2YDllphoWDEAPS6kqJczzCuhnGYpZCp9tTaYKGxZMGwEDHB0HGwgDbmRuCAVzaXRlMQgDS0VZCAgRvCL0YxX/F/0A/Sb9AP4PMTk3MDAxMDFUMDAwMDAw/QD/DzIwMzcwMTE3VDIxMjg0NhdIMEYCIQDXkR1hF3GiP7yLXq+0JBJfi9QC+hhAu/1Bykx+MWz6RAIhANwelBTxxZr2C5bD15mjfhWudK4I1tOb4b/9xWCHyM7F"
+      }
+  ]
+}
\ No newline at end of file
diff --git a/tests/unit-tests/configuration.t.cpp b/tests/unit-tests/configuration.t.cpp
index f1dd87f..3c73f12 100644
--- a/tests/unit-tests/configuration.t.cpp
+++ b/tests/unit-tests/configuration.t.cpp
@@ -50,6 +50,12 @@
   BOOST_CHECK_EQUAL(config.m_caItem.m_supportedChallenges.size(), 2);
   BOOST_CHECK_EQUAL(config.m_caItem.m_supportedChallenges.front(), "pin");
   BOOST_CHECK_EQUAL(config.m_caItem.m_supportedChallenges.back(), "email");
+
+  config.load("tests/unit-tests/config-files/config-ca-5");
+  BOOST_CHECK_EQUAL(config.m_redirection->size(), 1);
+  BOOST_CHECK_EQUAL(std::get<0>(config.m_redirection->at(0)), Name("/ndn/edu/ucla"));
+  BOOST_CHECK_EQUAL(std::get<1>(config.m_redirection->at(0))->getName(),
+                    "/ndn/site1/KEY/%11%BC%22%F4c%15%FF%17/self/%FD%00%00%01Y%C8%14%D9%A5");
 }
 
 BOOST_AUTO_TEST_CASE(CAConfigFileWithErrors)