blob: 5891ff1cf09385a47d09b1de5682f25dd4a5fff4 [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#include "validator-config.hpp"
25#include "certificate-cache-ttl.hpp"
26#include "../util/io.hpp"
27
28#include <boost/filesystem.hpp>
29#include <boost/property_tree/info_parser.hpp>
30#include <boost/algorithm/string.hpp>
31
32namespace ndn {
33
34const shared_ptr<CertificateCache> ValidatorConfig::DEFAULT_CERTIFICATE_CACHE;
Yingdi Yu0f5fb692014-06-10 12:07:28 -070035const time::milliseconds ValidatorConfig::DEFAULT_GRACE_INTERVAL(3000);
36const time::system_clock::Duration ValidatorConfig::DEFAULT_KEY_TIMESTAMP_TTL = time::hours(1);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070037
Yingdi Yu96e64062014-04-15 19:57:33 -070038ValidatorConfig::ValidatorConfig(Face& face,
39 const shared_ptr<CertificateCache>& certificateCache,
Yingdi Yu0f5fb692014-06-10 12:07:28 -070040 const time::milliseconds& graceInterval,
41 const size_t stepLimit,
42 const size_t maxTrackedKeys,
43 const time::system_clock::Duration& keyTimestampTtl)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070044 : Validator(face)
Yingdi Yu44d190c2014-04-16 17:05:46 -070045 , m_shouldValidate(true)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070046 , m_stepLimit(stepLimit)
47 , m_certificateCache(certificateCache)
Yingdi Yu0f5fb692014-06-10 12:07:28 -070048 , m_graceInterval(graceInterval < time::milliseconds::zero() ?
49 DEFAULT_GRACE_INTERVAL : graceInterval)
50 , m_maxTrackedKeys(maxTrackedKeys)
51 , m_keyTimestampTtl(keyTimestampTtl)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070052{
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070053 if (!static_cast<bool>(m_certificateCache))
Alexander Afanasyevb67090a2014-04-29 22:31:01 -070054 m_certificateCache = make_shared<CertificateCacheTtl>(ref(m_face.getIoService()));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070055}
56
57void
58ValidatorConfig::load(const std::string& filename)
59{
60 std::ifstream inputFile;
61 inputFile.open(filename.c_str());
62 if (!inputFile.good() || !inputFile.is_open())
63 {
64 std::string msg = "Failed to read configuration file: ";
65 msg += filename;
66 throw security::conf::Error(msg);
67 }
68 load(inputFile, filename);
69 inputFile.close();
70}
71
72void
73ValidatorConfig::load(const std::string& input, const std::string& filename)
74{
75 std::istringstream inputStream(input);
76 load(inputStream, filename);
77}
78
79
80void
81ValidatorConfig::load(std::istream& input, const std::string& filename)
82{
83 security::conf::ConfigSection tree;
84 try
85 {
86 boost::property_tree::read_info(input, tree);
87 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070088 catch (boost::property_tree::info_parser_error& error)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070089 {
90 std::stringstream msg;
91 msg << "Failed to parse configuration file";
92 msg << " " << filename;
93 msg << " " << error.message() << " line " << error.line();
94 throw security::conf::Error(msg.str());
95 }
96
Yingdi Yudfa9d732014-04-09 09:53:01 -070097 load(tree, filename);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070098}
99
100void
Yingdi Yudfa9d732014-04-09 09:53:01 -0700101ValidatorConfig::load(const security::conf::ConfigSection& configSection,
102 const std::string& filename)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700103{
104 BOOST_ASSERT(!filename.empty());
105
Yingdi Yu58f33712014-04-16 16:57:47 -0700106 reset();
107
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700108 if (configSection.begin() == configSection.end())
109 {
110 std::string msg = "Error processing configuration file";
111 msg += ": ";
112 msg += filename;
113 msg += " no data";
114 throw security::conf::Error(msg);
115 }
116
117 for (security::conf::ConfigSection::const_iterator i = configSection.begin();
118 i != configSection.end(); ++i)
119 {
120 const std::string& sectionName = i->first;
121 const security::conf::ConfigSection& section = i->second;
122
123 if (boost::iequals(sectionName, "rule"))
124 {
125 onConfigRule(section, filename);
126 }
127 else if (boost::iequals(sectionName, "trust-anchor"))
128 {
129 onConfigTrustAnchor(section, filename);
130 }
131 else
132 {
133 std::string msg = "Error processing configuration file";
134 msg += " ";
135 msg += filename;
136 msg += " unrecognized section: " + sectionName;
137 throw security::conf::Error(msg);
138 }
139 }
140}
141
142void
143ValidatorConfig::onConfigRule(const security::conf::ConfigSection& configSection,
144 const std::string& filename)
145{
146 using namespace ndn::security::conf;
147
148 ConfigSection::const_iterator propertyIt = configSection.begin();
149
150 // Get rule.id
151 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "id"))
152 throw Error("Expect <rule.id>!");
153
154 std::string ruleId = propertyIt->second.data();
155 propertyIt++;
156
157 // Get rule.for
158 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"for"))
159 throw Error("Expect <rule.for> in rule: " + ruleId + "!");
160
161 std::string usage = propertyIt->second.data();
162 propertyIt++;
163
164 bool isForData;
165 if (boost::iequals(usage, "data"))
166 isForData = true;
167 else if (boost::iequals(usage, "interest"))
168 isForData = false;
169 else
170 throw Error("Unrecognized <rule.for>: " + usage
171 + " in rule: " + ruleId);
172
173 // Get rule.filter(s)
174 std::vector<shared_ptr<Filter> > filters;
175 for (; propertyIt != configSection.end(); propertyIt++)
176 {
177 if (!boost::iequals(propertyIt->first, "filter"))
178 {
179 if (boost::iequals(propertyIt->first, "checker"))
180 break;
181 throw Error("Expect <rule.filter> in rule: " + ruleId);
182 }
183
184 filters.push_back(FilterFactory::create(propertyIt->second));
185 continue;
186 }
187
188 // Get rule.checker(s)
189 std::vector<shared_ptr<Checker> > checkers;
190 for (; propertyIt != configSection.end(); propertyIt++)
191 {
192 if (!boost::iequals(propertyIt->first, "checker"))
193 throw Error("Expect <rule.checker> in rule: " + ruleId);
194
195 checkers.push_back(CheckerFactory::create(propertyIt->second, filename));
196 continue;
197 }
198
199 // Check other stuff
200 if (propertyIt != configSection.end())
201 throw Error("Expect the end of rule: " + ruleId);
202
203 if (checkers.size() == 0)
204 throw Error("No <rule.checker> is specified in rule: " + ruleId);
205
206 if (isForData)
207 {
208 shared_ptr<DataRule> rule(new DataRule(ruleId));
209 for (size_t i = 0; i < filters.size(); i++)
210 rule->addFilter(filters[i]);
211 for (size_t i = 0; i < checkers.size(); i++)
212 rule->addChecker(checkers[i]);
213
214 m_dataRules.push_back(rule);
215 }
216 else
217 {
218 shared_ptr<InterestRule> rule(new InterestRule(ruleId));
219 for (size_t i = 0; i < filters.size(); i++)
220 rule->addFilter(filters[i]);
221 for (size_t i = 0; i < checkers.size(); i++)
222 rule->addChecker(checkers[i]);
223
224 m_interestRules.push_back(rule);
225 }
226}
227
228void
229ValidatorConfig::onConfigTrustAnchor(const security::conf::ConfigSection& configSection,
230 const std::string& filename)
231{
232 using namespace ndn::security::conf;
233 using namespace boost::filesystem;
234
235 ConfigSection::const_iterator propertyIt = configSection.begin();
236
237 // Get trust-anchor.type
238 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
239 throw Error("Expect <trust-anchor.type>!");
240
241 std::string type = propertyIt->second.data();
242 propertyIt++;
243
244 if (boost::iequals(type, "file"))
245 {
246 // Get trust-anchor.file
247 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"file-name"))
248 throw Error("Expect <trust-anchor.file-name>!");
249
250 std::string file = propertyIt->second.data();
251 propertyIt++;
252
253 // Check other stuff
254 if (propertyIt != configSection.end())
255 throw Error("Expect the end of trust-anchor!");
256
257 path certfilePath = absolute(file, path(filename).parent_path());
258 shared_ptr<IdentityCertificate> idCert =
259 io::load<IdentityCertificate>(certfilePath.string());
260
261 if (static_cast<bool>(idCert))
262 {
263 BOOST_ASSERT(idCert->getName().size() >= 1);
Yingdi Yub4650652014-04-17 10:19:59 -0700264 m_staticContainer.add(idCert);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700265 m_anchors[idCert->getName().getPrefix(-1)] = idCert;
266 }
267 else
268 throw Error("Cannot read certificate from file: " +
269 certfilePath.native());
270
271 return;
272 }
273 else if (boost::iequals(type, "base64"))
274 {
275 // Get trust-anchor.base64-string
276 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "base64-string"))
277 throw Error("Expect <trust-anchor.base64-string>!");
278
279 std::stringstream ss(propertyIt->second.data());
280 propertyIt++;
281
282 // Check other stuff
283 if (propertyIt != configSection.end())
284 throw Error("Expect the end of trust-anchor!");
285
286 shared_ptr<IdentityCertificate> idCert = io::load<IdentityCertificate>(ss);
287
288 if (static_cast<bool>(idCert))
289 {
290 BOOST_ASSERT(idCert->getName().size() >= 1);
Yingdi Yub4650652014-04-17 10:19:59 -0700291 m_staticContainer.add(idCert);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700292 m_anchors[idCert->getName().getPrefix(-1)] = idCert;
293 }
294 else
295 throw Error("Cannot decode certificate from base64-string");
296
297 return;
298 }
Yingdi Yub4650652014-04-17 10:19:59 -0700299 else if (boost::iequals(type, "dir"))
300 {
301 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "dir"))
302 throw Error("Expect <trust-anchor.dir>!");
303
304 std::string dirString(propertyIt->second.data());
305 propertyIt++;
306
307 if (propertyIt != configSection.end())
308 {
309 if (boost::iequals(propertyIt->first, "refresh"))
310 {
311 using namespace boost::filesystem;
312
313 time::nanoseconds refresh = getRefreshPeriod(propertyIt->second.data());
314 propertyIt++;
315
316 if (propertyIt != configSection.end())
317 throw Error("Expect the end of trust-anchor!");
318
319 path dirPath = absolute(dirString, path(filename).parent_path());
320
321 m_dynamicContainers.push_back(DynamicTrustAnchorContainer(dirPath, true, refresh));
322
323 m_dynamicContainers.rbegin()->setLastRefresh(time::system_clock::now() - refresh);
324
325 return;
326 }
327 else
328 throw Error("Expect <trust-anchor.refresh>!");
329 }
330 else
331 {
332 using namespace boost::filesystem;
333
334 path dirPath = absolute(dirString, path(filename).parent_path());
335
336 directory_iterator end;
337
338 for (directory_iterator it(dirPath); it != end; it++)
339 {
340 shared_ptr<IdentityCertificate> idCert =
341 io::load<IdentityCertificate>(it->path().string());
342
343 if (static_cast<bool>(idCert))
344 m_staticContainer.add(idCert);
345 }
346
347 return;
348 }
349 }
Yingdi Yu44d190c2014-04-16 17:05:46 -0700350 else if (boost::iequals(type, "any"))
351 {
352 m_shouldValidate = false;
353 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700354 else
355 throw Error("Unsupported trust-anchor.type: " + type);
356}
357
Yingdi Yub4650652014-04-17 10:19:59 -0700358time::nanoseconds
359ValidatorConfig::getRefreshPeriod(std::string inputString)
360{
361 char unit = inputString[inputString.size() - 1];
362 std::string refreshString = inputString.substr(0, inputString.size() - 1);
363
364 uint32_t number;
365
366 try
367 {
368 number = boost::lexical_cast<uint32_t>(refreshString);
369 }
370 catch (boost::bad_lexical_cast&)
371 {
372 throw Error("Bad number: " + refreshString);
373 }
374
375 if (number == 0)
376 return getDefaultRefreshPeriod();
377
378 switch (unit)
379 {
380 case 'h':
381 return time::duration_cast<time::nanoseconds>(time::hours(number));
382 case 'm':
383 return time::duration_cast<time::nanoseconds>(time::minutes(number));
384 case 's':
385 return time::duration_cast<time::nanoseconds>(time::seconds(number));
386 default:
387 throw Error(std::string("Wrong time unit: ") + unit);
388 }
389}
390
391void
392ValidatorConfig::refreshAnchors()
393{
394 time::system_clock::TimePoint now = time::system_clock::now();
395
396 bool isRefreshed = false;
397
398 for (DynamicContainers::iterator cIt = m_dynamicContainers.begin();
399 cIt != m_dynamicContainers.end(); cIt++)
400 {
401 if (cIt->getLastRefresh() + cIt->getRefreshPeriod() < now)
402 {
403 isRefreshed = true;
404 cIt->refresh();
405 cIt->setLastRefresh(now);
406 }
407 else
408 break;
409 }
410
411 if (isRefreshed)
412 {
413 m_anchors.clear();
414
415 for (CertificateList::const_iterator it = m_staticContainer.getAll().begin();
416 it != m_staticContainer.getAll().end(); it++)
417 {
418 m_anchors[(*it)->getName().getPrefix(-1)] = (*it);
419 }
420
421 for (DynamicContainers::iterator cIt = m_dynamicContainers.begin();
422 cIt != m_dynamicContainers.end(); cIt++)
423 {
424 const CertificateList& certList = cIt->getAll();
425
426 for (CertificateList::const_iterator it = certList.begin();
427 it != certList.end(); it++)
428 {
429 m_anchors[(*it)->getName().getPrefix(-1)] = (*it);
430 }
431 }
432 m_dynamicContainers.sort(ValidatorConfig::compareDynamicContainer);
433 }
434}
435
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700436void
437ValidatorConfig::checkPolicy(const Data& data,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700438 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700439 const OnDataValidated& onValidated,
440 const OnDataValidationFailed& onValidationFailed,
441 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
442{
Yingdi Yu44d190c2014-04-16 17:05:46 -0700443 if (!m_shouldValidate)
444 return onValidated(data.shared_from_this());
445
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700446 bool isMatched = false;
447 int8_t checkResult = -1;
448
449 for (DataRuleList::iterator it = m_dataRules.begin();
450 it != m_dataRules.end(); it++)
451 {
452 if ((*it)->match(data))
453 {
454 isMatched = true;
455 checkResult = (*it)->check(data, onValidated, onValidationFailed);
456 break;
457 }
458 }
459
460 if (!isMatched)
461 return onValidationFailed(data.shared_from_this(), "No rule matched!");
462
463 if (checkResult == 0)
464 {
465 const Signature& signature = data.getSignature();
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700466 checkSignature(data, signature, nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700467 onValidated, onValidationFailed, nextSteps);
468 }
469}
470
471void
472ValidatorConfig::checkPolicy(const Interest& interest,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700473 int nSteps,
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700474 const OnInterestValidated& onValidated,
475 const OnInterestValidationFailed& onValidationFailed,
476 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
477{
Yingdi Yu44d190c2014-04-16 17:05:46 -0700478 if (!m_shouldValidate)
479 return onValidated(interest.shared_from_this());
480
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700481 // If interestName has less than 4 name components,
482 // it is definitely not a signed interest.
483 if (interest.getName().size() < signed_interest::MIN_LENGTH)
484 return onValidationFailed(interest.shared_from_this(),
485 "Interest is not signed: " + interest.getName().toUri());
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700486
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700487 try
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700488 {
489 const Name& interestName = interest.getName();
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700490 Signature signature(interestName[signed_interest::POS_SIG_INFO].blockFromValue(),
491 interestName[signed_interest::POS_SIG_VALUE].blockFromValue());
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700492
Yingdi Yu4a557052014-07-09 16:40:37 -0700493 if (!signature.hasKeyLocator())
494 return onValidationFailed(interest.shared_from_this(),
495 "No valid KeyLocator");
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700496
Yingdi Yu4a557052014-07-09 16:40:37 -0700497 const KeyLocator& keyLocator = signature.getKeyLocator();
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700498
499 if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
500 return onValidationFailed(interest.shared_from_this(),
501 "Key Locator is not a name");
502
503 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocator.getName());
504
505 bool isMatched = false;
506 int8_t checkResult = -1;
507
508 for (InterestRuleList::iterator it = m_interestRules.begin();
509 it != m_interestRules.end(); it++)
510 {
511 if ((*it)->match(interest))
512 {
513 isMatched = true;
514 checkResult = (*it)->check(interest,
515 bind(&ValidatorConfig::checkTimestamp, this, _1,
516 keyName, onValidated, onValidationFailed),
517 onValidationFailed);
518 break;
519 }
520 }
521
522 if (!isMatched)
523 return onValidationFailed(interest.shared_from_this(), "No rule matched!");
524
525 if (checkResult == 0)
526 {
527 checkSignature<Interest, OnInterestValidated, OnInterestValidationFailed>
Yingdi Yu4a557052014-07-09 16:40:37 -0700528 (interest, signature, nSteps,
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700529 bind(&ValidatorConfig::checkTimestamp, this, _1,
530 keyName, onValidated, onValidationFailed),
531 onValidationFailed,
532 nextSteps);
533 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700534 }
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700535 catch (Signature::Error& e)
536 {
537 return onValidationFailed(interest.shared_from_this(),
538 "No valid signature");
539 }
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700540 catch (KeyLocator::Error& e)
541 {
542 return onValidationFailed(interest.shared_from_this(),
543 "No valid KeyLocator");
544 }
Junxiao Shic2b8d242014-11-04 08:35:29 -0700545 catch (tlv::Error& e)
546 {
547 return onValidationFailed(interest.shared_from_this(),
548 "Cannot decode signature");
549 }
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700550 catch (IdentityCertificate::Error& e)
551 {
552 return onValidationFailed(interest.shared_from_this(),
553 "Cannot determine the signing key");
554 }
555}
556
557void
558ValidatorConfig::checkTimestamp(const shared_ptr<const Interest>& interest,
559 const Name& keyName,
560 const OnInterestValidated& onValidated,
561 const OnInterestValidationFailed& onValidationFailed)
562{
563 const Name& interestName = interest->getName();
564 time::system_clock::TimePoint interestTime;
565
566 try
567 {
568 interestTime =
569 time::fromUnixTimestamp(
570 time::milliseconds(interestName.get(-signed_interest::MIN_LENGTH).toNumber()));
571 }
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600572 catch (tlv::Error& e)
Yingdi Yu0f5fb692014-06-10 12:07:28 -0700573 {
574 return onValidationFailed(interest,
575 "Cannot decode signature related TLVs");
576 }
577
578 time::system_clock::TimePoint currentTime = time::system_clock::now();
579
580 LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
581 if (timestampIt == m_lastTimestamp.end())
582 {
583 if (!(currentTime - m_graceInterval <= interestTime &&
584 interestTime <= currentTime + m_graceInterval))
585 return onValidationFailed(interest,
586 "The command is not in grace interval: " +
587 interest->getName().toUri());
588 }
589 else
590 {
591 if (interestTime <= timestampIt->second)
592 return onValidationFailed(interest,
593 "The command is outdated: " +
594 interest->getName().toUri());
595 }
596
597 //Update timestamp
598 if (timestampIt == m_lastTimestamp.end())
599 {
600 cleanOldKeys();
601 m_lastTimestamp[keyName] = interestTime;
602 }
603 else
604 {
605 timestampIt->second = interestTime;
606 }
607
608 return onValidated(interest);
609}
610
611void
612ValidatorConfig::cleanOldKeys()
613{
614 if (m_lastTimestamp.size() < m_maxTrackedKeys)
615 return;
616
617 LastTimestampMap::iterator timestampIt = m_lastTimestamp.begin();
618 LastTimestampMap::iterator end = m_lastTimestamp.end();
619
620 time::system_clock::TimePoint now = time::system_clock::now();
621 LastTimestampMap::iterator oldestKeyIt = m_lastTimestamp.begin();
622 time::system_clock::TimePoint oldestTimestamp = oldestKeyIt->second;
623
624 while (timestampIt != end)
625 {
626 if (now - timestampIt->second > m_keyTimestampTtl)
627 {
628 LastTimestampMap::iterator toDelete = timestampIt;
629 timestampIt++;
630 m_lastTimestamp.erase(toDelete);
631 continue;
632 }
633
634 if (timestampIt->second < oldestTimestamp)
635 {
636 oldestTimestamp = timestampIt->second;
637 oldestKeyIt = timestampIt;
638 }
639
640 timestampIt++;
641 }
642
643 if (m_lastTimestamp.size() >= m_maxTrackedKeys)
644 m_lastTimestamp.erase(oldestKeyIt);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700645}
646
Yingdi Yub4650652014-04-17 10:19:59 -0700647void
648ValidatorConfig::DynamicTrustAnchorContainer::refresh()
649{
650 using namespace boost::filesystem;
651
652 m_certificates.clear();
653
654 if (m_isDir)
655 {
656 directory_iterator end;
657
658 for (directory_iterator it(m_path); it != end; it++)
659 {
660 shared_ptr<IdentityCertificate> idCert =
661 io::load<IdentityCertificate>(it->path().string());
662
663 if (static_cast<bool>(idCert))
664 m_certificates.push_back(idCert);
665 }
666 }
667 else
668 {
669 shared_ptr<IdentityCertificate> idCert =
670 io::load<IdentityCertificate>(m_path.string());
671
672 if (static_cast<bool>(idCert))
673 m_certificates.push_back(idCert);
674 }
675}
676
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700677
678} // namespace ndn