blob: f768efc9676d32c10c28792bfe5066681bad51f7 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yu48e8c0c2014-03-19 12:01:55 -07002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070022 */
23
24#ifndef NDN_SECURITY_VALIDATOR_CONFIG_HPP
25#define NDN_SECURITY_VALIDATOR_CONFIG_HPP
26
27#include "validator.hpp"
28#include "certificate-cache.hpp"
29#include "conf/rule.hpp"
30#include "conf/common.hpp"
31
32namespace ndn {
33
34class ValidatorConfig : public Validator
35{
Yingdi Yub4650652014-04-17 10:19:59 -070036
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070037public:
38 class Error : public Validator::Error
39 {
40 public:
41 explicit
42 Error(const std::string& what)
43 : Validator::Error(what)
44 {
45 }
46 };
47
48 static const shared_ptr<CertificateCache> DEFAULT_CERTIFICATE_CACHE;
49
Yingdi Yu96e64062014-04-15 19:57:33 -070050 explicit
51 ValidatorConfig(Face& face,
52 const shared_ptr<CertificateCache>& certificateCache = DEFAULT_CERTIFICATE_CACHE,
53 const int stepLimit = 10);
54
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070055 virtual
56 ~ValidatorConfig()
57 {
58 }
59
60 void
61 load(const std::string& filename);
62
63 void
64 load(const std::string& input, const std::string& filename);
65
66 void
67 load(std::istream& input, const std::string& filename);
68
Yingdi Yudfa9d732014-04-09 09:53:01 -070069 void
70 load(const security::conf::ConfigSection& configSection,
71 const std::string& filename);
72
Yingdi Yu58f33712014-04-16 16:57:47 -070073 inline void
74 reset();
75
76 inline bool
77 isEmpty();
78
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070079protected:
80 virtual void
81 checkPolicy(const Data& data,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070082 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070083 const OnDataValidated& onValidated,
84 const OnDataValidationFailed& onValidationFailed,
85 std::vector<shared_ptr<ValidationRequest> >& nextSteps);
86
87 virtual void
88 checkPolicy(const Interest& interest,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070089 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070090 const OnInterestValidated& onValidated,
91 const OnInterestValidationFailed& onValidationFailed,
92 std::vector<shared_ptr<ValidationRequest> >& nextSteps);
93
94private:
95 template<class Packet, class OnValidated, class OnFailed>
96 void
97 checkSignature(const Packet& packet,
98 const Signature& signature,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -070099 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700100 const OnValidated& onValidated,
101 const OnFailed& onValidationFailed,
102 std::vector<shared_ptr<ValidationRequest> >& nextSteps);
103
104 template<class Packet, class OnValidated, class OnFailed>
105 void
106 onCertValidated(const shared_ptr<const Data>& signCertificate,
107 const shared_ptr<const Packet>& packet,
108 const OnValidated& onValidated,
109 const OnFailed& onValidationFailed);
110
111 template<class Packet, class OnFailed>
112 void
113 onCertFailed(const shared_ptr<const Data>& signCertificate,
114 const std::string& failureInfo,
115 const shared_ptr<const Packet>& packet,
116 const OnFailed& onValidationFailed);
117
118 void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700119 onConfigRule(const security::conf::ConfigSection& section,
120 const std::string& filename);
121
122 void
123 onConfigTrustAnchor(const security::conf::ConfigSection& section,
124 const std::string& filename);
125
Yingdi Yub4650652014-04-17 10:19:59 -0700126 time::nanoseconds
127 getRefreshPeriod(std::string refreshString);
128
129 inline time::nanoseconds
130 getDefaultRefreshPeriod();
131
132 void
133 refreshAnchors();
134
135
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700136private:
Yingdi Yub4650652014-04-17 10:19:59 -0700137
138 class TrustAnchorContainer
139 {
140 public:
141 TrustAnchorContainer()
142 {
143 }
144
145 const std::list<shared_ptr<IdentityCertificate> >&
146 getAll() const
147 {
148 return m_certificates;
149 }
150
151 void
152 add(shared_ptr<IdentityCertificate> certificate)
153 {
154 m_certificates.push_back(certificate);
155 }
156
157 protected:
158 std::list<shared_ptr<IdentityCertificate> > m_certificates;
159 };
160
161 class DynamicTrustAnchorContainer : public TrustAnchorContainer
162 {
163 public:
164 DynamicTrustAnchorContainer(const boost::filesystem::path& path, bool isDir,
165 time::nanoseconds refreshPeriod)
166 : m_path(path)
167 , m_isDir(isDir)
168 , m_refreshPeriod(refreshPeriod)
169 {
170 }
171
172 void
173 setLastRefresh(const time::system_clock::TimePoint& lastRefresh)
174 {
175 m_lastRefresh = lastRefresh;
176 }
177
178 const time::system_clock::TimePoint&
179 getLastRefresh() const
180 {
181 return m_lastRefresh;
182 }
183
184 const time::nanoseconds&
185 getRefreshPeriod() const
186 {
187 return m_refreshPeriod;
188 }
189
190 void
191 refresh();
192
193 private:
194 boost::filesystem::path m_path;
195 bool m_isDir;
196
197 time::system_clock::TimePoint m_lastRefresh;
198 time::nanoseconds m_refreshPeriod;
199 };
200
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700201 typedef security::conf::Rule<Interest> InterestRule;
202 typedef security::conf::Rule<Data> DataRule;
203 typedef std::vector<shared_ptr<InterestRule> > InterestRuleList;
204 typedef std::vector<shared_ptr<DataRule> > DataRuleList;
205 typedef std::map<Name, shared_ptr<IdentityCertificate> > AnchorList;
Yingdi Yub4650652014-04-17 10:19:59 -0700206 typedef std::list<DynamicTrustAnchorContainer> DynamicContainers; // sorted by m_lastRefresh
207 typedef std::list<shared_ptr<IdentityCertificate> > CertificateList;
208
209 static inline bool
210 compareDynamicContainer(const DynamicTrustAnchorContainer& containerA,
211 const DynamicTrustAnchorContainer& containerB)
212 {
213 return (containerA.getLastRefresh() < containerB.getLastRefresh());
214 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700215
Yingdi Yu44d190c2014-04-16 17:05:46 -0700216 /**
217 * @brief gives whether validation should be preformed
218 *
219 * If false, no validation occurs, and any packet is considered validated immediately.
220 */
221 bool m_shouldValidate;
222
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700223 int m_stepLimit;
224 shared_ptr<CertificateCache> m_certificateCache;
225
226 InterestRuleList m_interestRules;
227 DataRuleList m_dataRules;
Yingdi Yub4650652014-04-17 10:19:59 -0700228
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700229 AnchorList m_anchors;
Yingdi Yub4650652014-04-17 10:19:59 -0700230 TrustAnchorContainer m_staticContainer;
231 DynamicContainers m_dynamicContainers;
232
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700233};
234
Yingdi Yu58f33712014-04-16 16:57:47 -0700235inline void
236ValidatorConfig::reset()
237{
238 m_certificateCache->reset();
239 m_interestRules.clear();
240 m_dataRules.clear();
Yingdi Yub4650652014-04-17 10:19:59 -0700241
Yingdi Yu58f33712014-04-16 16:57:47 -0700242 m_anchors.clear();
Yingdi Yub4650652014-04-17 10:19:59 -0700243
244 m_staticContainer = TrustAnchorContainer();
245
246 m_dynamicContainers.clear();
Yingdi Yu58f33712014-04-16 16:57:47 -0700247}
248
249inline bool
250ValidatorConfig::isEmpty()
251{
252 if (m_certificateCache->isEmpty() &&
253 m_interestRules.empty() &&
254 m_dataRules.empty() &&
255 m_anchors.empty())
256 return true;
257 return false;
258}
259
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700260template<class Packet, class OnValidated, class OnFailed>
261void
262ValidatorConfig::checkSignature(const Packet& packet,
263 const Signature& signature,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700264 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700265 const OnValidated& onValidated,
266 const OnFailed& onValidationFailed,
267 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
268{
269 if (signature.getType() == Signature::Sha256)
270 {
Yingdi Yubf6a2812014-06-17 15:32:11 -0700271 DigestSha256 sigSha256(signature);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700272
273 if (verifySignature(packet, sigSha256))
274 return onValidated(packet.shared_from_this());
275 else
276 return onValidationFailed(packet.shared_from_this(),
277 "Sha256 Signature cannot be verified!");
278 }
279
280 if (signature.getType() == Signature::Sha256WithRsa)
281 {
282 SignatureSha256WithRsa sigSha256Rsa(signature);
283 Name keyLocatorName = sigSha256Rsa.getKeyLocator().getName();
284
285 shared_ptr<const Certificate> trustedCert;
286
Yingdi Yub4650652014-04-17 10:19:59 -0700287 refreshAnchors();
288
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700289 AnchorList::const_iterator it = m_anchors.find(keyLocatorName);
290 if (m_anchors.end() == it)
291 trustedCert = m_certificateCache->getCertificate(keyLocatorName);
292 else
293 trustedCert = it->second;
294
295 if (static_cast<bool>(trustedCert))
296 {
297 if (verifySignature(packet, sigSha256Rsa, trustedCert->getPublicKeyInfo()))
298 return onValidated(packet.shared_from_this());
299 else
300 return onValidationFailed(packet.shared_from_this(),
301 "Cannot verify signature");
302 }
303 else
304 {
Yingdi Yub4650652014-04-17 10:19:59 -0700305 if (m_stepLimit == nSteps)
306 return onValidationFailed(packet.shared_from_this(),
307 "Maximum steps of validation reached");
308
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700309 OnDataValidated onCertValidated =
310 bind(&ValidatorConfig::onCertValidated<Packet, OnValidated, OnFailed>,
311 this, _1, packet.shared_from_this(), onValidated, onValidationFailed);
312
313 OnDataValidationFailed onCertValidationFailed =
314 bind(&ValidatorConfig::onCertFailed<Packet, OnFailed>,
315 this, _1, _2, packet.shared_from_this(), onValidationFailed);
316
317 Interest certInterest(keyLocatorName);
318
319 shared_ptr<ValidationRequest> nextStep =
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700320 make_shared<ValidationRequest>(certInterest,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700321 onCertValidated,
322 onCertValidationFailed,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700323 1, nSteps + 1);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700324
325 nextSteps.push_back(nextStep);
326 return;
327 }
328 }
329 return onValidationFailed(packet.shared_from_this(), "Unsupported Signature Type!");
330}
331
332template<class Packet, class OnValidated, class OnFailed>
333void
334ValidatorConfig::onCertValidated(const shared_ptr<const Data>& signCertificate,
335 const shared_ptr<const Packet>& packet,
336 const OnValidated& onValidated,
337 const OnFailed& onValidationFailed)
338{
339 shared_ptr<IdentityCertificate> certificate =
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700340 make_shared<IdentityCertificate>(*signCertificate);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700341
342 if (!certificate->isTooLate() && !certificate->isTooEarly())
343 {
344 m_certificateCache->insertCertificate(certificate);
345
346 if (verifySignature(*packet, certificate->getPublicKeyInfo()))
347 return onValidated(packet);
348 else
349 return onValidationFailed(packet,
350 "Cannot verify signature: " +
351 packet->getName().toUri());
352 }
353 else
354 {
355 return onValidationFailed(packet,
356 "Signing certificate " +
357 signCertificate->getName().toUri() +
358 " is no longer valid.");
359 }
360}
361
362template<class Packet, class OnFailed>
363void
364ValidatorConfig::onCertFailed(const shared_ptr<const Data>& signCertificate,
365 const std::string& failureInfo,
366 const shared_ptr<const Packet>& packet,
367 const OnFailed& onValidationFailed)
368{
369 onValidationFailed(packet, failureInfo);
370}
371
Yingdi Yub4650652014-04-17 10:19:59 -0700372inline time::nanoseconds
373ValidatorConfig::getDefaultRefreshPeriod()
374{
375 return time::duration_cast<time::nanoseconds>(time::seconds(3600));
376}
377
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700378} // namespace ndn
379
380#endif // NDN_SECURITY_VALIDATOR_CONFIG_HPP