rib: Separate trust models for `/localhost` and `/localhop` RIB management commands

Change-Id: I10fd9a1c8a2e0e572ea28f6e97d57b0b5b9750c8
Refs: #1557
Refs: #1558
diff --git a/daemon/main.cpp b/daemon/main.cpp
index a13dfe1..d647936 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -84,7 +84,7 @@
       // Ignore "log" and sections beginning with "rib_" (intended for rib manager),
       // but raise an error if we're missing a handler for an NFD section.
 
-      if (sectionName.find("rib_") == 0 || sectionName == "log")
+      if (sectionName.find("rib") == 0 || sectionName == "log")
         {
           // do nothing
         }
diff --git a/nfd.conf.sample.in b/nfd.conf.sample.in
index 8c48743..74d4333 100644
--- a/nfd.conf.sample.in
+++ b/nfd.conf.sample.in
@@ -162,76 +162,90 @@
   ; }
 }
 
-rib_security
+rib
 {
-  ; This section defines the trust model for NFD RIB Management. It consists of rules and
-  ; trust-anchors, which are briefly defined in this file.  For more information refer to
-  ; manpage of ndn-validator.conf:
-  ;
-  ;     man ndn-validator.conf
-  ;
-  ; A trust-anchor is a pre-trusted certificate.  This can be any certificate that is the
-  ; root of certification chain (e.g., NDN testbed root certificate) or an existing
-  ; default system certificate `default.ndncert`.
-  ;
-  ; A rule defines conditions a valid packet MUST have. A packet must satisfy one of the
-  ; rules defined here. A rule can be broken into two parts: matching & checking. A packet
-  ; will be matched against rules from the first to the last until a matched rule is
-  ; encountered. The matched rule will be used to check the packet. If a packet does not
-  ; match any rule, it will be treated as invalid.  The matching part of a rule consists
-  ; of `for` and `filter` sections. They collectively define which packets can be checked
-  ; with this rule. `for` defines packet type (data or interest) and `filter` defines
-  ; conditions on other properties of a packet. Right now, you can only define conditions
-  ; on packet name, and you can only specify ONLY ONE filter for packet name.  The
-  ; checking part of a rule consists of `checker`, which defines the conditions that a
-  ; VALID packet MUST have. See comments in checker section for more details.
+  ; The following localhost_security allows anyone to register routing entries in local RIB
+  localhost_security
+  {
+    trust-anchor
+    {
+      type any
+    }
+  }
 
-  rule
-  {
-    id "NRD Prefix Registration Command Rule"
-    for interest                              ; rule for Interests (to validate CommandInterests)
-    filter
-    {
-      type name                               ; condition on interest name (w/o signature)
-      regex ^[<localhop><localhost>]<nfd><rib>[<register><unregister>]<>{3}$
-    }
-    checker
-    {
-      type customized
-      sig-type rsa-sha256                     ; interest must have a rsa-sha256 signature
-      key-locator
-      {
-        type name                             ; key locator must be the certificate name of
-                                              ; the signing key
-        regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$
-      }
-    }
-  }
-  rule
-  {
-    id "NDN Testbed Hierarchy Rule"
-    for data                                  ; rule for Data (to validate NDN certificates)
-    filter
-    {
-      type name                               ; condition on data name
-      regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$
-    }
-    checker
-    {
-      type hierarchical                       ; the certificate name of the signing key and
-                                              ; the data name must follow the hierarchical model
-      sig-type rsa-sha256                     ; data must have a rsa-sha256 signature
-    }
-  }
-  trust-anchor
-  {
-    type file
-    file-name keys/default.ndncert ; the file name, by default this file should be placed in the
-                                  ; same folder as this config file.
-  }
-  ; trust-anchor ; Can be repeated multiple times to specify multiple trust anchors
+  ; localhop_security should be enabled when NFD runs on a hub.
+  ; "/localhop/nfd/fib" command prefix will be disabled when localhop_security section is missing.
+  ; localhop_security
   ; {
-  ;   type file
-  ;   file-name keys/ndn-testbed.ndncert
+  ;   ; This section defines the trust model for NFD RIB Management. It consists of rules and
+  ;   ; trust-anchors, which are briefly defined in this file.  For more information refer to
+  ;   ; manpage of ndn-validator.conf:
+  ;   ;
+  ;   ;     man ndn-validator.conf
+  ;   ;
+  ;   ; A trust-anchor is a pre-trusted certificate.  This can be any certificate that is the
+  ;   ; root of certification chain (e.g., NDN testbed root certificate) or an existing
+  ;   ; default system certificate `default.ndncert`.
+  ;   ;
+  ;   ; A rule defines conditions a valid packet MUST have. A packet must satisfy one of the
+  ;   ; rules defined here. A rule can be broken into two parts: matching & checking. A packet
+  ;   ; will be matched against rules from the first to the last until a matched rule is
+  ;   ; encountered. The matched rule will be used to check the packet. If a packet does not
+  ;   ; match any rule, it will be treated as invalid.  The matching part of a rule consists
+  ;   ; of `for` and `filter` sections. They collectively define which packets can be checked
+  ;   ; with this rule. `for` defines packet type (data or interest) and `filter` defines
+  ;   ; conditions on other properties of a packet. Right now, you can only define conditions
+  ;   ; on packet name, and you can only specify ONLY ONE filter for packet name.  The
+  ;   ; checking part of a rule consists of `checker`, which defines the conditions that a
+  ;   ; VALID packet MUST have. See comments in checker section for more details.
+  ;
+  ;   rule
+  ;   {
+  ;     id "NRD Prefix Registration Command Rule"
+  ;     for interest                         ; rule for Interests (to validate CommandInterests)
+  ;     filter
+  ;     {
+  ;       type name                          ; condition on interest name (w/o signature)
+  ;       regex ^[<localhop><localhost>]<nfd><rib>[<register><unregister>]<>{3}$
+  ;     }
+  ;     checker
+  ;     {
+  ;       type customized
+  ;       sig-type rsa-sha256                ; interest must have a rsa-sha256 signature
+  ;       key-locator
+  ;       {
+  ;         type name                        ; key locator must be the certificate name of the
+  ;                                          ; signing key
+  ;         regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$
+  ;       }
+  ;     }
+  ;   }
+  ;   rule
+  ;   {
+  ;     id "NDN Testbed Hierarchy Rule"
+  ;     for data                             ; rule for Data (to validate NDN certificates)
+  ;     filter
+  ;     {
+  ;       type name                          ; condition on data name
+  ;       regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$
+  ;     }
+  ;     checker
+  ;     {
+  ;       type hierarchical                  ; the certificate name of the signing key and
+  ;                                          ; the data name must follow the hierarchical model
+  ;       sig-type rsa-sha256                ; data must have a rsa-sha256 signature
+  ;     }
+  ;   }
+  ;   trust-anchor
+  ;   {
+  ;     type file
+  ;     file-name keys/default.ndncert ; the file name, by default this file should be placed in the
+  ;                                    ; same folder as this config file.
+  ;   }
+  ;   ; trust-anchor ; Can be repeated multiple times to specify multiple trust anchors
+  ;   ; {
+  ;   ;   type file
+  ;   ;   file-name keys/ndn-testbed.ndncert
+  ;   ; }
   ; }
 }
diff --git a/rib/rib-manager.cpp b/rib/rib-manager.cpp
index 916ed93..3db042d 100644
--- a/rib/rib-manager.cpp
+++ b/rib/rib-manager.cpp
@@ -66,8 +66,10 @@
 RibManager::RibManager()
   : m_face(shared_ptr<boost::asio::io_service>(&getGlobalIoService(), &NullDeleter))
   , m_nfdController(new ndn::nfd::Controller(m_face))
-  , m_validator(m_face)
+  , m_localhostValidator(m_face)
+  , m_localhopValidator(m_face)
   , m_faceMonitor(m_face)
+  , m_isLocalhopEnabled(false)
   , m_verbDispatch(COMMAND_VERBS,
                    COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
 {
@@ -82,13 +84,16 @@
   NFD_LOG_INFO("Setting interest filter on: " << COMMAND_PREFIX);
   m_face.setController(m_nfdController);
   m_face.setInterestFilter(COMMAND_PREFIX,
-                           bind(&RibManager::onRibRequest, this, _2),
+                           bind(&RibManager::onLocalhostRequest, this, _2),
                            bind(&RibManager::setInterestFilterFailed, this, _1, _2));
 
-  NFD_LOG_INFO("Setting interest filter on: " << REMOTE_COMMAND_PREFIX);
-  m_face.setInterestFilter(REMOTE_COMMAND_PREFIX,
-                           bind(&RibManager::onRibRequest, this, _2),
-                           bind(&RibManager::setInterestFilterFailed, this, _1, _2));
+  if (m_isLocalhopEnabled)
+    {
+      NFD_LOG_INFO("Setting interest filter on: " << REMOTE_COMMAND_PREFIX);
+      m_face.setInterestFilter(REMOTE_COMMAND_PREFIX,
+                               bind(&RibManager::onLocalhopRequest, this, _2),
+                               bind(&RibManager::setInterestFilterFailed, this, _1, _2));
+    }
 
   NFD_LOG_INFO("Start monitoring face create/destroy events");
   m_faceMonitor.addSubscriber(boost::bind(&RibManager::onNotification, this, _1));
@@ -98,7 +103,7 @@
 void
 RibManager::setConfigFile(ConfigFile& configFile)
 {
-  configFile.addSectionHandler("rib_security",
+  configFile.addSectionHandler("rib",
                                bind(&RibManager::onConfig, this, _1, _2, _3));
 }
 
@@ -107,9 +112,19 @@
                      bool isDryRun,
                      const std::string& filename)
 {
-  /// \todo remove check after validator-conf replaces settings on each load
-  if (!isDryRun)
-    m_validator.load(configSection, filename);
+  for (ConfigSection::const_iterator i = configSection.begin();
+       i != configSection.end(); ++i)
+    {
+      if (i->first == "localhost_security")
+          m_localhostValidator.load(i->second, filename);
+      else if (i->first == "localhop_security")
+        {
+          m_localhopValidator.load(i->second, filename);
+          m_isLocalhopEnabled = true;
+        }
+      else
+        throw Error("Unrecognized rib property: " + i->first);
+    }
 }
 
 void
@@ -142,11 +157,19 @@
 }
 
 void
-RibManager::onRibRequest(const Interest& request)
+RibManager::onLocalhostRequest(const Interest& request)
 {
-  m_validator.validate(request,
-                       bind(&RibManager::onCommandValidated, this, _1),
-                       bind(&RibManager::onCommandValidationFailed, this, _1, _2));
+  m_localhostValidator.validate(request,
+                                bind(&RibManager::onCommandValidated, this, _1),
+                                bind(&RibManager::onCommandValidationFailed, this, _1, _2));
+}
+
+void
+RibManager::onLocalhopRequest(const Interest& request)
+{
+  m_localhopValidator.validate(request,
+                               bind(&RibManager::onCommandValidated, this, _1),
+                               bind(&RibManager::onCommandValidationFailed, this, _1, _2));
 }
 
 void
diff --git a/rib/rib-manager.hpp b/rib/rib-manager.hpp
index 4c2c344..1d542fb 100644
--- a/rib/rib-manager.hpp
+++ b/rib/rib-manager.hpp
@@ -46,10 +46,17 @@
 class RibManager : noncopyable
 {
 public:
-  RibManager();
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
 
-  void
-  onRibRequest(const Interest& request);
+  RibManager();
 
   void
   registerWithNfd();
@@ -67,6 +74,12 @@
            const std::string& filename);
 
   void
+  onLocalhopRequest(const Interest& request);
+
+  void
+  onLocalhostRequest(const Interest& request);
+
+  void
   sendResponse(const Name& name,
                const ControlResponse& response);
 
@@ -131,8 +144,10 @@
   ndn::Face m_face;
   ndn::shared_ptr<ndn::nfd::Controller> m_nfdController;
   ndn::KeyChain m_keyChain;
-  ndn::ValidatorConfig m_validator;
+  ndn::ValidatorConfig m_localhostValidator;
+  ndn::ValidatorConfig m_localhopValidator;
   FaceMonitor m_faceMonitor;
+  bool m_isLocalhopEnabled;
 
   typedef boost::function<void(RibManager*,
                                const shared_ptr<const Interest>& request,