mgmt: don't crash if no authorizations are configured

Change-Id: I02d439a73c9b02fcb7141104d62a67aa1fa5aefb
Refs: #4487
diff --git a/daemon/mgmt/command-authenticator.cpp b/daemon/mgmt/command-authenticator.cpp
index 30ee829..6f85fc7 100644
--- a/daemon/mgmt/command-authenticator.cpp
+++ b/daemon/mgmt/command-authenticator.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -210,42 +210,46 @@
   m_validators[module]; // declares module, so that privilege is recognized
 
   auto self = this->shared_from_this();
-  return [=] (const Name& prefix, const Interest& interest,
-              const ndn::mgmt::ControlParameters* params,
+  return [=] (const Name&, const Interest& interest,
+              const ndn::mgmt::ControlParameters*,
               const ndn::mgmt::AcceptContinuation& accept,
               const ndn::mgmt::RejectContinuation& reject) {
-    shared_ptr<sec2::Validator> validator = self->m_validators.at(module);
-    validator->validate(interest,
-      [accept, validator] (const Interest& interest1) {
-        auto signer1 = getSignerFromTag(interest1);
-        BOOST_ASSERT(signer1 || // signer must be available unless 'certfile any'
-          dynamic_cast<sec2::ValidationPolicyAcceptAll*>(&validator->getPolicy()) != nullptr);
-        std::string signer = signer1.value_or("*");
-        NFD_LOG_DEBUG("accept " << interest1.getName() << " signer=" << signer);
-        accept(signer);
-      },
-      [reject] (const Interest& interest1, const sec2::ValidationError& err) {
-        NFD_LOG_DEBUG("reject " << interest1.getName() << " signer=" <<
-                      getSignerFromTag(interest1).value_or("?") << ' ' << err);
-
-        using ndn::mgmt::RejectReply;
-        RejectReply reply = RejectReply::STATUS403;
-        using ErrCode = sec2::ValidationError::Code;
-        switch (err.getCode()) {
-          case ErrCode::NO_SIGNATURE:
-          case ErrCode::INVALID_KEY_LOCATOR:
-            reply = RejectReply::SILENT;
-            break;
-          case ErrCode::POLICY_ERROR:
-            if (interest1.getName().size() < ndn::command_interest::MIN_SIZE) { // "name too short"
-              reply = RejectReply::SILENT;
-            }
-            break;
-          default:
-            break;
+    auto validator = self->m_validators.at(module);
+    auto successCb = [accept, validator] (const Interest& interest1) {
+      auto signer1 = getSignerFromTag(interest1);
+      BOOST_ASSERT(signer1 || // signer must be available unless 'certfile any'
+                   dynamic_cast<sec2::ValidationPolicyAcceptAll*>(&validator->getPolicy()) != nullptr);
+      std::string signer = signer1.value_or("*");
+      NFD_LOG_DEBUG("accept " << interest1.getName() << " signer=" << signer);
+      accept(signer);
+    };
+    auto failureCb = [reject] (const Interest& interest1, const sec2::ValidationError& err) {
+      using ndn::mgmt::RejectReply;
+      RejectReply reply = RejectReply::STATUS403;
+      switch (err.getCode()) {
+      case sec2::ValidationError::NO_SIGNATURE:
+      case sec2::ValidationError::INVALID_KEY_LOCATOR:
+        reply = RejectReply::SILENT;
+        break;
+      case sec2::ValidationError::POLICY_ERROR:
+        if (interest1.getName().size() < ndn::command_interest::MIN_SIZE) { // "name too short"
+          reply = RejectReply::SILENT;
         }
-        reject(reply);
-      });
+        break;
+      }
+      NFD_LOG_DEBUG("reject " << interest1.getName() << " signer=" <<
+                    getSignerFromTag(interest1).value_or("?") << " reason=" << err);
+      reject(reply);
+    };
+
+    if (validator) {
+      validator->validate(interest, successCb, failureCb);
+    }
+    else {
+      NFD_LOG_DEBUG("reject " << interest.getName() << " signer=" <<
+                    getSignerFromTag(interest).value_or("?") << " reason=Unauthorized");
+      reject(ndn::mgmt::RejectReply::STATUS403);
+    }
   };
 }
 
diff --git a/tests/daemon/mgmt/command-authenticator.t.cpp b/tests/daemon/mgmt/command-authenticator.t.cpp
index 469c333..ce4ab53 100644
--- a/tests/daemon/mgmt/command-authenticator.t.cpp
+++ b/tests/daemon/mgmt/command-authenticator.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -52,8 +52,7 @@
   void
   loadConfig(const std::string& config)
   {
-    boost::filesystem::path configPath = boost::filesystem::current_path() /=
-                                         "command-authenticator-test.conf";
+    auto configPath = boost::filesystem::current_path() / "command-authenticator-test.conf";
     ConfigFile cf;
     authenticator->setConfigFile(cf);
     cf.parse(config, false, configPath.c_str());
@@ -64,7 +63,7 @@
             const function<void(Interest&)>& modifyInterest = nullptr)
   {
     Interest interest = this->makeControlCommandRequest(Name("/prefix/" + module + "/verb"),
-                        ControlParameters(), identity);
+                                                        ControlParameters(), identity);
     if (modifyInterest != nullptr) {
       modifyInterest(interest);
     }
@@ -87,7 +86,7 @@
         lastRejectReply = act;
       });
 
-    this->advanceClocks(time::milliseconds(1), 10);
+    this->advanceClocks(1_ms, 10);
     BOOST_REQUIRE_MESSAGE(isAccepted || isRejected,
                           "authorization function should invoke one continuation");
     return isAccepted;
@@ -356,6 +355,18 @@
   BOOST_CHECK(lastRejectReply == ndn::mgmt::RejectReply::STATUS403);
 }
 
+BOOST_FIXTURE_TEST_CASE(MissingAuthorizationsSection, CommandAuthenticatorFixture)
+{
+  Name id0("/localhost/CommandAuthenticator/0");
+  BOOST_REQUIRE(addIdentity(id0));
+
+  makeModules({"module42"});
+  loadConfig("");
+
+  BOOST_CHECK_EQUAL(authorize("module42", id0), false);
+  BOOST_CHECK(lastRejectReply == ndn::mgmt::RejectReply::STATUS403);
+}
+
 BOOST_AUTO_TEST_SUITE_END() // Rejects
 
 BOOST_AUTO_TEST_SUITE(BadConfig)