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.setCanBePrefix(true);
99  bundleInterest.setMustBeFresh(true);
100  bundleInterest.setChildSelector(1);
101  bundleInterest.setInterestLifetime(m_bundleInterestLifetime);
102 
103  m_face.expressInterest(bundleInterest,
104  [=] (const Interest& interest, const Data& data) {
105  dataCallback(data, true, certRequest, state, continueValidation);
106  },
107  [=] (const Interest& interest, const lp::Nack& nack) {
108  nackCallback(nack, certRequest, state, continueValidation, bundleNamePrefix);
109  },
110  [=] (const Interest& interest) {
111  timeoutCallback(certRequest, state, continueValidation, bundleNamePrefix);
112  });
113 }
114 
115 void
116 CertificateBundleFetcher::fetchNextBundleSegment(const Name& fullBundleName, const name::Component& segmentNo,
117  const shared_ptr<CertificateRequest>& certRequest,
118  const shared_ptr<ValidationState>& state,
119  const ValidationContinuation& continueValidation)
120 {
121  shared_ptr<FinalBlockIdTag> finalBlockId = state->getTag<FinalBlockIdTag>();
122  if (finalBlockId != nullptr && segmentNo > finalBlockId->get()) {
123  return m_inner->fetch(certRequest, state, continueValidation);
124  }
125 
126  Interest bundleInterest(fullBundleName.getPrefix(-1).append(segmentNo));
127  bundleInterest.setCanBePrefix(false);
128  bundleInterest.setMustBeFresh(false);
129  bundleInterest.setInterestLifetime(m_bundleInterestLifetime);
130 
131  m_face.expressInterest(bundleInterest,
132  [=] (const Interest& interest, const Data& data) {
133  dataCallback(data, false, certRequest, state, continueValidation);
134  },
135  [=] (const Interest& interest, const lp::Nack& nack) {
136  nackCallback(nack, certRequest, state, continueValidation, fullBundleName);
137  },
138  [=] (const Interest& interest) {
139  timeoutCallback(certRequest, state, continueValidation, fullBundleName);
140  });
141 }
142 
143 void
144 CertificateBundleFetcher::dataCallback(const Data& bundleData,
145  bool isSegmentZeroExpected,
146  const shared_ptr<CertificateRequest>& certRequest,
147  const shared_ptr<ValidationState>& state,
148  const ValidationContinuation& continueValidation)
149 {
150  NDN_LOG_DEBUG_DEPTH("Fetched certificate bundle from network " << bundleData.getName());
151 
152  name::Component currentSegment = bundleData.getName().get(-1);
153  if (!currentSegment.isSegment()) {
154  return m_inner->fetch(certRequest, state, continueValidation);
155  }
156 
157  if (isSegmentZeroExpected && currentSegment.toSegment() != 0) {
158  // fetch segment zero
159  fetchNextBundleSegment(bundleData.getName(), name::Component::fromSegment(0),
160  certRequest, state, continueValidation);
161  }
162  else {
163  state->setTag(make_shared<BundleNameTag>(bundleData.getName()));
164 
165  const auto& finalBlockId = bundleData.getFinalBlock();
166  if (!finalBlockId) {
167  state->setTag(make_shared<FinalBlockIdTag>(*finalBlockId));
168  }
169 
170  Block bundleContent = bundleData.getContent();
171  bundleContent.parse();
172 
173  // store all the certificates in unverified cache
174  for (const auto& block : bundleContent.elements()) {
176  }
177 
178  auto cert = m_certStorage->getUnverifiedCertCache().find(certRequest->m_interest);
179  continueValidation(*cert, state);
180  }
181 }
182 
183 void
184 CertificateBundleFetcher::nackCallback(const lp::Nack& nack,
185  const shared_ptr<CertificateRequest>& certRequest,
186  const shared_ptr<ValidationState>& state,
187  const ValidationContinuation& continueValidation,
188  const Name& bundleName)
189 {
190  NDN_LOG_DEBUG_DEPTH("NACK (" << nack.getReason() << ") while fetching certificate bundle"
191  << bundleName);
192 
193  m_inner->fetch(certRequest, state, continueValidation);
194 }
195 
196 void
197 CertificateBundleFetcher::timeoutCallback(const shared_ptr<CertificateRequest>& certRequest,
198  const shared_ptr<ValidationState>& state,
199  const ValidationContinuation& continueValidation,
200  const Name& bundleName)
201 {
202  NDN_LOG_DEBUG_DEPTH("Timeout while fetching certificate bundle" << bundleName);
203 
204  m_inner->fetch(certRequest, state, continueValidation);
205 }
206 
207 Name
208 CertificateBundleFetcher::deriveBundleName(const Name& name)
209 {
210  name::Component lastComponent = name.at(-1);
211 
212  Name bundleName = name;
213  if (lastComponent.isImplicitSha256Digest()) {
214  if (name.size() >= 2 && name.get(-2).isSegment()) {
215  bundleName = name.getPrefix(-2);
216  }
217  else {
218  bundleName = name.getPrefix(-1);
219  }
220  }
221  else if (lastComponent.isSegment()) {
222  bundleName = name.getPrefix(-1);
223  }
224  bundleName.append("_BUNDLE");
225  bundleName.appendNumber(00);
226 
227  return bundleName;
228 }
229 
230 } // namespace v2
231 } // namespace security
232 } // namespace ndn
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:65
The certificate following the certificate format naming convention.
Definition: certificate.hpp:81
const element_container & elements() const
Get container of sub elements.
Definition: block.hpp:361
#define NDN_LOG_DEBUG_DEPTH(x)
Interest & setMustBeFresh(bool mustBeFresh)
Add or remove MustBeFresh element.
Definition: interest.hpp:214
void setBundleInterestLifetime(time::milliseconds time)
Set the lifetime of certificate bundle interest.
STL namespace.
void cacheUnverifiedCert(Certificate &&cert)
Cache unverified certificate for a period of time (5 minutes)
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
Represents an Interest packet.
Definition: interest.hpp:43
const optional< name::Component > & getFinalBlock() const
Definition: data.hpp:222
std::function< void(const Certificate &cert, const shared_ptr< ValidationState > &state)> ValidationContinuation
CertificateBundleFetcher(unique_ptr< CertificateFetcher > inner, Face &face)
#define NDN_LOG_INIT(name)
Define a non-member log module.
Definition: logger.hpp:163
const Certificate * find(const Name &certPrefix) const
Get certificate given key name.
Name & appendNumber(uint64_t number)
Append a component with a nonNegativeInteger.
Definition: name.hpp:336
Name & append(const Component &component)
Append a component.
Definition: name.hpp:248
represents a Network Nack
Definition: nack.hpp:40
Validation state for a data packet.
provides a tag type for simple types
Definition: tag.hpp:58
NackReason getReason() const
Definition: nack.hpp:92
static Component fromSegment(uint64_t segmentNo)
Create segment number component using NDN naming conventions.
bool isSegment() const
Check if the component is segment number per NDN naming conventions.
const CertificateCache & getUnverifiedCertCache() const
Interest & setChildSelector(int childSelector)
Definition: interest.hpp:433
Storage for trusted anchors, verified certificate cache, and unverified certificate cache...
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.
const Block & get(uint32_t type) const
Get the first sub element of specified TLV-TYPE.
Definition: block.cpp:422
size_t size() const
Get number of components.
Definition: name.hpp:146
Represents an absolute name.
Definition: name.hpp:42
const Component & at(ssize_t i) const
Get the component at the given index.
Definition: name.cpp:180
Fetch certificate bundle from the network.
void parse() const
Parse TLV-VALUE into sub elements.
Definition: block.cpp:333
Component getSuccessor() const
Get the successor of this name component.
const Name & getName() const
Get name.
Definition: data.hpp:124
Represents a name component.
const Block & getContent() const
Get Content.
Definition: data.cpp:234
bool empty() const
Check if name is empty.
Definition: name.hpp:138
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix of the name.
Definition: name.hpp:202
Interest & setInterestLifetime(time::milliseconds lifetime)
Set Interest&#39;s lifetime.
Definition: interest.cpp:578
const PendingInterestId * expressInterest(const Interest &interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Express Interest.
Definition: face.cpp:178
Represents a Data packet.
Definition: data.hpp:35
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:156
void setCertificateStorage(CertificateStorage &certStorage) override
Set the storage for this and inner certificate fetcher.
bool isImplicitSha256Digest() const
Check if the component is ImplicitSha256DigestComponent.
Interest & setCanBePrefix(bool canBePrefix)
Add or remove CanBePrefix element.
Definition: interest.hpp:186