All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
validator-config.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
7 #include "validator-config.hpp"
9 #include "../util/io.hpp"
10 
11 #include <boost/filesystem.hpp>
12 #include <boost/property_tree/info_parser.hpp>
13 #include <boost/algorithm/string.hpp>
14 
15 namespace ndn {
16 
17 const shared_ptr<CertificateCache> ValidatorConfig::DEFAULT_CERTIFICATE_CACHE;
18 
20  const shared_ptr<CertificateCache>& certificateCache,
21  const int stepLimit)
22  : Validator(face)
23  , m_stepLimit(stepLimit)
24  , m_certificateCache(certificateCache)
25 {
26  if (!static_cast<bool>(m_certificateCache))
27  m_certificateCache = make_shared<CertificateCacheTtl>(m_face.ioService());
28 }
29 
30 ValidatorConfig::ValidatorConfig(const shared_ptr<Face>& face,
31  const shared_ptr<CertificateCache>& certificateCache,
32  const int stepLimit)
33  : Validator(*face)
34  , m_stepLimit(stepLimit)
35  , m_certificateCache(certificateCache)
36 {
37  if (!static_cast<bool>(m_certificateCache))
38  m_certificateCache = make_shared<CertificateCacheTtl>(m_face.ioService());
39 }
40 
41 
42 void
43 ValidatorConfig::load(const std::string& filename)
44 {
45  std::ifstream inputFile;
46  inputFile.open(filename.c_str());
47  if (!inputFile.good() || !inputFile.is_open())
48  {
49  std::string msg = "Failed to read configuration file: ";
50  msg += filename;
51  throw security::conf::Error(msg);
52  }
53  load(inputFile, filename);
54  inputFile.close();
55 }
56 
57 void
58 ValidatorConfig::load(const std::string& input, const std::string& filename)
59 {
60  std::istringstream inputStream(input);
61  load(inputStream, filename);
62 }
63 
64 
65 void
66 ValidatorConfig::load(std::istream& input, const std::string& filename)
67 {
69  try
70  {
71  boost::property_tree::read_info(input, tree);
72  }
73  catch (boost::property_tree::info_parser_error& error)
74  {
75  std::stringstream msg;
76  msg << "Failed to parse configuration file";
77  msg << " " << filename;
78  msg << " " << error.message() << " line " << error.line();
79  throw security::conf::Error(msg.str());
80  }
81 
82  load(tree, filename);
83 }
84 
85 void
87  const std::string& filename)
88 {
89  BOOST_ASSERT(!filename.empty());
90 
91  if (configSection.begin() == configSection.end())
92  {
93  std::string msg = "Error processing configuration file";
94  msg += ": ";
95  msg += filename;
96  msg += " no data";
97  throw security::conf::Error(msg);
98  }
99 
100  for (security::conf::ConfigSection::const_iterator i = configSection.begin();
101  i != configSection.end(); ++i)
102  {
103  const std::string& sectionName = i->first;
104  const security::conf::ConfigSection& section = i->second;
105 
106  if (boost::iequals(sectionName, "rule"))
107  {
108  onConfigRule(section, filename);
109  }
110  else if (boost::iequals(sectionName, "trust-anchor"))
111  {
112  onConfigTrustAnchor(section, filename);
113  }
114  else
115  {
116  std::string msg = "Error processing configuration file";
117  msg += " ";
118  msg += filename;
119  msg += " unrecognized section: " + sectionName;
120  throw security::conf::Error(msg);
121  }
122  }
123 }
124 
125 void
126 ValidatorConfig::onConfigRule(const security::conf::ConfigSection& configSection,
127  const std::string& filename)
128 {
129  using namespace ndn::security::conf;
130 
131  ConfigSection::const_iterator propertyIt = configSection.begin();
132 
133  // Get rule.id
134  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "id"))
135  throw Error("Expect <rule.id>!");
136 
137  std::string ruleId = propertyIt->second.data();
138  propertyIt++;
139 
140  // Get rule.for
141  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"for"))
142  throw Error("Expect <rule.for> in rule: " + ruleId + "!");
143 
144  std::string usage = propertyIt->second.data();
145  propertyIt++;
146 
147  bool isForData;
148  if (boost::iequals(usage, "data"))
149  isForData = true;
150  else if (boost::iequals(usage, "interest"))
151  isForData = false;
152  else
153  throw Error("Unrecognized <rule.for>: " + usage
154  + " in rule: " + ruleId);
155 
156  // Get rule.filter(s)
157  std::vector<shared_ptr<Filter> > filters;
158  for (; propertyIt != configSection.end(); propertyIt++)
159  {
160  if (!boost::iequals(propertyIt->first, "filter"))
161  {
162  if (boost::iequals(propertyIt->first, "checker"))
163  break;
164  throw Error("Expect <rule.filter> in rule: " + ruleId);
165  }
166 
167  filters.push_back(FilterFactory::create(propertyIt->second));
168  continue;
169  }
170 
171  // Get rule.checker(s)
172  std::vector<shared_ptr<Checker> > checkers;
173  for (; propertyIt != configSection.end(); propertyIt++)
174  {
175  if (!boost::iequals(propertyIt->first, "checker"))
176  throw Error("Expect <rule.checker> in rule: " + ruleId);
177 
178  checkers.push_back(CheckerFactory::create(propertyIt->second, filename));
179  continue;
180  }
181 
182  // Check other stuff
183  if (propertyIt != configSection.end())
184  throw Error("Expect the end of rule: " + ruleId);
185 
186  if (checkers.size() == 0)
187  throw Error("No <rule.checker> is specified in rule: " + ruleId);
188 
189  if (isForData)
190  {
191  shared_ptr<DataRule> rule(new DataRule(ruleId));
192  for (size_t i = 0; i < filters.size(); i++)
193  rule->addFilter(filters[i]);
194  for (size_t i = 0; i < checkers.size(); i++)
195  rule->addChecker(checkers[i]);
196 
197  m_dataRules.push_back(rule);
198  }
199  else
200  {
201  shared_ptr<InterestRule> rule(new InterestRule(ruleId));
202  for (size_t i = 0; i < filters.size(); i++)
203  rule->addFilter(filters[i]);
204  for (size_t i = 0; i < checkers.size(); i++)
205  rule->addChecker(checkers[i]);
206 
207  m_interestRules.push_back(rule);
208  }
209 }
210 
211 void
212 ValidatorConfig::onConfigTrustAnchor(const security::conf::ConfigSection& configSection,
213  const std::string& filename)
214 {
215  using namespace ndn::security::conf;
216  using namespace boost::filesystem;
217 
218  ConfigSection::const_iterator propertyIt = configSection.begin();
219 
220  // Get trust-anchor.type
221  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
222  throw Error("Expect <trust-anchor.type>!");
223 
224  std::string type = propertyIt->second.data();
225  propertyIt++;
226 
227  if (boost::iequals(type, "file"))
228  {
229  // Get trust-anchor.file
230  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"file-name"))
231  throw Error("Expect <trust-anchor.file-name>!");
232 
233  std::string file = propertyIt->second.data();
234  propertyIt++;
235 
236  // Check other stuff
237  if (propertyIt != configSection.end())
238  throw Error("Expect the end of trust-anchor!");
239 
240  path certfilePath = absolute(file, path(filename).parent_path());
241  shared_ptr<IdentityCertificate> idCert =
242  io::load<IdentityCertificate>(certfilePath.string());
243 
244  if (static_cast<bool>(idCert))
245  {
246  BOOST_ASSERT(idCert->getName().size() >= 1);
247  m_anchors[idCert->getName().getPrefix(-1)] = idCert;
248  }
249  else
250  throw Error("Cannot read certificate from file: " +
251  certfilePath.native());
252 
253  return;
254  }
255  else if (boost::iequals(type, "base64"))
256  {
257  // Get trust-anchor.base64-string
258  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "base64-string"))
259  throw Error("Expect <trust-anchor.base64-string>!");
260 
261  std::stringstream ss(propertyIt->second.data());
262  propertyIt++;
263 
264  // Check other stuff
265  if (propertyIt != configSection.end())
266  throw Error("Expect the end of trust-anchor!");
267 
268  shared_ptr<IdentityCertificate> idCert = io::load<IdentityCertificate>(ss);
269 
270  if (static_cast<bool>(idCert))
271  {
272  BOOST_ASSERT(idCert->getName().size() >= 1);
273  m_anchors[idCert->getName().getPrefix(-1)] = idCert;
274  }
275  else
276  throw Error("Cannot decode certificate from base64-string");
277 
278  return;
279  }
280  else
281  throw Error("Unsupported trust-anchor.type: " + type);
282 }
283 
284 void
286  int nSteps,
287  const OnDataValidated& onValidated,
288  const OnDataValidationFailed& onValidationFailed,
289  std::vector<shared_ptr<ValidationRequest> >& nextSteps)
290 {
291  if (m_stepLimit == nSteps)
292  return onValidationFailed(data.shared_from_this(),
293  "Maximum steps of validation reached");
294 
295  bool isMatched = false;
296  int8_t checkResult = -1;
297 
298  for (DataRuleList::iterator it = m_dataRules.begin();
299  it != m_dataRules.end(); it++)
300  {
301  if ((*it)->match(data))
302  {
303  isMatched = true;
304  checkResult = (*it)->check(data, onValidated, onValidationFailed);
305  break;
306  }
307  }
308 
309  if (!isMatched)
310  return onValidationFailed(data.shared_from_this(), "No rule matched!");
311 
312  if (checkResult == 0)
313  {
314  const Signature& signature = data.getSignature();
315  checkSignature(data, signature, nSteps,
316  onValidated, onValidationFailed, nextSteps);
317  }
318 }
319 
320 void
322  int nSteps,
323  const OnInterestValidated& onValidated,
324  const OnInterestValidationFailed& onValidationFailed,
325  std::vector<shared_ptr<ValidationRequest> >& nextSteps)
326 {
327  if (m_stepLimit == nSteps)
328  return onValidationFailed(interest.shared_from_this(),
329  "Maximum steps of validation reached");
330 
331  bool isMatched = false;
332  int8_t checkResult = -1;
333 
334  for (InterestRuleList::iterator it = m_interestRules.begin();
335  it != m_interestRules.end(); it++)
336  {
337  if ((*it)->match(interest))
338  {
339  isMatched = true;
340  checkResult = (*it)->check(interest, onValidated, onValidationFailed);
341  break;
342  }
343  }
344 
345  if (!isMatched)
346  return onValidationFailed(interest.shared_from_this(), "No rule matched!");
347 
348  if (checkResult == 0)
349  {
350  const Name& interestName = interest.getName();
351  Name signedName = interestName.getPrefix(-2);
352  Signature signature(interestName[-2].blockFromValue(),
353  interestName[-1].blockFromValue());
354 
355  checkSignature(interest, signature, nSteps,
356  onValidated, onValidationFailed, nextSteps);
357  }
358 }
359 
360 
361 } // namespace ndn
const Name & getName() const
Definition: interest.hpp:182
void load(const std::string &filename)
Name getPrefix(int nComponents) const
Return a new Name with the first nComponents components of this Name.
Definition: name.hpp:240
ValidatorConfig(Face &face, const shared_ptr< CertificateCache > &certificateCache=DEFAULT_CERTIFICATE_CACHE, const int stepLimit=10)
An Interest holds a Name and other fields for an interest.
Definition: interest.hpp:24
virtual void checkPolicy(const Data &data, int nSteps, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed, std::vector< shared_ptr< ValidationRequest > > &nextSteps)
Check the Data against policy and return the next validation step if necessary.
function< void(const shared_ptr< const Data > &)> OnDataValidated
Callback to report a successful Data validation.
shared_ptr< boost::asio::io_service > ioService()
Get shared_ptr of the IO service object.
Definition: face.hpp:279
function< void(const shared_ptr< const Data > &, const std::string &)> OnDataValidationFailed
Callback to report a failed Data validation.
Abstraction to communicate with local or remote NDN forwarder.
Definition: face.hpp:54
static const shared_ptr< CertificateCache > DEFAULT_CERTIFICATE_CACHE
A Name holds an array of Name::Component and represents an NDN name.
Definition: name.hpp:26
const Signature & getSignature() const
Definition: data.hpp:450
function< void(const shared_ptr< const Interest > &, const std::string &)> OnInterestValidationFailed
Callback to report a failed Interest validation.
boost::property_tree::ptree ConfigSection
Validator is one of the main classes of the security library.
Definition: validator.hpp:27
function< void(const shared_ptr< const Interest > &)> OnInterestValidated
Callback to report a successful Interest validation.
A Signature is storage for the signature-related information (info and value) in a Data packet...
Definition: signature.hpp:15