blob: 21ff8b60d8211a7a776802880ae9c3674a5ea0b5 [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_CONF_KEY_LOCATOR_CHECKER_HPP
25#define NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP
26
27#include "../../common.hpp"
28#include "../../data.hpp"
29#include "../../interest.hpp"
30#include <boost/algorithm/string.hpp>
31
32#include "common.hpp"
33
34namespace ndn {
35namespace security {
36namespace conf {
37
38class KeyLocatorCheckerFactory;
39
40class KeyLocatorChecker
41{
42public:
43 enum Relation
44 {
45 RELATION_EQUAL,
46 RELATION_IS_PREFIX_OF,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070047 RELATION_IS_STRICT_PREFIX_OF
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070048 };
49
50 virtual
51 ~KeyLocatorChecker()
52 {
53 }
54
55 bool
56 check(const Data& data,
57 const KeyLocator& keyLocator,
58 std::string& failInfo)
59 {
60 return check(data.getName(), keyLocator, failInfo);
61 }
62
63 bool
64 check(const Interest& interest,
65 const KeyLocator& keyLocator,
66 std::string& failInfo)
67 {
68 if (interest.getName().size() < 2)
69 {
70 failInfo = "No Signature";
71 return false;
72 }
73
74 Name signedName = interest.getName().getPrefix(-2);
75 return check(signedName, keyLocator, failInfo);
76 }
77
78protected:
79
80 virtual bool
81 check(const Name& packetName,
82 const KeyLocator& keyLocator,
83 std::string& failInfo) = 0;
84
85 bool
86 checkRelation(const Relation& relation, const Name& name1, const Name& name2)
87 {
88 switch (relation)
89 {
90 case RELATION_EQUAL:
91 return (name1 == name2);
92 case RELATION_IS_PREFIX_OF:
93 return name1.isPrefixOf(name2);
94 case RELATION_IS_STRICT_PREFIX_OF:
95 return (name1.isPrefixOf(name2) && name1 != name2);
96 default:
97 return false;
98 }
99 }
100};
101
102class RelationKeyLocatorNameChecker : public KeyLocatorChecker
103{
104public:
105 RelationKeyLocatorNameChecker(const Name& name,
106 const KeyLocatorChecker::Relation& relation)
107 : m_name(name)
108 , m_relation(relation)
109 {
110 }
111
112protected:
113 virtual bool
114 check(const Name& packetName,
115 const KeyLocator& keyLocator,
116 std::string& failInfo)
117 {
118 try
119 {
120 if (checkRelation(m_relation, m_name, keyLocator.getName()))
121 return true;
122
123 failInfo = "KeyLocatorChecker failed!";
124 return false;
125 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700126 catch (KeyLocator::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700127 {
128 failInfo = "KeyLocator does not have name";
129 return false;
130 }
131 }
132
133private:
134 Name m_name;
135 KeyLocatorChecker::Relation m_relation;
136};
137
138class RegexKeyLocatorNameChecker : public KeyLocatorChecker
139{
140public:
141 RegexKeyLocatorNameChecker(const Regex& regex)
142 : m_regex(regex)
143 {
144 }
145
146protected:
147 virtual bool
148 check(const Name& packetName,
149 const KeyLocator& keyLocator,
150 std::string& failInfo)
151 {
152 try
153 {
154 if (m_regex.match(keyLocator.getName()))
155 return true;
156
157 failInfo = "KeyLocatorChecker failed!";
158 return false;
159 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700160 catch (KeyLocator::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700161 {
162 failInfo = "KeyLocator does not have name";
163 return false;
164 }
165 }
166
167private:
168 Regex m_regex;
169};
170
171class HyperKeyLocatorNameChecker : public KeyLocatorChecker
172{
173public:
174 HyperKeyLocatorNameChecker(const std::string& pExpr, const std::string pExpand,
175 const std::string& kExpr, const std::string kExpand,
176 const Relation& hyperRelation)
177 : m_hyperPRegex(new Regex(pExpr, pExpand))
178 , m_hyperKRegex(new Regex(kExpr, kExpand))
179 , m_hyperRelation(hyperRelation)
180 {
181 }
182
183protected:
184 virtual bool
185 check(const Name& packetName,
186 const KeyLocator& keyLocator,
187 std::string& failInfo)
188 {
189 try
190 {
191 if (m_hyperPRegex->match(packetName) &&
192 m_hyperKRegex->match(keyLocator.getName()) &&
193 checkRelation(m_hyperRelation,
194 m_hyperKRegex->expand(),
195 m_hyperPRegex->expand()))
196 return true;
197
198 failInfo = "KeyLocatorChecker failed!";
199 return false;
200 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700201 catch (KeyLocator::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700202 {
203 failInfo = "KeyLocator does not have name";
204 return false;
205 }
206
207 }
208
209private:
210 shared_ptr<Regex> m_hyperPRegex;
211 shared_ptr<Regex> m_hyperKRegex;
212 Relation m_hyperRelation;
213};
214
215
216class KeyLocatorCheckerFactory
217{
218public:
219 static shared_ptr<KeyLocatorChecker>
220 create(const ConfigSection& configSection, const std::string& filename)
221 {
222 ConfigSection::const_iterator propertyIt = configSection.begin();
223
224 // Get checker.key-locator.type
225 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
226 throw Error("Expect <checker.key-locator.type>!");
227
228 std::string type = propertyIt->second.data();
229
230 if (boost::iequals(type, "name"))
231 return createKeyLocatorNameChecker(configSection, filename);
232 else
233 throw Error("Unsupported checker.key-locator.type: " + type);
234 }
235
236private:
237 static shared_ptr<KeyLocatorChecker>
238 createKeyLocatorNameChecker(const ConfigSection& configSection,
239 const std::string& filename)
240 {
241 ConfigSection::const_iterator propertyIt = configSection.begin();
242 propertyIt++;
243
244 if (propertyIt == configSection.end())
245 throw Error("Expect more checker.key-locator properties");
246
247 if (boost::iequals(propertyIt->first, "name"))
248 {
249 Name name;
250 try
251 {
252 name = Name(propertyIt->second.data());
253 }
254 catch (Name::Error& e)
255 {
256 throw Error("Invalid checker.key-locator.name: "
257 + propertyIt->second.data());
258 }
259 propertyIt++;
260
261 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "relation"))
262 throw Error("Expect <checker.key-locator.relation>!");
263
264 std::string relationString = propertyIt->second.data();
265 propertyIt++;
266
267 KeyLocatorChecker::Relation relation;
268 if (boost::iequals(relationString, "equal"))
269 relation = KeyLocatorChecker::RELATION_EQUAL;
270 else if (boost::iequals(relationString, "is-prefix-of"))
271 relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
272 else if (boost::iequals(relationString, "is-strict-prefix-of"))
273 relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
274 else
275 throw Error("Unsupported relation: " + relationString);
276
277 if (propertyIt != configSection.end())
278 throw Error("Expect the end of checker.key-locator!");
279
280 return shared_ptr<RelationKeyLocatorNameChecker>
281 (new RelationKeyLocatorNameChecker(name, relation));
282 }
283 else if (boost::iequals(propertyIt->first, "regex"))
284 {
285 std::string regexString = propertyIt->second.data();
286 propertyIt++;
287
288 if (propertyIt != configSection.end())
289 throw Error("Expect the end of checker.key-locator!");
290
291 try
292 {
293 return shared_ptr<RegexKeyLocatorNameChecker>
294 (new RegexKeyLocatorNameChecker(regexString));
295 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700296 catch (Regex::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700297 {
298 throw Error("Invalid checker.key-locator.regex: " + regexString);
299 }
300 }
301 else if (boost::iequals(propertyIt->first, "hyper-relation"))
302 {
303 const ConfigSection& hSection = propertyIt->second;
304
305 ConfigSection::const_iterator hPropertyIt = hSection.begin();
306
307 // Get k-regex
308 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-regex"))
309 throw Error("Expect <checker.key-locator.hyper-relation.k-regex>!");
310
311 std::string kRegex = hPropertyIt->second.data();
312 hPropertyIt++;
313
314 // Get k-expand
315 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "k-expand"))
316 throw Error("Expect <checker.key-locator.hyper-relation.k-expand>!");
317
318 std::string kExpand = hPropertyIt->second.data();
319 hPropertyIt++;
320
321 // Get h-relation
322 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "h-relation"))
323 throw Error("Expect <checker.key-locator.hyper-relation.h-relation>!");
324
325 std::string hRelation = hPropertyIt->second.data();
326 hPropertyIt++;
327
328 // Get p-regex
329 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-regex"))
330 throw Error("Expect <checker.key-locator.hyper-relation.p-regex>!");
331
332 std::string pRegex = hPropertyIt->second.data();
333 hPropertyIt++;
334
335 // Get p-expand
336 if (hPropertyIt == hSection.end() || !boost::iequals(hPropertyIt->first, "p-expand"))
337 throw Error("Expect <checker.key-locator.hyper-relation.p-expand>!");
338
339 std::string pExpand = hPropertyIt->second.data();
340 hPropertyIt++;
341
342 if (hPropertyIt != hSection.end())
343 throw Error("Expect the end of checker.key-locator.hyper-relation!");
344
345 KeyLocatorChecker::Relation relation;
346 if (boost::iequals(hRelation, "equal"))
347 relation = KeyLocatorChecker::RELATION_EQUAL;
348 else if (boost::iequals(hRelation, "is-prefix-of"))
349 relation = KeyLocatorChecker::RELATION_IS_PREFIX_OF;
350 else if (boost::iequals(hRelation, "is-strict-prefix-of"))
351 relation = KeyLocatorChecker::RELATION_IS_STRICT_PREFIX_OF;
352 else
353 throw Error("Unsupported checker.key-locator.hyper-relation.h-relation: "
354 + hRelation);
355
356 try
357 {
358 return shared_ptr<HyperKeyLocatorNameChecker>
359 (new HyperKeyLocatorNameChecker(pRegex, pExpand,
360 kRegex, kExpand,
361 relation));
362 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700363 catch (Regex::Error& e)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700364 {
365 throw Error("Invalid regex for key-locator.hyper-relation");
366 }
367 }
368 else
369 throw Error("Unsupported checker.key-locator");
370 }
371};
372
373
374} // namespace conf
375} // namespace security
376} // namespace ndn
377
378#endif // NDN_SECURITY_CONF_KEY_LOCATOR_CHECKER_HPP