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