checker.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2017 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 
22 #include "checker.hpp"
25 #include "security/pib/key.hpp"
26 #include "util/logger.hpp"
27 
28 #include <boost/algorithm/string.hpp>
29 #include <boost/filesystem.hpp>
30 #include <boost/lexical_cast.hpp>
31 
32 namespace ndn {
33 namespace security {
34 namespace v2 {
35 namespace validator_config {
36 
37 bool
38 Checker::check(uint32_t pktType, const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state)
39 {
40  BOOST_ASSERT(pktType == tlv::Interest || pktType == tlv::Data);
41 
42  if (pktType == tlv::Interest) {
43  if (pktName.size() < signed_interest::MIN_SIZE)
44  return false;
45 
46  return checkNames(pktName.getPrefix(-signed_interest::MIN_SIZE), klName, state);
47  }
48  else {
49  return checkNames(pktName, klName, state);
50  }
51 }
52 
54  : m_name(name)
55  , m_relation(relation)
56 {
57 }
58 
59 bool
60 NameRelationChecker::checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state)
61 {
62  // pktName not used in this check
63  Name identity = extractIdentityFromKeyName(klName);
64  bool result = checkNameRelation(m_relation, m_name, identity);
65  if (!result) {
66  std::ostringstream os;
67  os << "KeyLocator check failed: name relation " << m_name << " " << m_relation
68  << " for packet " << pktName << " is invalid"
69  << " (KeyLocator=" << klName << ", identity=" << identity << ")";
70  state->fail({ValidationError::POLICY_ERROR, os.str()});
71  }
72  return result;
73 }
74 
76  : m_regex(regex)
77 {
78 }
79 
80 bool
81 RegexChecker::checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state)
82 {
83  bool result = m_regex.match(klName);
84  if (!result) {
85  std::ostringstream os;
86  os << "KeyLocator check failed: regex " << m_regex << " for packet " << pktName << " is invalid"
87  << " (KeyLocator=" << klName << ")";
88  state->fail({ValidationError::POLICY_ERROR, os.str()});
89  }
90 
91  return result;
92 }
93 
94 HyperRelationChecker::HyperRelationChecker(const std::string& pktNameExpr, const std::string pktNameExpand,
95  const std::string& klNameExpr, const std::string klNameExpand,
96  const NameRelation& hyperRelation)
97  : m_hyperPRegex(pktNameExpr, pktNameExpand)
98  , m_hyperKRegex(klNameExpr, klNameExpand)
99  , m_hyperRelation(hyperRelation)
100 {
101 }
102 
103 bool
104 HyperRelationChecker::checkNames(const Name& pktName, const Name& klName, const shared_ptr<ValidationState>& state)
105 {
106  if (!m_hyperPRegex.match(pktName) || !m_hyperKRegex.match(klName)) {
107  std::ostringstream os;
108  os << "Packet " << pktName << " (" << "KeyLocator=" << klName << ") does not match "
109  << "the hyper relation rule pkt=" << m_hyperPRegex << ", key=" << m_hyperKRegex;
110  state->fail({ValidationError::POLICY_ERROR, os.str()});
111  return false;
112  }
113 
114  bool result = checkNameRelation(m_hyperRelation, m_hyperKRegex.expand(), m_hyperPRegex.expand());
115  if (!result) {
116  std::ostringstream os;
117  os << "KeyLocator check failed: hyper relation " << m_hyperRelation
118  << " pkt=" << m_hyperPRegex << ", key=" << m_hyperKRegex
119  << " of packet " << pktName << " (KeyLocator=" << klName << ") is invalid";
120  state->fail({ValidationError::POLICY_ERROR, os.str()});
121  }
122  return result;
123 }
124 
125 unique_ptr<Checker>
126 Checker::create(const ConfigSection& configSection, const std::string& configFilename)
127 {
128  auto propertyIt = configSection.begin();
129 
130  // Get checker.type
131  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type")) {
132  BOOST_THROW_EXCEPTION(Error("Expect <checker.type>"));
133  }
134 
135  std::string type = propertyIt->second.data();
136 
137  if (boost::iequals(type, "customized")) {
138  return createCustomizedChecker(configSection, configFilename);
139  }
140  else if (boost::iequals(type, "hierarchical")) {
141  return createHierarchicalChecker(configSection, configFilename);
142  }
143  else {
144  BOOST_THROW_EXCEPTION(Error("Unsupported checker type: " + type));
145  }
146 }
147 
148 unique_ptr<Checker>
149 Checker::createCustomizedChecker(const ConfigSection& configSection,
150  const std::string& configFilename)
151 {
152  auto propertyIt = configSection.begin();
153  propertyIt++;
154 
155  // TODO implement restrictions based on signature type (outside this checker)
156 
157  if (propertyIt != configSection.end() && boost::iequals(propertyIt->first, "sig-type")) {
158  // ignore sig-type
159  propertyIt++;
160  }
161 
162  // Get checker.key-locator
163  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator")) {
164  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator>"));
165  }
166 
167  auto checker = createKeyLocatorChecker(propertyIt->second, configFilename);
168  propertyIt++;
169 
170  if (propertyIt != configSection.end()) {
171  BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
172  }
173 
174  return checker;
175 }
176 
177 unique_ptr<Checker>
178 Checker::createHierarchicalChecker(const ConfigSection& configSection,
179  const std::string& configFilename)
180 {
181  auto propertyIt = configSection.begin();
182  propertyIt++;
183 
184  // TODO implement restrictions based on signature type (outside this checker)
185 
186  if (propertyIt != configSection.end() && boost::iequals(propertyIt->first, "sig-type")) {
187  // ignore sig-type
188  propertyIt++;
189  }
190 
191  if (propertyIt != configSection.end()) {
192  BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
193  }
194 
195  return make_unique<HyperRelationChecker>("^(<>*)$", "\\1",
196  "^(<>*)<KEY><>$", "\\1",
198 }
199 
201 
202 unique_ptr<Checker>
203 Checker::createKeyLocatorChecker(const ConfigSection& configSection, const std::string& configFilename)
204 {
205  auto propertyIt = configSection.begin();
206 
207  // Get checker.key-locator.type
208  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
209  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.type>"));
210 
211  std::string type = propertyIt->second.data();
212 
213  if (boost::iequals(type, "name"))
214  return createKeyLocatorNameChecker(configSection, configFilename);
215  else
216  BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator.type: " + type));
217 }
218 
219 unique_ptr<Checker>
220 Checker::createKeyLocatorNameChecker(const ConfigSection& configSection, const std::string& configFilename)
221 {
222  auto propertyIt = configSection.begin();
223  propertyIt++;
224 
225  if (propertyIt == configSection.end())
226  BOOST_THROW_EXCEPTION(Error("Expect more checker.key-locator properties"));
227 
228  if (boost::iequals(propertyIt->first, "name")) {
229  Name name;
230  try {
231  name = Name(propertyIt->second.data());
232  }
233  catch (const Name::Error& e) {
234  BOOST_THROW_EXCEPTION(Error("Invalid checker.key-locator.name: " + propertyIt->second.data()));
235  }
236  propertyIt++;
237 
238  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation")) {
239  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.relation>"));
240  }
241 
242  std::string relationString = propertyIt->second.data();
243  propertyIt++;
244 
245  NameRelation relation = getNameRelationFromString(relationString);
246 
247  if (propertyIt != configSection.end()) {
248  BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator"));
249  }
250  return make_unique<NameRelationChecker>(name, relation);
251  }
252  else if (boost::iequals(propertyIt->first, "regex")) {
253  std::string regexString = propertyIt->second.data();
254  propertyIt++;
255 
256  if (propertyIt != configSection.end()) {
257  BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator"));
258  }
259 
260  try {
261  return make_unique<RegexChecker>(Regex(regexString));
262  }
263  catch (const Regex::Error& e) {
264  BOOST_THROW_EXCEPTION(Error("Invalid checker.key-locator.regex: " + regexString));
265  }
266  }
267  else if (boost::iequals(propertyIt->first, "hyper-relation")) {
268  const ConfigSection& hSection = propertyIt->second;
269 
270  ConfigSection::const_iterator hPropertyIt = hSection.begin();
271 
272  // Get k-regex
273  if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-regex")) {
274  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.k-regex>"));
275  }
276 
277  std::string kRegex = hPropertyIt->second.data();
278  hPropertyIt++;
279 
280  // Get k-expand
281  if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-expand")) {
282  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.k-expand>"));
283  }
284 
285  std::string kExpand = hPropertyIt->second.data();
286  hPropertyIt++;
287 
288  // Get h-relation
289  if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "h-relation")) {
290  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.h-relation>"));
291  }
292 
293  std::string hRelation = hPropertyIt->second.data();
294  hPropertyIt++;
295 
296  // Get p-regex
297  if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-regex")) {
298  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.p-regex>"));
299  }
300 
301  std::string pRegex = hPropertyIt->second.data();
302  hPropertyIt++;
303 
304  // Get p-expand
305  if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-expand")) {
306  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator.hyper-relation.p-expand>"));
307  }
308 
309  std::string pExpand = hPropertyIt->second.data();
310  hPropertyIt++;
311 
312  if (hPropertyIt != hSection.end()) {
313  BOOST_THROW_EXCEPTION(Error("Expect the end of checker.key-locator.hyper-relation"));
314  }
315 
316  NameRelation relation = getNameRelationFromString(hRelation);
317  try {
318  return make_unique<HyperRelationChecker>(pRegex, pExpand, kRegex, kExpand, relation);
319  }
320  catch (const Regex::Error& e) {
321  BOOST_THROW_EXCEPTION(Error("Invalid regex for key-locator.hyper-relation"));
322  }
323  }
324  else {
325  BOOST_THROW_EXCEPTION(Error("Unsupported checker.key-locator"));
326  }
327 }
328 
329 } // namespace validator_config
330 } // namespace v2
331 } // namespace security
332 } // namespace ndn
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
NameRelationChecker(const Name &name, const NameRelation &relation)
Definition: checker.cpp:53
bool checkNames(const Name &pktName, const Name &klName, const shared_ptr< ValidationState > &state) override
Definition: checker.cpp:104
const size_t MIN_SIZE
minimal number of components for Signed Interest
bool checkNameRelation(NameRelation relation, const Name &name1, const Name &name2)
check whether name1 and name2 satisfies relation
bool checkNames(const Name &pktName, const Name &klName, const shared_ptr< ValidationState > &state) override
Definition: checker.cpp:81
NameRelation getNameRelationFromString(const std::string &relationString)
convert relationString to NameRelation
size_t size() const
Get number of components.
Definition: name.hpp:154
Represents an absolute name.
Definition: name.hpp:42
virtual Name expand(const std::string &expand="")
bool checkNames(const Name &pktName, const Name &klName, const shared_ptr< ValidationState > &state) override
Definition: checker.cpp:60
bool match(const Name &name)
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix of the name.
Definition: name.hpp:210
HyperRelationChecker(const std::string &pktNameExpr, const std::string pktNameExpand, const std::string &klNameExpr, const std::string klNameExpand, const NameRelation &hyperRelation)
Definition: checker.cpp:94
bool check(uint32_t pktType, const Name &pktName, const Name &klName, const shared_ptr< ValidationState > &state)
Check if packet name ane KeyLocator satisfy the checker&#39;s conditions.
Definition: checker.cpp:38
virtual bool checkNames(const Name &pktName, const Name &klName, const shared_ptr< ValidationState > &state)=0
RegexTopMatcher Regex
Definition: regex.hpp:31
Name extractIdentityFromKeyName(const Name &keyName)
Extract identity namespace from the key name keyName.
Definition: key.cpp:160
static unique_ptr< Checker > create(const ConfigSection &configSection, const std::string &configFilename)
create a checker from configuration section
Definition: checker.cpp:126