validator.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2021 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 
24 #include "ndn-cxx/face.hpp"
26 #include "ndn-cxx/util/logger.hpp"
27 
28 namespace ndn {
29 namespace security {
30 inline namespace v2 {
31 
33 
34 #define NDN_LOG_DEBUG_DEPTH(x) NDN_LOG_DEBUG(std::string(state->getDepth() + 1, '>') << " " << x)
35 #define NDN_LOG_TRACE_DEPTH(x) NDN_LOG_TRACE(std::string(state->getDepth() + 1, '>') << " " << x)
36 
37 Validator::Validator(unique_ptr<ValidationPolicy> policy, unique_ptr<CertificateFetcher> certFetcher)
38  : m_policy(std::move(policy))
39  , m_certFetcher(std::move(certFetcher))
40  , m_maxDepth(25)
41 {
42  BOOST_ASSERT(m_policy != nullptr);
43  BOOST_ASSERT(m_certFetcher != nullptr);
44  m_policy->setValidator(*this);
45  m_certFetcher->setCertificateStorage(*this);
46 }
47 
48 Validator::~Validator() = default;
49 
52 {
53  return *m_policy;
54 }
55 
58 {
59  return *m_certFetcher;
60 }
61 
62 void
64 {
65  m_maxDepth = depth;
66 }
67 
68 size_t
70 {
71  return m_maxDepth;
72 }
73 
74 void
76  const DataValidationSuccessCallback& successCb,
77  const DataValidationFailureCallback& failureCb)
78 {
79  auto state = make_shared<DataValidationState>(data, successCb, failureCb);
80  NDN_LOG_DEBUG_DEPTH("Start validating data " << data.getName());
81 
82  m_policy->checkPolicy(data, state,
83  [this] (const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state) {
84  if (certRequest == nullptr) {
85  state->bypassValidation();
86  }
87  else {
88  // need to fetch key and validate it
89  requestCertificate(certRequest, state);
90  }
91  });
92 }
93 
94 void
95 Validator::validate(const Interest& interest,
96  const InterestValidationSuccessCallback& successCb,
97  const InterestValidationFailureCallback& failureCb)
98 {
99  auto state = make_shared<InterestValidationState>(interest, successCb, failureCb);
100 
102  state->setTag(make_shared<SignedInterestFormatTag>(fmt));
103 
104  NDN_LOG_DEBUG_DEPTH("Start validating interest (" << fmt << ") " << interest.getName());
105 
106  m_policy->checkPolicy(interest, state,
107  [this] (const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state) {
108  if (certRequest == nullptr) {
109  state->bypassValidation();
110  }
111  else {
112  // need to fetch key and validate it
113  requestCertificate(certRequest, state);
114  }
115  });
116 }
117 
118 void
119 Validator::validate(const Certificate& cert, const shared_ptr<ValidationState>& state)
120 {
121  NDN_LOG_DEBUG_DEPTH("Start validating certificate " << cert.getName());
122 
123  if (!cert.isValid()) {
124  return state->fail({ValidationError::Code::EXPIRED_CERT, "Retrieved certificate is not yet valid or expired "
125  "`" + cert.getName().toUri() + "`"});
126  }
127 
128  m_policy->checkPolicy(cert, state,
129  [this, cert] (const shared_ptr<CertificateRequest>& certRequest, const shared_ptr<ValidationState>& state) {
130  if (certRequest == nullptr) {
131  state->fail({ValidationError::POLICY_ERROR, "Validation policy is not allowed to designate `" +
132  cert.getName().toUri() + "` as a trust anchor"});
133  }
134  else {
135  // need to fetch key and validate it
136  state->addCertificate(cert);
137  requestCertificate(certRequest, state);
138  }
139  });
140 }
141 
142 void
143 Validator::requestCertificate(const shared_ptr<CertificateRequest>& certRequest,
144  const shared_ptr<ValidationState>& state)
145 {
146  // TODO configurable check for the maximum number of steps
147  if (state->getDepth() >= m_maxDepth) {
148  state->fail({ValidationError::Code::EXCEEDED_DEPTH_LIMIT,
149  "Exceeded validation depth limit (" + to_string(m_maxDepth) + ")"});
150  return;
151  }
152 
153  if (certRequest->interest.getName() == SigningInfo::getDigestSha256Identity()) {
154  state->verifyOriginalPacket(nullopt);
155  return;
156  }
157 
158  if (state->hasSeenCertificateName(certRequest->interest.getName())) {
159  state->fail({ValidationError::Code::LOOP_DETECTED,
160  "Validation loop detected for certificate `" + certRequest->interest.getName().toUri() + "`"});
161  return;
162  }
163 
164  NDN_LOG_DEBUG_DEPTH("Retrieving " << certRequest->interest.getName());
165 
166  auto cert = findTrustedCert(certRequest->interest);
167  if (cert != nullptr) {
168  NDN_LOG_TRACE_DEPTH("Found trusted certificate " << cert->getName());
169 
170  cert = state->verifyCertificateChain(*cert);
171  if (cert != nullptr) {
172  state->verifyOriginalPacket(*cert);
173  }
174  for (auto trustedCert = std::make_move_iterator(state->m_certificateChain.begin());
175  trustedCert != std::make_move_iterator(state->m_certificateChain.end());
176  ++trustedCert) {
177  cacheVerifiedCertificate(*trustedCert);
178  }
179  return;
180  }
181 
182  m_certFetcher->fetch(certRequest, state, [this] (const Certificate& cert, const shared_ptr<ValidationState>& state) {
183  validate(cert, state);
184  });
185 }
186 
188 // Trust anchor management
190 
191 // to change visibility from protected to public
192 
193 void
194 Validator::loadAnchor(const std::string& groupId, Certificate&& cert)
195 {
196  CertificateStorage::loadAnchor(groupId, std::move(cert));
197 }
198 
199 void
200 Validator::loadAnchor(const std::string& groupId, const std::string& certfilePath,
201  time::nanoseconds refreshPeriod, bool isDir)
202 {
203  CertificateStorage::loadAnchor(groupId, certfilePath, refreshPeriod, isDir);
204 }
205 
206 void
208 {
210 }
211 
212 void
214 {
215  CertificateStorage::cacheVerifiedCert(std::move(cert));
216 }
217 
218 void
220 {
222 }
223 
224 } // inline namespace v2
225 } // namespace security
226 } // namespace ndn
Represents a Data packet.
Definition: data.hpp:38
const Name & getName() const noexcept
Get name.
Definition: data.hpp:127
Represents an Interest packet.
Definition: interest.hpp:50
const Name & getName() const noexcept
Definition: interest.hpp:173
optional< SignatureInfo > getSignatureInfo() const
Get the InterestSignatureInfo.
Definition: interest.cpp:549
static const Name & getDigestSha256Identity()
A localhost identity to indicate that the signature is generated using SHA-256.
Interface used by the validator to fetch missing certificates.
const Certificate * findTrustedCert(const Interest &interestForCert) const
Find a trusted certificate in trust anchor container or in verified cache.
void loadAnchor(const std::string &groupId, Certificate &&cert)
load static trust anchor.
void resetVerifiedCerts()
Remove any cached verified certificates.
void resetAnchors()
remove any previously loaded static or dynamic trust anchor
void cacheVerifiedCert(Certificate &&cert)
Cache verified certificate a period of time (1 hour)
Represents an NDN certificate following the version 2.0 format.
Definition: certificate.hpp:61
bool isValid(const time::system_clock::TimePoint &ts=time::system_clock::now()) const
Check if the certificate is valid at ts.
Abstraction that implements validation policy for Data and Interest packets.
Interface for validating data and interest packets.
Definition: validator.hpp:62
ValidationPolicy & getPolicy()
Definition: validator.cpp:51
void cacheVerifiedCertificate(Certificate &&cert)
Cache verified cert a period of time (1 hour)
Definition: validator.cpp:213
void setMaxDepth(size_t depth)
Set the maximum depth of the certificate chain.
Definition: validator.cpp:63
size_t getMaxDepth() const
Definition: validator.cpp:69
void resetAnchors()
remove any previously loaded static or dynamic trust anchor
Definition: validator.cpp:207
CertificateFetcher & getFetcher()
Definition: validator.cpp:57
Validator(unique_ptr< ValidationPolicy > policy, unique_ptr< CertificateFetcher > certFetcher)
Validator constructor.
Definition: validator.cpp:37
void resetVerifiedCertificates()
Remove any cached verified certificates.
Definition: validator.cpp:219
void validate(const Data &data, const DataValidationSuccessCallback &successCb, const DataValidationFailureCallback &failureCb)
Asynchronously validate data.
Definition: validator.cpp:75
void loadAnchor(const std::string &groupId, Certificate &&cert)
load static trust anchor.
Definition: validator.cpp:194
#define NDN_LOG_INIT(name)
Define a non-member log module.
Definition: logger.hpp:163
std::string to_string(const errinfo_stacktrace &x)
Definition: exception.cpp:31
function< void(const Interest &interest, const ValidationError &error)> InterestValidationFailureCallback
Callback to report a failed Interest validation.
function< void(const Data &data)> DataValidationSuccessCallback
Callback to report a successful Data validation.
function< void(const Data &data, const ValidationError &error)> DataValidationFailureCallback
Callback to report a failed Data validation.
function< void(const Interest &interest)> InterestValidationSuccessCallback
Callback to report a successful Interest validation.
@ V03
Sign Interest using Packet Specification v0.3 semantics.
@ V02
Sign Interest using Packet Specification v0.2 semantics.
boost::chrono::nanoseconds nanoseconds
Definition: time.hpp:50
Definition: data.cpp:25
#define NDN_LOG_DEBUG_DEPTH(x)
Definition: validator.cpp:34
#define NDN_LOG_TRACE_DEPTH(x)
Definition: validator.cpp:35