mgmt: rename extractRequester() and support signed Interest v0.3

Change-Id: I6bb6635896fa1b9fa54beb70b902c5a35831dc9c
diff --git a/.jenkins.d/00-deps.sh b/.jenkins.d/00-deps.sh
index 6b135d9..1e36384 100755
--- a/.jenkins.d/00-deps.sh
+++ b/.jenkins.d/00-deps.sh
@@ -40,7 +40,7 @@
     fi
 
 elif [[ $ID_LIKE == *fedora* ]]; then
-    sudo dnf -y install gcc-c++ libasan pkgconf-pkg-config python3 \
+    sudo dnf -y install gcc-c++ libasan lld pkgconf-pkg-config python3 \
                         boost-devel openssl-devel sqlite-devel \
                         libpcap-devel systemd-devel
 fi
diff --git a/daemon/mgmt/manager-base.cpp b/daemon/mgmt/manager-base.cpp
index a39bbd6..ee5f782 100644
--- a/daemon/mgmt/manager-base.cpp
+++ b/daemon/mgmt/manager-base.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -58,22 +58,20 @@
   return m_dispatcher.addNotificationStream(makeRelPrefix(verb));
 }
 
-void
-ManagerBase::extractRequester(const Interest& interest,
-                              const ndn::mgmt::AcceptContinuation& accept)
+std::string
+ManagerBase::extractSigner(const Interest& interest)
 {
-  const Name& interestName = interest.getName();
-
   try {
-    ndn::SignatureInfo sigInfo(interestName.at(ndn::signed_interest::POS_SIG_INFO).blockFromValue());
-    if (!sigInfo.hasKeyLocator() || sigInfo.getKeyLocator().getType() != tlv::Name) {
-      return accept("");
+    // try v0.3 format first
+    auto sigInfo = interest.getSignatureInfo();
+    if (!sigInfo) {
+      // fallback to v0.2 format
+      sigInfo.emplace(interest.getName().at(ndn::signed_interest::POS_SIG_INFO).blockFromValue());
     }
-
-    accept(sigInfo.getKeyLocator().getName().toUri());
+    return sigInfo->getKeyLocator().getName().toUri();
   }
   catch (const tlv::Error&) {
-    accept("");
+    return "";
   }
 }
 
diff --git a/daemon/mgmt/manager-base.hpp b/daemon/mgmt/manager-base.hpp
index eeb55f5..592d4fa 100644
--- a/daemon/mgmt/manager-base.hpp
+++ b/daemon/mgmt/manager-base.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -92,15 +92,13 @@
 
 NFD_PUBLIC_WITH_TESTS_ELSE_PROTECTED: // helpers
   /**
-   * @brief Extracts the requester from a ControlCommand request.
+   * @brief Extracts the name from the %KeyLocator of a ControlCommand request.
    *
    * This is called after the signature has been validated.
-   *
-   * @param interest a request for ControlCommand
-   * @param accept callback of successful validation, takes the requester string as argument
+   * Returns an empty string if %SignatureInfo or %KeyLocator are missing or malformed.
    */
-  static void
-  extractRequester(const Interest& interest, const ndn::mgmt::AcceptContinuation& accept);
+  static std::string
+  extractSigner(const Interest& interest);
 
 NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   /**
diff --git a/daemon/mgmt/rib-manager.cpp b/daemon/mgmt/rib-manager.cpp
index afeca1c..484b4eb 100644
--- a/daemon/mgmt/rib-manager.cpp
+++ b/daemon/mgmt/rib-manager.cpp
@@ -313,7 +313,7 @@
 
     auto& validator = prefix == LOCALHOST_TOP_PREFIX ? m_localhostValidator : m_localhopValidator;
     validator.validate(interest,
-                       [&interest, accept] (auto&&...) { extractRequester(interest, accept); },
+                       [&interest, accept] (auto&&...) { accept(extractSigner(interest)); },
                        [reject] (auto&&...) { reject(ndn::mgmt::RejectReply::STATUS403); });
   };
 }
diff --git a/docs/INSTALL.rst b/docs/INSTALL.rst
index 468c346..ade7244 100644
--- a/docs/INSTALL.rst
+++ b/docs/INSTALL.rst
@@ -23,7 +23,7 @@
 - Fedora >= 29
 - Gentoo Linux
 - Raspberry Pi OS (formerly Raspbian) >= 2019-06-20
-- FreeBSD >= 12.0
+- FreeBSD >= 12.2
 
 .. _Install NFD on Ubuntu Linux using the NDN PPA repository:
 
diff --git a/tests/daemon/mgmt/command-authenticator.t.cpp b/tests/daemon/mgmt/command-authenticator.t.cpp
index 3c2d59d..635ee12 100644
--- a/tests/daemon/mgmt/command-authenticator.t.cpp
+++ b/tests/daemon/mgmt/command-authenticator.t.cpp
@@ -50,11 +50,12 @@
 
   bool
   authorize(const std::string& module, const Name& identity,
-            const std::function<void(Interest&)>& modifyInterest = nullptr)
+            const std::function<void(Interest&)>& modifyInterest = nullptr,
+            ndn::security::SignedInterestFormat format = ndn::security::SignedInterestFormat::V02)
   {
-    Interest interest = this->makeControlCommandRequest(Name("/prefix/" + module + "/verb"),
-                                                        ControlParameters(), identity);
-    if (modifyInterest != nullptr) {
+    Interest interest = makeControlCommandRequest(Name("/prefix/" + module + "/verb"),
+                                                  {}, format, identity);
+    if (modifyInterest) {
       modifyInterest(interest);
     }
 
diff --git a/tests/daemon/mgmt/manager-base.t.cpp b/tests/daemon/mgmt/manager-base.t.cpp
index ce74b1c..ea7aea5 100644
--- a/tests/daemon/mgmt/manager-base.t.cpp
+++ b/tests/daemon/mgmt/manager-base.t.cpp
@@ -125,17 +125,26 @@
                     Name("/localhost/nfd/test-module/test-notification").appendSequenceNumber(0));
 }
 
-BOOST_AUTO_TEST_CASE(ExtractRequester)
+BOOST_AUTO_TEST_CASE(ExtractSigner)
 {
-  std::string requesterName;
-  auto testAccept = [&] (const std::string& requester) { requesterName = requester; };
+  std::string signer = ManagerBase::extractSigner(Interest("/test/interest/unsigned"));
+  BOOST_CHECK_EQUAL(signer, ""); // missing SignatureInfo
 
-  m_manager.extractRequester(Interest("/test/interest/unsigned"), testAccept);
-  BOOST_CHECK_EQUAL(requesterName, "");
+  auto signedV03 = makeControlCommandRequest("/test/interest/signed", {},
+                                             ndn::security::SignedInterestFormat::V03);
+  signer = ManagerBase::extractSigner(signedV03);
+  BOOST_CHECK_EQUAL(signer,
+                    m_keyChain.getPib().getIdentity(DEFAULT_COMMAND_SIGNER_IDENTITY)
+                    .getDefaultKey().getDefaultCertificate().getName().toUri());
 
-  requesterName.clear();
-  m_manager.extractRequester(makeControlCommandRequest("/test/interest/signed"), testAccept);
-  BOOST_CHECK_EQUAL(requesterName,
+  signedV03.setSignatureInfo(ndn::SignatureInfo(tlv::SignatureSha256WithEcdsa));
+  signer = ManagerBase::extractSigner(signedV03);
+  BOOST_CHECK_EQUAL(signer, ""); // missing KeyLocator
+
+  auto signedV02 = makeControlCommandRequest("/test/interest/signed", {},
+                                             ndn::security::SignedInterestFormat::V02);
+  signer = ManagerBase::extractSigner(signedV02);
+  BOOST_CHECK_EQUAL(signer,
                     m_keyChain.getPib().getIdentity(DEFAULT_COMMAND_SIGNER_IDENTITY)
                     .getDefaultKey().getDefaultCertificate().getName().toUri());
 }
diff --git a/tests/daemon/mgmt/manager-common-fixture.cpp b/tests/daemon/mgmt/manager-common-fixture.cpp
index b427a3e..d69763d 100644
--- a/tests/daemon/mgmt/manager-common-fixture.cpp
+++ b/tests/daemon/mgmt/manager-common-fixture.cpp
@@ -33,18 +33,23 @@
 }
 
 Interest
-InterestSignerFixture::makeCommandInterest(const Name& name, const Name& identity)
-{
-  return m_signer.makeCommandInterest(name, ndn::security::signingByIdentity(identity));
-}
-
-Interest
 InterestSignerFixture::makeControlCommandRequest(Name commandName,
                                                  const ControlParameters& params,
+                                                 ndn::security::SignedInterestFormat format,
                                                  const Name& identity)
 {
   commandName.append(tlv::GenericNameComponent, params.wireEncode());
-  return this->makeCommandInterest(commandName, identity);
+
+  switch (format) {
+    case ndn::security::SignedInterestFormat::V02:
+      return m_signer.makeCommandInterest(commandName, ndn::security::signingByIdentity(identity));
+    case ndn::security::SignedInterestFormat::V03: {
+      Interest interest(commandName);
+      m_signer.makeSignedInterest(interest, ndn::security::signingByIdentity(identity));
+      return interest;
+    }
+  }
+  NDN_CXX_UNREACHABLE;
 }
 
 void
diff --git a/tests/daemon/mgmt/manager-common-fixture.hpp b/tests/daemon/mgmt/manager-common-fixture.hpp
index 2ae3b85..4741ea4 100644
--- a/tests/daemon/mgmt/manager-common-fixture.hpp
+++ b/tests/daemon/mgmt/manager-common-fixture.hpp
@@ -46,23 +46,17 @@
 protected:
   InterestSignerFixture();
 
-  /** \brief sign a command Interest
-   *  \param name command name include prefix and parameters
-   *  \param identity signing identity
-   *  \return a command Interest
-   */
-  Interest
-  makeCommandInterest(const Name& name, const Name& identity = DEFAULT_COMMAND_SIGNER_IDENTITY);
-
-  /** \brief create a ControlCommand request
-   *  \param commandName command name including prefix, such as `/localhost/nfd/fib/add-nexthop`
-   *  \param params command parameters
-   *  \param identity signing identity
-   *  \return a command Interest
+  /**
+   * \brief Create a ControlCommand request
+   * \param commandName Command name including prefix, such as `/localhost/nfd/fib/add-nexthop`
+   * \param params Command parameters
+   * \param format Signed Interest format
+   * \param identity Signing identity
    */
   Interest
   makeControlCommandRequest(Name commandName,
                             const ControlParameters& params = {},
+                            ndn::security::SignedInterestFormat format = ndn::security::SignedInterestFormat::V03,
                             const Name& identity = DEFAULT_COMMAND_SIGNER_IDENTITY);
 
 protected:
diff --git a/tests/daemon/mgmt/rib-manager.t.cpp b/tests/daemon/mgmt/rib-manager.t.cpp
index 78589a2..ecdf8b2 100644
--- a/tests/daemon/mgmt/rib-manager.t.cpp
+++ b/tests/daemon/mgmt/rib-manager.t.cpp
@@ -173,7 +173,7 @@
     advanceClocks(1_ms);
 
     auto replyFibAddCommand = [this] (const Interest& interest) {
-      ControlParameters params(interest.getName().get(-5).blockFromValue());
+      ControlParameters params(interest.getName().at(4).blockFromValue());
       BOOST_CHECK(params.getName() == "/localhost/nfd/rib" || params.getName() == "/localhop/nfd/rib");
       params.setFaceId(1)
             .setCost(0);
@@ -315,6 +315,7 @@
   auto parameters  = this->makeRegisterParameters("/test-authorization", 9527);
   auto commandHost = this->makeControlCommandRequest("/localhost/nfd/rib/register", parameters);
   auto commandHop  = this->makeControlCommandRequest("/localhop/nfd/rib/register", parameters,
+                                                     ndn::security::SignedInterestFormat::V03,
                                                      this->m_derivedId);
   if (this->m_status.isLocalhopConfigured) {
     commandHop.setTag(make_shared<lp::IncomingFaceIdTag>(123));