ndn-cxx: NDN C++ Library 0.9.0-33-g832ea91d
Loading...
Searching...
No Matches
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-2024 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
27#include "ndn-cxx/tag.hpp"
29
30#define NDN_LOG_DEBUG_DEPTH(x) NDN_LOG_DEBUG(std::string(state->getDepth() + 1, '>') << ' ' << x)
31
32namespace ndn::security {
33
35
38
39CertificateBundleFetcher::CertificateBundleFetcher(unique_ptr<CertificateFetcher> inner, Face& face)
40 : m_inner(std::move(inner))
41 , m_face(face)
42{
43 BOOST_ASSERT(m_inner != nullptr);
44}
45
46void
48{
49 m_certStorage = &certStorage;
50 m_inner->setCertificateStorage(certStorage);
51}
52
53void
54CertificateBundleFetcher::doFetch(const shared_ptr<CertificateRequest>& certRequest,
55 const shared_ptr<ValidationState>& state,
56 const ValidationContinuation& continueValidation)
57{
58 auto dataValidationState = std::dynamic_pointer_cast<DataValidationState>(state);
59 if (dataValidationState == nullptr) {
60 return m_inner->fetch(certRequest, state, continueValidation);
61 }
62
63 // check if a bundle segment was fetched before
64 shared_ptr<BundleNameTag> bundleNameTag = state->getTag<BundleNameTag>();
65 if (bundleNameTag == nullptr) {
66 const Name& originalDataName = dataValidationState->getOriginalData().getName();
67 if (originalDataName.empty()) {
68 return m_inner->fetch(certRequest, state, continueValidation);
69 }
70 // derive certificate bundle name from original data name
71 Name bundleNamePrefix = deriveBundleName(originalDataName);
72 fetchFirstBundleSegment(bundleNamePrefix, certRequest, state, continueValidation);
73 }
74 else {
75 Name fullBundleName = bundleNameTag->get();
76 fetchNextBundleSegment(fullBundleName, fullBundleName.get(-1).getSuccessor(),
77 certRequest, state, continueValidation);
78 }
79}
80
81void
82CertificateBundleFetcher::fetchFirstBundleSegment(const Name& bundleNamePrefix,
83 const shared_ptr<CertificateRequest>& certRequest,
84 const shared_ptr<ValidationState>& state,
85 const ValidationContinuation& continueValidation)
86{
87 Interest bundleInterest = Interest(bundleNamePrefix);
88 bundleInterest.setCanBePrefix(true);
89 bundleInterest.setMustBeFresh(true);
90 bundleInterest.setInterestLifetime(m_bundleInterestLifetime);
91
92 m_face.expressInterest(bundleInterest,
93 [=] (const Interest&, const Data& data) {
94 dataCallback(data, true, certRequest, state, continueValidation);
95 },
96 [=] (const Interest&, const lp::Nack& nack) {
97 nackCallback(nack, certRequest, state, continueValidation, bundleNamePrefix);
98 },
99 [=] (const Interest&) {
100 timeoutCallback(certRequest, state, continueValidation, bundleNamePrefix);
101 });
102}
103
104void
105CertificateBundleFetcher::fetchNextBundleSegment(const Name& fullBundleName, const name::Component& segmentNo,
106 const shared_ptr<CertificateRequest>& certRequest,
107 const shared_ptr<ValidationState>& state,
108 const ValidationContinuation& continueValidation)
109{
110 shared_ptr<FinalBlockIdTag> finalBlockId = state->getTag<FinalBlockIdTag>();
111 if (finalBlockId != nullptr && segmentNo > finalBlockId->get()) {
112 return m_inner->fetch(certRequest, state, continueValidation);
113 }
114
115 Interest bundleInterest(fullBundleName.getPrefix(-1).append(segmentNo));
116 bundleInterest.setCanBePrefix(false);
117 bundleInterest.setMustBeFresh(false);
118 bundleInterest.setInterestLifetime(m_bundleInterestLifetime);
119
120 m_face.expressInterest(bundleInterest,
121 [=] (const Interest&, const Data& data) {
122 dataCallback(data, false, certRequest, state, continueValidation);
123 },
124 [=] (const Interest&, const lp::Nack& nack) {
125 nackCallback(nack, certRequest, state, continueValidation, fullBundleName);
126 },
127 [=] (const Interest&) {
128 timeoutCallback(certRequest, state, continueValidation, fullBundleName);
129 });
130}
131
132void
133CertificateBundleFetcher::dataCallback(const Data& bundleData,
134 bool isSegmentZeroExpected,
135 const shared_ptr<CertificateRequest>& certRequest,
136 const shared_ptr<ValidationState>& state,
137 const ValidationContinuation& continueValidation)
138{
139 NDN_LOG_DEBUG_DEPTH("Fetched certificate bundle " << bundleData.getName());
140
141 name::Component currentSegment = bundleData.getName().get(-1);
142 if (!currentSegment.isSegment()) {
143 return m_inner->fetch(certRequest, state, continueValidation);
144 }
145
146 if (isSegmentZeroExpected && currentSegment.toSegment() != 0) {
147 // fetch segment zero
148 fetchNextBundleSegment(bundleData.getName(), name::Component::fromSegment(0),
149 certRequest, state, continueValidation);
150 }
151 else {
152 state->setTag(make_shared<BundleNameTag>(bundleData.getName()));
153
154 const auto& finalBlockId = bundleData.getFinalBlock();
155 if (finalBlockId) {
156 state->setTag(make_shared<FinalBlockIdTag>(*finalBlockId));
157 }
158
159 Block bundleContent = bundleData.getContent();
160 bundleContent.parse();
161
162 // store all the certificates in unverified cache
163 for (const auto& block : bundleContent.elements()) {
164 m_certStorage->cacheUnverifiedCert(Certificate(block));
165 }
166
167 auto cert = m_certStorage->getUnverifiedCertCache().find(certRequest->interest);
168 continueValidation(*cert, state);
169 }
170}
171
172void
173CertificateBundleFetcher::nackCallback(const lp::Nack& nack,
174 const shared_ptr<CertificateRequest>& certRequest,
175 const shared_ptr<ValidationState>& state,
176 const ValidationContinuation& continueValidation,
177 const Name& bundleName)
178{
179 NDN_LOG_DEBUG_DEPTH("NACK (" << nack.getReason() << ") while fetching certificate bundle "
180 << bundleName);
181
182 m_inner->fetch(certRequest, state, continueValidation);
183}
184
185void
186CertificateBundleFetcher::timeoutCallback(const shared_ptr<CertificateRequest>& certRequest,
187 const shared_ptr<ValidationState>& state,
188 const ValidationContinuation& continueValidation,
189 const Name& bundleName)
190{
191 NDN_LOG_DEBUG_DEPTH("Timeout while fetching certificate bundle " << bundleName);
192
193 m_inner->fetch(certRequest, state, continueValidation);
194}
195
196Name
197CertificateBundleFetcher::deriveBundleName(const Name& name)
198{
199 Name bundleName = name;
200 const auto& lastComponent = name.at(-1);
201
202 if (lastComponent.isImplicitSha256Digest()) {
203 if (name.size() >= 2 && name.get(-2).isSegment()) {
204 bundleName = name.getPrefix(-2);
205 }
206 else {
207 bundleName = name.getPrefix(-1);
208 }
209 }
210 else if (lastComponent.isSegment()) {
211 bundleName = name.getPrefix(-1);
212 }
213
214 bundleName.append("_BUNDLE");
215 bundleName.appendNumber(0);
216 return bundleName;
217}
218
219} // namespace ndn::security
#define NDN_LOG_DEBUG_DEPTH(x)
Represents a Data packet.
Definition data.hpp:39
Provide a communication channel with local or remote NDN forwarder.
Definition face.hpp:91
PendingInterestHandle expressInterest(const Interest &interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Express an Interest.
Definition face.cpp:151
Represents an Interest packet.
Definition interest.hpp:50
Interest & setCanBePrefix(bool canBePrefix)
Add or remove CanBePrefix element.
Definition interest.cpp:372
Interest & setMustBeFresh(bool mustBeFresh)
Add or remove MustBeFresh element.
Definition interest.cpp:382
Interest & setInterestLifetime(time::milliseconds lifetime)
Set the Interest's lifetime.
Definition interest.cpp:451
Represents an absolute name.
Definition name.hpp:45
const Component & get(ssize_t i) const noexcept
Returns an immutable reference to the component at the specified index.
Definition name.hpp:192
bool empty() const noexcept
Checks if the name is empty, i.e., has no components.
Definition name.hpp:171
Provides a tag type for simple types.
Definition tag.hpp:56
Represents a Network Nack.
Definition nack.hpp:39
static Component fromSegment(uint64_t segmentNo)
Create a segment number component using NDN naming conventions.
Component getSuccessor() const
Get the successor of this name component.
Fetch certificate bundle from the network.
CertificateBundleFetcher(unique_ptr< CertificateFetcher > inner, Face &face)
void doFetch(const shared_ptr< CertificateRequest > &certRequest, const shared_ptr< ValidationState > &state, const ValidationContinuation &continueValidation) override
Asynchronous certificate fetching implementation.
void setCertificateStorage(CertificateStorage &certStorage) override
Set the storage for this and inner certificate fetcher.
const Certificate * find(const Name &certPrefix) const
Get certificate given key name.
std::function< void(const Certificate &cert, const shared_ptr< ValidationState > &state)> ValidationContinuation
Storage for trusted anchors, verified certificate cache, and unverified certificate cache.
void cacheUnverifiedCert(Certificate &&cert)
Cache unverified certificate for a period of time (5 minutes).
const CertificateCache & getUnverifiedCertCache() const
#define NDN_LOG_INIT(name)
Define a non-member log module.
Definition logger.hpp:169
Contains the ndn-cxx security framework.
SimpleTag< name::Component, 1001 > FinalBlockIdTag
@ Name
Definition tlv.hpp:71
@ Interest
Definition tlv.hpp:68
Definition data.cpp:25
STL namespace.