NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
certificate-bundle-fetcher.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2018 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  */
21 
23 #include "face.hpp"
24 #include "util/logger.hpp"
25 
26 namespace ndn {
27 namespace security {
28 namespace v2 {
29 
31 
32 #define NDN_LOG_DEBUG_DEPTH(x) NDN_LOG_DEBUG(std::string(state->getDepth() + 1, '>') << " " << x)
33 #define NDN_LOG_TRACE_DEPTH(x) NDN_LOG_TRACE(std::string(state->getDepth() + 1, '>') << " " << x)
34 
35 CertificateBundleFetcher::CertificateBundleFetcher(unique_ptr<CertificateFetcher> inner,
36  Face& face)
37  : m_inner(std::move(inner))
38  , m_face(face)
39  , m_bundleInterestLifetime(1000)
40 {
41  BOOST_ASSERT(m_inner != nullptr);
42 }
43 
44 void
46 {
47  m_bundleInterestLifetime = time;
48 }
49 
50 time::milliseconds
52 {
53  return m_bundleInterestLifetime;
54 }
55 
56 void
58 {
59  m_certStorage = &certStorage;
60  m_inner->setCertificateStorage(certStorage);
61 }
62 
63 void
64 CertificateBundleFetcher::doFetch(const shared_ptr<CertificateRequest>& certRequest,
65  const shared_ptr<ValidationState>& state,
66  const ValidationContinuation& continueValidation)
67 {
68  auto dataValidationState = dynamic_pointer_cast<DataValidationState>(state);
69  if (dataValidationState == nullptr) {
70  return m_inner->fetch(certRequest, state, continueValidation);
71  }
72 
73  // check if a bundle segment was fetched before
74  shared_ptr<BundleNameTag> bundleNameTag = state->getTag<BundleNameTag>();
75  if (bundleNameTag == nullptr) {
76  const Name& originalDataName = dataValidationState->getOriginalData().getName();
77  if (originalDataName.empty()) {
78  return m_inner->fetch(certRequest, state, continueValidation);
79  }
80  // derive certificate bundle name from original data name
81  Name bundleNamePrefix = deriveBundleName(originalDataName);
82  fetchFirstBundleSegment(bundleNamePrefix, certRequest, state, continueValidation);
83  }
84  else {
85  Name fullBundleName = bundleNameTag->get();
86  fetchNextBundleSegment(fullBundleName, fullBundleName.get(-1).getSuccessor(),
87  certRequest, state, continueValidation);
88  }
89 }
90 
91 void
92 CertificateBundleFetcher::fetchFirstBundleSegment(const Name& bundleNamePrefix,
93  const shared_ptr<CertificateRequest>& certRequest,
94  const shared_ptr<ValidationState>& state,
95  const ValidationContinuation& continueValidation)
96 {
97  Interest bundleInterest = Interest(bundleNamePrefix);
98  bundleInterest.setInterestLifetime(m_bundleInterestLifetime);
99  bundleInterest.setMustBeFresh(true);
100  bundleInterest.setChildSelector(1);
101 
102  m_face.expressInterest(bundleInterest,
103  [=] (const Interest& interest, const Data& data) {
104  dataCallback(data, true, certRequest, state, continueValidation);
105  },
106  [=] (const Interest& interest, const lp::Nack& nack) {
107  nackCallback(nack, certRequest, state, continueValidation, bundleNamePrefix);
108  },
109  [=] (const Interest& interest) {
110  timeoutCallback(certRequest, state, continueValidation, bundleNamePrefix);
111  });
112 }
113 
114 void
115 CertificateBundleFetcher::fetchNextBundleSegment(const Name& fullBundleName, const name::Component& segmentNo,
116  const shared_ptr<CertificateRequest>& certRequest,
117  const shared_ptr<ValidationState>& state,
118  const ValidationContinuation& continueValidation)
119 {
120  shared_ptr<FinalBlockIdTag> finalBlockId = state->getTag<FinalBlockIdTag>();
121  if (finalBlockId != nullptr && segmentNo > finalBlockId->get()) {
122  return m_inner->fetch(certRequest, state, continueValidation);
123  }
124 
125  Interest bundleInterest(fullBundleName.getPrefix(-1).append(segmentNo));
126  bundleInterest.setInterestLifetime(m_bundleInterestLifetime);
127  bundleInterest.setMustBeFresh(false);
128 
129  m_face.expressInterest(bundleInterest,
130  [=] (const Interest& interest, const Data& data) {
131  dataCallback(data, false, certRequest, state, continueValidation);
132  },
133  [=] (const Interest& interest, const lp::Nack& nack) {
134  nackCallback(nack, certRequest, state, continueValidation, fullBundleName);
135  },
136  [=] (const Interest& interest) {
137  timeoutCallback(certRequest, state, continueValidation, fullBundleName);
138  });
139 }
140 
141 void
142 CertificateBundleFetcher::dataCallback(const Data& bundleData,
143  bool isSegmentZeroExpected,
144  const shared_ptr<CertificateRequest>& certRequest,
145  const shared_ptr<ValidationState>& state,
146  const ValidationContinuation& continueValidation)
147 {
148  NDN_LOG_DEBUG_DEPTH("Fetched certificate bundle from network " << bundleData.getName());
149 
150  name::Component currentSegment = bundleData.getName().get(-1);
151  if (!currentSegment.isSegment()) {
152  return m_inner->fetch(certRequest, state, continueValidation);
153  }
154 
155  if (isSegmentZeroExpected && currentSegment.toSegment() != 0) {
156  // fetch segment zero
157  fetchNextBundleSegment(bundleData.getName(), name::Component::fromSegment(0),
158  certRequest, state, continueValidation);
159  }
160  else {
161  state->setTag(make_shared<BundleNameTag>(bundleData.getName()));
162 
163  const auto& finalBlockId = bundleData.getFinalBlock();
164  if (!finalBlockId) {
165  state->setTag(make_shared<FinalBlockIdTag>(*finalBlockId));
166  }
167 
168  Block bundleContent = bundleData.getContent();
169  bundleContent.parse();
170 
171  // store all the certificates in unverified cache
172  for (const auto& block : bundleContent.elements()) {
173  m_certStorage->cacheUnverifiedCert(Certificate(block));
174  }
175 
176  auto cert = m_certStorage->getUnverifiedCertCache().find(certRequest->m_interest);
177  continueValidation(*cert, state);
178  }
179 }
180 
181 void
182 CertificateBundleFetcher::nackCallback(const lp::Nack& nack,
183  const shared_ptr<CertificateRequest>& certRequest,
184  const shared_ptr<ValidationState>& state,
185  const ValidationContinuation& continueValidation,
186  const Name& bundleName)
187 {
188  NDN_LOG_DEBUG_DEPTH("NACK (" << nack.getReason() << ") while fetching certificate bundle"
189  << bundleName);
190 
191  m_inner->fetch(certRequest, state, continueValidation);
192 }
193 
194 void
195 CertificateBundleFetcher::timeoutCallback(const shared_ptr<CertificateRequest>& certRequest,
196  const shared_ptr<ValidationState>& state,
197  const ValidationContinuation& continueValidation,
198  const Name& bundleName)
199 {
200  NDN_LOG_DEBUG_DEPTH("Timeout while fetching certificate bundle" << bundleName);
201 
202  m_inner->fetch(certRequest, state, continueValidation);
203 }
204 
205 Name
206 CertificateBundleFetcher::deriveBundleName(const Name& name)
207 {
208  name::Component lastComponent = name.at(-1);
209 
210  Name bundleName = name;
211  if (lastComponent.isImplicitSha256Digest()) {
212  if (name.size() >= 2 && name.get(-2).isSegment()) {
213  bundleName = name.getPrefix(-2);
214  }
215  else {
216  bundleName = name.getPrefix(-1);
217  }
218  }
219  else if (lastComponent.isSegment()) {
220  bundleName = name.getPrefix(-1);
221  }
222  bundleName.append("_BUNDLE");
223  bundleName.appendNumber(00);
224 
225  return bundleName;
226 }
227 
228 } // namespace v2
229 } // namespace security
230 } // namespace ndn
Copyright (c) 2011-2015 Regents of the University of California.
#define NDN_LOG_DEBUG_DEPTH(x)
Interest & setMustBeFresh(bool mustBeFresh)
Add or remove MustBeFresh element.
Definition: interest.hpp:197
const Certificate * find(const Name &certPrefix) const
Get certificate given key name.
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:164
void setBundleInterestLifetime(time::milliseconds time)
Set the lifetime of certificate bundle interest.
NDN_CXX_DEPRECATED Interest & setChildSelector(int childSelector)
Definition: interest.hpp:371
STL namespace.
void cacheUnverifiedCert(Certificate &&cert)
Cache unverified certificate for a period of time (5 minutes)
Represents an Interest packet.
Definition: interest.hpp:42
std::function< void(const Certificate &cert, const shared_ptr< ValidationState > &state)> ValidationContinuation
CertificateBundleFetcher(unique_ptr< CertificateFetcher > inner, Face &face)
represents a Network Nack
Definition: nack.hpp:40
Validation state for a data packet.
NackReason getReason() const
Definition: nack.hpp:92
provides a tag type for simple types
Definition: tag.hpp:58
static Component fromSegment(uint64_t segmentNo)
Create segment number component using NDN naming conventions.
Component getSuccessor() const
#define NDN_LOG_INIT(name)
declare a log module
Definition: logger.hpp:32
const CertificateCache & getUnverifiedCertCache() const
const Block & get(uint32_t type) const
Get the first sub element of specified TLV-TYPE.
Definition: block.cpp:425
Storage for trusted anchors, verified certificate cache, and unverified certificate cache...
bool isSegment() const
Check if the component is segment number per NDN naming conventions.
Provide a communication channel with local or remote NDN forwarder.
Definition: face.hpp:90
void doFetch(const shared_ptr< CertificateRequest > &certRequest, const shared_ptr< ValidationState > &state, const ValidationContinuation &continueValidation) override
Asynchronous certificate fetching implementation.
bool isImplicitSha256Digest() const
Check if the component is ImplicitSha256DigestComponent.
Represents an absolute name.
Definition: name.hpp:42
Fetch certificate bundle from the network.
Represents a name component.
bool empty() const
Check if name is empty.
Definition: name.hpp:146
Interest & setInterestLifetime(time::milliseconds lifetime)
Set Interest&#39;s lifetime.
Definition: interest.cpp:476
const PendingInterestId * expressInterest(const Interest &interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Express Interest.
Definition: face.cpp:132
Represents a Data packet.
Definition: data.hpp:35
void setCertificateStorage(CertificateStorage &certStorage) override
Set the storage for this and inner certificate fetcher.