certificate-bundle-fetcher.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
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 name::Component& finalBlockId = bundleData.getMetaInfo().getFinalBlockId();
164  if (!finalBlockId.empty()) {
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()) {
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) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
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:347
#define NDN_LOG_DEBUG_DEPTH(x)
Interest & setMustBeFresh(bool mustBeFresh)
Definition: interest.hpp:324
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:42
const MetaInfo & getMetaInfo() const
Get MetaInfo.
Definition: data.hpp:135
std::function< void(const Certificate &cert, const shared_ptr< ValidationState > &state)> ValidationContinuation
CertificateBundleFetcher(unique_ptr< CertificateFetcher > inner, Face &face)
#define NDN_LOG_INIT(name)
declare a log module
Definition: logger.hpp:101
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:324
Name & append(const Component &component)
Append a component.
Definition: name.hpp:256
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:310
Storage for trusted anchors, verified certificate cache, and unverified certificate cache...
Provide a communication channel with local or remote NDN forwarder.
Definition: face.hpp:95
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:416
size_t size() const
Get number of components.
Definition: name.hpp:154
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:185
Fetch certificate bundle from the network.
void parse() const
Parse TLV-VALUE into sub elements.
Definition: block.cpp:334
Component getSuccessor() const
const Name & getName() const
Get name.
Definition: data.hpp:121
Component holds a read-only name component value.
Interest & setInterestLifetime(time::milliseconds interestLifetime)
Set Interest&#39;s lifetime.
Definition: interest.cpp:332
const Block & getContent() const
Get Content.
Definition: data.cpp:185
bool empty() const
Check if name is empty.
Definition: name.hpp:146
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix of the name.
Definition: name.hpp:210
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 name::Component & getFinalBlockId() const
Definition: meta-info.hpp:219
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:164
void setCertificateStorage(CertificateStorage &certStorage) override
Set the storage for this and inner certificate fetcher.
bool isImplicitSha256Digest() const
Check if the component is ImplicitSha256DigestComponent.