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-2019 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 "ndn-cxx/face.hpp"
24 #include "ndn-cxx/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.setCanBePrefix(true);
99  bundleInterest.setMustBeFresh(true);
100  bundleInterest.setInterestLifetime(m_bundleInterestLifetime);
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.setCanBePrefix(false);
127  bundleInterest.setMustBeFresh(false);
128  bundleInterest.setInterestLifetime(m_bundleInterestLifetime);
129 
130  m_face.expressInterest(bundleInterest,
131  [=] (const Interest& interest, const Data& data) {
132  dataCallback(data, false, certRequest, state, continueValidation);
133  },
134  [=] (const Interest& interest, const lp::Nack& nack) {
135  nackCallback(nack, certRequest, state, continueValidation, fullBundleName);
136  },
137  [=] (const Interest& interest) {
138  timeoutCallback(certRequest, state, continueValidation, fullBundleName);
139  });
140 }
141 
142 void
143 CertificateBundleFetcher::dataCallback(const Data& bundleData,
144  bool isSegmentZeroExpected,
145  const shared_ptr<CertificateRequest>& certRequest,
146  const shared_ptr<ValidationState>& state,
147  const ValidationContinuation& continueValidation)
148 {
149  NDN_LOG_DEBUG_DEPTH("Fetched certificate bundle from network " << bundleData.getName());
150 
151  name::Component currentSegment = bundleData.getName().get(-1);
152  if (!currentSegment.isSegment()) {
153  return m_inner->fetch(certRequest, state, continueValidation);
154  }
155 
156  if (isSegmentZeroExpected && currentSegment.toSegment() != 0) {
157  // fetch segment zero
158  fetchNextBundleSegment(bundleData.getName(), name::Component::fromSegment(0),
159  certRequest, state, continueValidation);
160  }
161  else {
162  state->setTag(make_shared<BundleNameTag>(bundleData.getName()));
163 
164  const auto& finalBlockId = bundleData.getFinalBlock();
165  if (!finalBlockId) {
166  state->setTag(make_shared<FinalBlockIdTag>(*finalBlockId));
167  }
168 
169  Block bundleContent = bundleData.getContent();
170  bundleContent.parse();
171 
172  // store all the certificates in unverified cache
173  for (const auto& block : bundleContent.elements()) {
174  m_certStorage->cacheUnverifiedCert(Certificate(block));
175  }
176 
177  auto cert = m_certStorage->getUnverifiedCertCache().find(certRequest->interest);
178  continueValidation(*cert, state);
179  }
180 }
181 
182 void
183 CertificateBundleFetcher::nackCallback(const lp::Nack& nack,
184  const shared_ptr<CertificateRequest>& certRequest,
185  const shared_ptr<ValidationState>& state,
186  const ValidationContinuation& continueValidation,
187  const Name& bundleName)
188 {
189  NDN_LOG_DEBUG_DEPTH("NACK (" << nack.getReason() << ") while fetching certificate bundle"
190  << bundleName);
191 
192  m_inner->fetch(certRequest, state, continueValidation);
193 }
194 
195 void
196 CertificateBundleFetcher::timeoutCallback(const shared_ptr<CertificateRequest>& certRequest,
197  const shared_ptr<ValidationState>& state,
198  const ValidationContinuation& continueValidation,
199  const Name& bundleName)
200 {
201  NDN_LOG_DEBUG_DEPTH("Timeout while fetching certificate bundle" << bundleName);
202 
203  m_inner->fetch(certRequest, state, continueValidation);
204 }
205 
206 Name
207 CertificateBundleFetcher::deriveBundleName(const Name& name)
208 {
209  name::Component lastComponent = name.at(-1);
210 
211  Name bundleName = name;
212  if (lastComponent.isImplicitSha256Digest()) {
213  if (name.size() >= 2 && name.get(-2).isSegment()) {
214  bundleName = name.getPrefix(-2);
215  }
216  else {
217  bundleName = name.getPrefix(-1);
218  }
219  }
220  else if (lastComponent.isSegment()) {
221  bundleName = name.getPrefix(-1);
222  }
223  bundleName.append("_BUNDLE");
224  bundleName.appendNumber(00);
225 
226  return bundleName;
227 }
228 
229 } // namespace v2
230 } // namespace security
231 } // 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:215
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:157
void setBundleInterestLifetime(time::milliseconds time)
Set the lifetime of certificate bundle interest.
void cacheUnverifiedCert(Certificate &&cert)
Cache unverified certificate for a period of time (5 minutes)
Represents an Interest packet.
Definition: interest.hpp:44
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:38
NackReason getReason() const
Definition: nack.hpp:90
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
Get the successor of this name component.
const CertificateCache & getUnverifiedCertCache() const
const Block & get(uint32_t type) const
Get the first sub element of specified TLV-TYPE.
Definition: block.cpp:422
constexpr const T & get() const noexcept
Definition: tag.hpp:86
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:93
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:43
Fetch certificate bundle from the network.
PendingInterestHandle expressInterest(const Interest &interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Express Interest.
Definition: face.cpp:131
Represents a name component.
bool empty() const
Check if name is empty.
Definition: name.hpp:139
#define NDN_LOG_INIT(name)
declare a log module
Definition: logger.hpp:90
Interest & setInterestLifetime(time::milliseconds lifetime)
Set Interest's lifetime.
Definition: interest.cpp:570
Represents a Data packet.
Definition: data.hpp:35
void setCertificateStorage(CertificateStorage &certStorage) override
Set the storage for this and inner certificate fetcher.
Interest & setCanBePrefix(bool canBePrefix)
Add or remove CanBePrefix element.
Definition: interest.hpp:187