blob: bb651bc178a3a7421834bbad7e2466bafb8d29b6 [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_CHECKER_HPP
25#define NDN_SECURITY_CONF_CHECKER_HPP
26
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070027#include "common.hpp"
28
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070029#include "key-locator-checker.hpp"
30#include "../../util/io.hpp"
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070031#include "../validator.hpp"
Joao Pereira0b3cac52015-07-02 14:49:49 -040032#include "../identity-certificate.hpp"
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070033
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070034#include <boost/algorithm/string.hpp>
35#include <boost/filesystem.hpp>
36#include <boost/lexical_cast.hpp>
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070037
38namespace ndn {
39namespace security {
40namespace conf {
41
42class Checker
43{
44public:
45 typedef function<void(const shared_ptr<const Interest>&)> OnInterestChecked;
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070046 typedef function<void(const shared_ptr<const Interest>&,
47 const std::string&)> OnInterestCheckFailed;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070048 typedef function<void(const shared_ptr<const Data>&)> OnDataChecked;
49 typedef function<void(const shared_ptr<const Data>&, const std::string&)> OnDataCheckFailed;
50
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070051 enum {
52 INTEREST_SIG_VALUE = -1,
53 INTEREST_SIG_INFO = -2
54 };
55
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070056
57 virtual
58 ~Checker()
59 {
60 }
61
62 /**
63 * @brief check if data satisfies condition defined in the specific checker implementation
64 *
65 * @param data Data packet
66 * @param onValidated Callback function which is called when data is immediately valid
67 * @param onValidationFailed Call function which is called when data is immediately invalid
68 * @return -1 if data is immediately invalid (onValidationFailed has been called)
69 * 1 if data is immediately valid (onValidated has been called)
70 * 0 if further signature verification is needed.
71 */
72 virtual int8_t
73 check(const Data& data,
74 const OnDataChecked& onValidated,
75 const OnDataCheckFailed& onValidationFailed) = 0;
76
77 /**
78 * @brief check if interest satisfies condition defined in the specific checker implementation
79 *
80 * @param interest Interest packet
81 * @param onValidated Callback function which is called when interest is immediately valid
82 * @param onValidationFailed Call function which is called when interest is immediately invalid
83 * @return -1 if interest is immediately invalid (onValidationFailed has been called)
84 * 1 if interest is immediately valid (onValidated has been called)
85 * 0 if further signature verification is needed.
86 */
87 virtual int8_t
88 check(const Interest& interest,
89 const OnInterestChecked& onValidated,
90 const OnInterestCheckFailed& onValidationFailed) = 0;
91};
92
93class CustomizedChecker : public Checker
94{
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070095public:
96 CustomizedChecker(uint32_t sigType,
97 shared_ptr<KeyLocatorChecker> keyLocatorChecker)
98 : m_sigType(sigType)
99 , m_keyLocatorChecker(keyLocatorChecker)
100 {
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700101 switch (sigType)
102 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600103 case tlv::SignatureSha256WithRsa:
104 case tlv::SignatureSha256WithEcdsa:
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700105 {
106 if (!static_cast<bool>(m_keyLocatorChecker))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700107 BOOST_THROW_EXCEPTION(Error("Strong signature requires KeyLocatorChecker"));
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700108
109 return;
110 }
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600111 case tlv::DigestSha256:
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700112 return;
113 default:
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700114 BOOST_THROW_EXCEPTION(Error("Unsupported signature type"));
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700115 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700116 }
117
118 virtual int8_t
119 check(const Data& data,
120 const OnDataChecked& onValidated,
121 const OnDataCheckFailed& onValidationFailed)
122 {
123 return check(data, data.getSignature(), onValidated, onValidationFailed);
124 }
125
126 virtual int8_t
127 check(const Interest& interest,
128 const OnInterestChecked& onValidated,
129 const OnInterestCheckFailed& onValidationFailed)
130 {
Yingdi Yu20a06962014-04-17 12:56:04 -0700131 try
132 {
133 const Name& interestName = interest.getName();
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700134 Signature signature(interestName[Checker::INTEREST_SIG_INFO].blockFromValue(),
135 interestName[Checker::INTEREST_SIG_VALUE].blockFromValue());
Yingdi Yu20a06962014-04-17 12:56:04 -0700136 return check(interest, signature, onValidated, onValidationFailed);
137 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700138 catch (Signature::Error& e)
Yingdi Yu20a06962014-04-17 12:56:04 -0700139 {
Yingdi Yu96e64062014-04-15 19:57:33 -0700140 onValidationFailed(interest.shared_from_this(), "Invalid signature");
Yingdi Yu20a06962014-04-17 12:56:04 -0700141 return -1;
142 }
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600143 catch (tlv::Error& e)
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700144 {
145 onValidationFailed(interest.shared_from_this(), "Cannot decode signature related TLVs");
146 return -1;
147 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700148 }
149
150private:
151 template<class Packet, class OnValidated, class OnFailed>
152 int8_t
153 check(const Packet& packet, const Signature& signature,
154 const OnValidated& onValidated,
155 const OnFailed& onValidationFailed)
156 {
157 if (m_sigType != signature.getType())
158 {
159 onValidationFailed(packet.shared_from_this(),
160 "Signature type does not match: " +
161 boost::lexical_cast<std::string>(m_sigType) +
162 "!=" +
163 boost::lexical_cast<std::string>(signature.getType()));
164 return -1;
165 }
166
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600167 if (signature.getType() == tlv::DigestSha256)
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700168 return 0;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700169
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700170 try
171 {
172 switch (signature.getType())
173 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600174 case tlv::SignatureSha256WithRsa:
175 case tlv::SignatureSha256WithEcdsa:
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700176 {
Yingdi Yu4a557052014-07-09 16:40:37 -0700177 if (!signature.hasKeyLocator()) {
178 onValidationFailed(packet.shared_from_this(),
179 "Missing KeyLocator in SignatureInfo");
180 }
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700181 break;
182 }
183 default:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700184 {
185 onValidationFailed(packet.shared_from_this(),
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700186 "Unsupported signature type: " +
187 boost::lexical_cast<std::string>(signature.getType()));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700188 return -1;
189 }
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700190 }
191 }
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700192 catch (KeyLocator::Error& e)
193 {
194 onValidationFailed(packet.shared_from_this(),
195 "Cannot decode KeyLocator");
196 return -1;
197 }
Junxiao Shic2b8d242014-11-04 08:35:29 -0700198 catch (tlv::Error& e)
199 {
200 onValidationFailed(packet.shared_from_this(),
201 "Cannot decode signature");
202 return -1;
203 }
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700204
205 std::string failInfo;
Yingdi Yu4a557052014-07-09 16:40:37 -0700206 if (m_keyLocatorChecker->check(packet, signature.getKeyLocator(), failInfo))
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700207 return 0;
208 else
209 {
210 onValidationFailed(packet.shared_from_this(), failInfo);
211 return -1;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700212 }
213 }
214
215private:
216 uint32_t m_sigType;
217 shared_ptr<KeyLocatorChecker> m_keyLocatorChecker;
218};
219
220class HierarchicalChecker : public CustomizedChecker
221{
222public:
Alexander Afanasyeva4297a62014-06-19 13:29:34 -0700223 explicit
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700224 HierarchicalChecker(uint32_t sigType)
225 : CustomizedChecker(sigType,
226 make_shared<HyperKeyLocatorNameChecker>("^(<>*)$", "\\1",
227 "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
228 "\\1\\2",
229 KeyLocatorChecker::RELATION_IS_PREFIX_OF))
230 {
231 }
232};
233
234class FixedSignerChecker : public Checker
235{
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700236public:
237 FixedSignerChecker(uint32_t sigType,
238 const std::vector<shared_ptr<IdentityCertificate> >& signers)
239 : m_sigType(sigType)
240 {
241 for (std::vector<shared_ptr<IdentityCertificate> >::const_iterator it = signers.begin();
242 it != signers.end(); it++)
243 m_signers[(*it)->getName().getPrefix(-1)] = (*it);
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700244
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600245 if (sigType != tlv::SignatureSha256WithRsa &&
246 sigType != tlv::SignatureSha256WithEcdsa)
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700247 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700248 BOOST_THROW_EXCEPTION(Error("FixedSigner is only meaningful for strong signature type"));
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700249 }
250
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700251 }
252
253 virtual int8_t
254 check(const Data& data,
255 const OnDataChecked& onValidated,
256 const OnDataCheckFailed& onValidationFailed)
257 {
258 return check(data, data.getSignature(), onValidated, onValidationFailed);
259 }
260
261 virtual int8_t
262 check(const Interest& interest,
263 const OnInterestChecked& onValidated,
264 const OnInterestCheckFailed& onValidationFailed)
265 {
Yingdi Yu20a06962014-04-17 12:56:04 -0700266 try
267 {
268 const Name& interestName = interest.getName();
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700269 Signature signature(interestName[Checker::INTEREST_SIG_INFO].blockFromValue(),
270 interestName[Checker::INTEREST_SIG_VALUE].blockFromValue());
Yingdi Yu20a06962014-04-17 12:56:04 -0700271 return check(interest, signature, onValidated, onValidationFailed);
272 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700273 catch (Signature::Error& e)
Yingdi Yu20a06962014-04-17 12:56:04 -0700274 {
Yingdi Yu96e64062014-04-15 19:57:33 -0700275 onValidationFailed(interest.shared_from_this(), "Invalid signature");
Yingdi Yu20a06962014-04-17 12:56:04 -0700276 return -1;
277 }
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600278 catch (tlv::Error& e)
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700279 {
280 onValidationFailed(interest.shared_from_this(), "Cannot decode signature related TLVs");
281 return -1;
282 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700283 }
284
285private:
286 template<class Packet, class OnValidated, class OnFailed>
287 int8_t
288 check(const Packet& packet, const Signature& signature,
289 const OnValidated& onValidated,
290 const OnFailed& onValidationFailed)
291 {
292 if (m_sigType != signature.getType())
293 {
294 onValidationFailed(packet.shared_from_this(),
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700295 "Signature type does not match: " +
296 boost::lexical_cast<std::string>(m_sigType) +
297 "!=" +
298 boost::lexical_cast<std::string>(signature.getType()));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700299 return -1;
300 }
301
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600302 if (signature.getType() == tlv::DigestSha256)
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700303 {
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700304 onValidationFailed(packet.shared_from_this(),
305 "FixedSigner does not allow Sha256 signature type");
306 return -1;
307 }
308
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700309 try
310 {
311 switch (signature.getType())
312 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600313 case tlv::SignatureSha256WithRsa:
314 case tlv::SignatureSha256WithEcdsa:
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700315 {
Yingdi Yu4a557052014-07-09 16:40:37 -0700316 if (!signature.hasKeyLocator()) {
317 onValidationFailed(packet.shared_from_this(),
318 "Missing KeyLocator in SignatureInfo");
319 }
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700320 break;
321 }
322 default:
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700323 {
324 onValidationFailed(packet.shared_from_this(),
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700325 "Unsupported signature type: " +
326 boost::lexical_cast<std::string>(signature.getType()));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700327 return -1;
328 }
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700329 }
330
Yingdi Yu4a557052014-07-09 16:40:37 -0700331 const Name& keyLocatorName = signature.getKeyLocator().getName();
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700332
333 if (m_signers.find(keyLocatorName) == m_signers.end())
334 {
335 onValidationFailed(packet.shared_from_this(),
336 "Signer is not in the fixed signer list: " +
337 keyLocatorName.toUri());
338 return -1;
339 }
340
Yingdi Yu4a557052014-07-09 16:40:37 -0700341 if (Validator::verifySignature(packet, signature,
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700342 m_signers[keyLocatorName]->getPublicKeyInfo()))
343 {
344 onValidated(packet.shared_from_this());
345 return 1;
346 }
347 else
348 {
349 onValidationFailed(packet.shared_from_this(),
350 "Signature cannot be validated");
351 return -1;
352 }
353 }
354 catch (KeyLocator::Error& e)
355 {
356 onValidationFailed(packet.shared_from_this(),
357 "KeyLocator does not have name");
358 return -1;
359 }
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600360 catch (tlv::Error& e)
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700361 {
362 onValidationFailed(packet.shared_from_this(),
363 "Cannot decode signature");
364 return -1;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700365 }
366 }
367
368private:
369 typedef std::map<Name, shared_ptr<IdentityCertificate> > SignerList;
370
371 uint32_t m_sigType;
372 SignerList m_signers;
373};
374
375class CheckerFactory
376{
377public:
378 /**
379 * @brief create a checker from configuration file.
380 *
381 * @param configSection The section containing the definition of checker.
382 * @param configFilename The configuration file name.
383 * @return a shared pointer to the created checker.
384 */
385 static shared_ptr<Checker>
386 create(const ConfigSection& configSection, const std::string& configFilename)
387 {
388 ConfigSection::const_iterator propertyIt = configSection.begin();
389
390 // Get checker.type
391 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700392 BOOST_THROW_EXCEPTION(Error("Expect <checker.type>"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700393
394 std::string type = propertyIt->second.data();
395
396 if (boost::iequals(type, "customized"))
397 return createCustomizedChecker(configSection, configFilename);
398 else if (boost::iequals(type, "hierarchical"))
399 return createHierarchicalChecker(configSection, configFilename);
400 else if (boost::iequals(type, "fixed-signer"))
401 return createFixedSignerChecker(configSection, configFilename);
402 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700403 BOOST_THROW_EXCEPTION(Error("Unsupported checker type: " + type));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700404 }
405
406private:
407 static shared_ptr<Checker>
408 createCustomizedChecker(const ConfigSection& configSection,
409 const std::string& configFilename)
410 {
411 ConfigSection::const_iterator propertyIt = configSection.begin();
412 propertyIt++;
413
414 // Get checker.sig-type
415 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700416 BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700417
418 std::string sigType = propertyIt->second.data();
419 propertyIt++;
420
421 // Get checker.key-locator
422 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700423 BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator>"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700424
425 shared_ptr<KeyLocatorChecker> keyLocatorChecker =
426 KeyLocatorCheckerFactory::create(propertyIt->second, configFilename);
427 propertyIt++;
428
429 if (propertyIt != configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700430 BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700431
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700432 return make_shared<CustomizedChecker>(getSigType(sigType), keyLocatorChecker);
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700433 }
434
435 static shared_ptr<Checker>
436 createHierarchicalChecker(const ConfigSection& configSection,
437 const std::string& configFilename)
438 {
439 ConfigSection::const_iterator propertyIt = configSection.begin();
440 propertyIt++;
441
442 // Get checker.sig-type
443 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700444 BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700445
446 std::string sigType = propertyIt->second.data();
447 propertyIt++;
448
449 if (propertyIt != configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700450 BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700451
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700452 return make_shared<HierarchicalChecker>(getSigType(sigType));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700453 }
454
455 static shared_ptr<Checker>
456 createFixedSignerChecker(const ConfigSection& configSection,
457 const std::string& configFilename)
458 {
459 ConfigSection::const_iterator propertyIt = configSection.begin();
460 propertyIt++;
461
462 // Get checker.sig-type
463 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700464 BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700465
466 std::string sigType = propertyIt->second.data();
467 propertyIt++;
468
469 std::vector<shared_ptr<IdentityCertificate> > signers;
470 for (; propertyIt != configSection.end(); propertyIt++)
471 {
472 if (!boost::iequals(propertyIt->first, "signer"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700473 BOOST_THROW_EXCEPTION(Error("Expect <checker.signer> but get <checker." +
474 propertyIt->first + ">"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700475
476 signers.push_back(getSigner(propertyIt->second, configFilename));
477 }
478
479 if (propertyIt != configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700480 BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700481
482 return shared_ptr<FixedSignerChecker>(new FixedSignerChecker(getSigType(sigType),
483 signers));
484 }
485
486 static shared_ptr<IdentityCertificate>
487 getSigner(const ConfigSection& configSection, const std::string& configFilename)
488 {
489 using namespace boost::filesystem;
490
491 ConfigSection::const_iterator propertyIt = configSection.begin();
492
493 // Get checker.signer.type
494 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700495 BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.type>"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700496
497 std::string type = propertyIt->second.data();
498 propertyIt++;
499
500 if (boost::iequals(type, "file"))
501 {
502 // Get checker.signer.file-name
503 if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700504 BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.file-name>"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700505
506 path certfilePath = absolute(propertyIt->second.data(),
507 path(configFilename).parent_path());
508 propertyIt++;
509
510 if (propertyIt != configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700511 BOOST_THROW_EXCEPTION(Error("Expect the end of checker.signer"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700512
513 shared_ptr<IdentityCertificate> idCert
514 = io::load<IdentityCertificate>(certfilePath.c_str());
515
516 if (static_cast<bool>(idCert))
517 return idCert;
518 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700519 BOOST_THROW_EXCEPTION(Error("Cannot read certificate from file: " +
520 certfilePath.native()));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700521 }
522 else if (boost::iequals(type, "base64"))
523 {
524 // Get checker.signer.base64-string
525 if (propertyIt == configSection.end() ||
526 !boost::iequals(propertyIt->first, "base64-string"))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700527 BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.base64-string>"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700528
529 std::stringstream ss(propertyIt->second.data());
530 propertyIt++;
531
532 if (propertyIt != configSection.end())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700533 BOOST_THROW_EXCEPTION(Error("Expect the end of checker.signer"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700534
535 shared_ptr<IdentityCertificate> idCert = io::load<IdentityCertificate>(ss);
536
537 if (static_cast<bool>(idCert))
538 return idCert;
539 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700540 BOOST_THROW_EXCEPTION(Error("Cannot decode certificate from string"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700541 }
542 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700543 BOOST_THROW_EXCEPTION(Error("Unsupported checker.signer type: " + type));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700544 }
545
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700546 static uint32_t
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700547 getSigType(const std::string& sigType)
548 {
549 if (boost::iequals(sigType, "rsa-sha256"))
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600550 return tlv::SignatureSha256WithRsa;
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700551 else if (boost::iequals(sigType, "ecdsa-sha256"))
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600552 return tlv::SignatureSha256WithEcdsa;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700553 else if (boost::iequals(sigType, "sha256"))
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600554 return tlv::DigestSha256;
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700555 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700556 BOOST_THROW_EXCEPTION(Error("Unsupported signature type"));
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700557 }
558};
559
560} // namespace conf
561} // namespace security
562} // namespace ndn
563
Yingdi Yu5ec0ee32014-06-24 16:26:09 -0700564#endif // NDN_SECURITY_CONF_CHECKER_HPP