security: enable direct fetch for data sig validation

Change-Id: Icae66769cf980a20bc637caca46f381b29361047
diff --git a/src/security/v2/certificate-fetcher-direct-fetch.cpp b/src/security/v2/certificate-fetcher-direct-fetch.cpp
index 2e01612..0f240a2 100644
--- a/src/security/v2/certificate-fetcher-direct-fetch.cpp
+++ b/src/security/v2/certificate-fetcher-direct-fetch.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -38,20 +38,26 @@
                                        const ValidationContinuation& continueValidation)
 {
   auto interestState = dynamic_pointer_cast<InterestValidationState>(state);
+  uint64_t incomingFaceId = 0;
   if (interestState != nullptr) {
-    uint64_t incomingFaceId = 0;
     auto incomingFaceIdTag = interestState->getOriginalInterest().getTag<lp::IncomingFaceIdTag>();
     if (incomingFaceIdTag != nullptr) {
       incomingFaceId = incomingFaceIdTag->get();
     }
-
-    if (incomingFaceId != 0) {
-      Interest directInterest(keyRequest->m_interest);
-      directInterest.refreshNonce();
-      directInterest.setTag(make_shared<lp::NextHopFaceIdTag>(incomingFaceId));
-      m_face.expressInterest(directInterest, nullptr, nullptr, nullptr);
+  }
+  else {
+    auto dataState = dynamic_pointer_cast<DataValidationState>(state);
+    auto incomingFaceIdTag = dataState->getOriginalData().getTag<lp::IncomingFaceIdTag>();
+    if (incomingFaceIdTag != nullptr) {
+      incomingFaceId = incomingFaceIdTag->get();
     }
   }
+  if (incomingFaceId != 0) {
+    Interest directInterest(keyRequest->m_interest);
+    directInterest.refreshNonce();
+    directInterest.setTag(make_shared<lp::NextHopFaceIdTag>(incomingFaceId));
+    m_face.expressInterest(directInterest, nullptr, nullptr, nullptr);
+  }
 
   // send infrastructure Interest
   CertificateFetcherFromNetwork::doFetch(keyRequest, state, continueValidation);
diff --git a/src/security/v2/certificate-fetcher-direct-fetch.hpp b/src/security/v2/certificate-fetcher-direct-fetch.hpp
index 2f51246..5eba1f0 100644
--- a/src/security/v2/certificate-fetcher-direct-fetch.hpp
+++ b/src/security/v2/certificate-fetcher-direct-fetch.hpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -29,14 +29,13 @@
 namespace v2 {
 
 /**
- * @brief Extends CertificateFetcherFromNetwork to fetch certificates from Interest sender
+ * @brief Extends CertificateFetcherFromNetwork to fetch certificates from the incoming face of
+ *   the packet
  *
- * During Interest validation, if IncomingFaceId tag is present on the original Interest, this
- * fetcher will send a "direct Interest" to fetch certificates from the face where the original
- * Interest was received, in addition to fetching from the infrastructure. The application must
+ * During Interest and Data validation, if IncomingFaceId tag is present on the original Interest,
+ * this fetcher will send a "direct Interest" to fetch certificates from the face where the original
+ * packet was received, in addition to fetching from the infrastructure. The application must
  * enable NextHopFaceId privilege on the face used by this fetcher prior to the validation.
- *
- * During Data validation, this fetcher is equivalent to CertificateFetcherFromNetwork.
  */
 class CertificateFetcherDirectFetch : public CertificateFetcherFromNetwork
 {
diff --git a/tests/unit-tests/security/v2/certificate-fetcher-direct-fetch.t.cpp b/tests/unit-tests/security/v2/certificate-fetcher-direct-fetch.t.cpp
index d62edf2..2f27878 100644
--- a/tests/unit-tests/security/v2/certificate-fetcher-direct-fetch.t.cpp
+++ b/tests/unit-tests/security/v2/certificate-fetcher-direct-fetch.t.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -121,20 +121,36 @@
 
 BOOST_FIXTURE_TEST_CASE(ValidateSuccessData, CertificateFetcherDirectFetchFixture<Cert>)
 {
-  VALIDATE_SUCCESS(this->data, "Should get accepted, as interests bring cert");
-  BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 2);
+  VALIDATE_SUCCESS(this->data, "Should get accepted, normal and/or direct interests bring certs");
+  BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4);
 
-  for (const auto& sentInterest : this->face.sentInterests) {
+  // odd interests
+  for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
+    BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
+  }
+
+  // even interests
+  for (const auto& sentInterest : this->face.sentInterests |
+                                    boost::adaptors::sliced(1, this->face.sentInterests.size()) |
+                                    boost::adaptors::strided(2)) {
     BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
   }
 }
 
 BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateFailureData, T, Failures, CertificateFetcherDirectFetchFixture<T>)
 {
-  VALIDATE_FAILURE(this->data, "Should fail, as non-direct interests don't bring data");
-  BOOST_CHECK_GT(this->face.sentInterests.size(), 2);
+  VALIDATE_FAILURE(this->data, "Should fail, as all interests either NACKed or timeout");
+  BOOST_CHECK_GT(this->face.sentInterests.size(), 4);
 
-  for (const auto& sentInterest : this->face.sentInterests) {
+  // odd interests
+  for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
+    BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
+  }
+
+  // even interests
+  for (const auto& sentInterest : this->face.sentInterests |
+                                    boost::adaptors::sliced(1, this->face.sentInterests.size()) |
+                                    boost::adaptors::strided(2)) {
     BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
   }
 }