security: fix CommandInterestValidator bug (no check on signature type)

refs: #1423

Change-Id: Ida49fde746c5766373ea6fb174f82598e16915d1
diff --git a/src/util/command-interest-validator.hpp b/src/util/command-interest-validator.hpp
index ca65f27..07e164f 100644
--- a/src/util/command-interest-validator.hpp
+++ b/src/util/command-interest-validator.hpp
@@ -22,6 +22,8 @@
     POS_RANDOM_VAL = -3,
     POS_TIMESTAMP = -4,
 
+    MIN_LENGTH = 4,
+
     GRACE_INTERVAL = 3000 // ms
   };
 
@@ -98,74 +100,102 @@
   const Name& interestName = interest.getName();
 
   //Prepare
-  if (interestName.size() < 4)
+  if (interestName.size() < MIN_LENGTH)
     return onValidationFailed(interest.shared_from_this(),
                               "Interest is not signed: " + interest.getName().toUri());
-
-  Signature signature(interestName[POS_SIG_INFO].blockFromValue(),
-                      interestName[POS_SIG_VALUE].blockFromValue());
-
-  SignatureSha256WithRsa sig(signature);
-  const Name& keyLocatorName = sig.getKeyLocator().getName();
-  Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
-
-  //Check if command is in the trusted scope
-  bool isInScope = false;
-  for (std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
-      scopeIt != m_trustScopeForInterest.end();
-      ++scopeIt)
+  Name keyName;
+  try
     {
-      if (scopeIt->satisfy(interestName, keyName))
-        {
-          isInScope = true;
-          break;
-        }
-    }
+      Signature signature(interestName[POS_SIG_INFO].blockFromValue(),
+                          interestName[POS_SIG_VALUE].blockFromValue());
 
-  if (isInScope == false)
-    return onValidationFailed(interest.shared_from_this(),
-                              "Signer cannot be authorized for the command: " + keyName.toUri());
-
-  //Check if timestamp is valid
-  time::system_clock::TimePoint interestTime =
-    time::fromUnixTimestamp(time::milliseconds(interestName.get(POS_TIMESTAMP).toNumber()));
-
-  time::system_clock::TimePoint currentTime = time::system_clock::now();
-
-  LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
-  if (timestampIt == m_lastTimestamp.end())
-    {
-      if (!(currentTime - m_graceInterval <= interestTime &&
-            interestTime <= currentTime + m_graceInterval))
-        {
-          return onValidationFailed(interest.shared_from_this(),
-                                    "The command is not in grace interval: " +
-                                    interest.getName().toUri());
-        }
-    }
-  else
-    {
-      if(interestTime <= timestampIt->second)
+      if (signature.getType() != Signature::Sha256WithRsa)
         return onValidationFailed(interest.shared_from_this(),
-                                  "The command is outdated: " + interest.getName().toUri());
-    }
+                                  "Require SignatureSha256WithRsa");
 
-  //Check signature
-  if (!Validator::verifySignature(interestName.wireEncode().value(),
-                                  interestName.wireEncode().value_size() -
-                                  interestName[-1].size(),
-                                  sig, m_trustAnchorsForInterest[keyName]))
-    return onValidationFailed(interest.shared_from_this(),
-                              "Signature cannot be validated: " + interest.getName().toUri());
+      SignatureSha256WithRsa sig(signature);
 
-  //Update timestamp
-  if (timestampIt == m_lastTimestamp.end())
-    {
-      m_lastTimestamp[keyName] = interestTime;
+      const KeyLocator& keyLocator = sig.getKeyLocator();
+
+      if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
+        return onValidationFailed(interest.shared_from_this(),
+                                  "Key Locator is not a name");
+
+      keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocator.getName());
+
+      //Check if command is in the trusted scope
+      bool isInScope = false;
+      for (std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
+           scopeIt != m_trustScopeForInterest.end();
+           ++scopeIt)
+        {
+          if (scopeIt->satisfy(interestName, keyName))
+            {
+              isInScope = true;
+              break;
+            }
+        }
+      if (isInScope == false)
+        return onValidationFailed(interest.shared_from_this(),
+                                  "Signer cannot be authorized for the command: " +
+                                  keyName.toUri());
+
+      //Check signature
+      if (!Validator::verifySignature(interestName.wireEncode().value(),
+                                      interestName.wireEncode().value_size() -
+                                      interestName[-1].size(),
+                                      sig, m_trustAnchorsForInterest[keyName]))
+        return onValidationFailed(interest.shared_from_this(),
+                                  "Signature cannot be validated: " +
+                                  interest.getName().toUri());
+
+      //Check if timestamp is valid
+      time::system_clock::TimePoint interestTime =
+        time::fromUnixTimestamp(time::milliseconds(interestName.get(POS_TIMESTAMP).toNumber()));
+
+      time::system_clock::TimePoint currentTime = time::system_clock::now();
+
+      LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
+      if (timestampIt == m_lastTimestamp.end())
+        {
+          if (!(currentTime - m_graceInterval <= interestTime &&
+                interestTime <= currentTime + m_graceInterval))
+            return onValidationFailed(interest.shared_from_this(),
+                                      "The command is not in grace interval: " +
+                                      interest.getName().toUri());
+        }
+      else
+        {
+          if (interestTime <= timestampIt->second)
+            return onValidationFailed(interest.shared_from_this(),
+                                      "The command is outdated: " +
+                                      interest.getName().toUri());
+        }
+
+      //Update timestamp
+      if (timestampIt == m_lastTimestamp.end())
+        {
+          m_lastTimestamp[keyName] = interestTime;
+        }
+      else
+        {
+          timestampIt->second = interestTime;
+        }
     }
-  else
+  catch (const Tlv::Error& e)
     {
-      timestampIt->second = interestTime;
+      return onValidationFailed(interest.shared_from_this(),
+                                "Cannot decode signature related TLVs");
+    }
+  catch (const Signature::Error& e)
+    {
+      return onValidationFailed(interest.shared_from_this(),
+                                "No valid signature");
+    }
+  catch (const IdentityCertificate::Error& e)
+    {
+      return onValidationFailed(interest.shared_from_this(),
+                                "Cannot locate the signing key");
     }
 
   return onValidated(interest.shared_from_this());