blob: 8c5ecc384b50dd3549b82c3f3111490962044fe4 [file] [log] [blame]
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * See COPYING for copyright and distribution information.
5 */
6
7#ifndef NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
8#define NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
9
10#include "../security/validator.hpp"
11#include "../security/identity-certificate.hpp"
12#include "../security/sec-rule-specific.hpp"
13
14namespace ndn {
15
16class CommandInterestValidator : public Validator
17{
18public:
19 enum {
20 POS_SIG_VALUE = -1,
21 POS_SIG_INFO = -2,
22 POS_RANDOM_VAL = -3,
23 POS_TIMESTAMP = -4,
24
25 GRACE_INTERVAL = 3000 // ms
26 };
27
28 CommandInterestValidator(int64_t graceInterval = GRACE_INTERVAL/*ms*/)
29 {
30 m_graceInterval = (graceInterval < 0 ? GRACE_INTERVAL : graceInterval);
31 }
32
33 virtual
34 ~CommandInterestValidator()
35 {
36 }
37
38 void
39 addInterestRule(const std::string& regex, const IdentityCertificate& certificate);
40
41 void
42 addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey);
43
44protected:
45 virtual void
46 checkPolicy (const Data& data,
47 int stepCount,
48 const OnDataValidated &onValidated,
49 const OnDataValidationFailed &onValidationFailed,
50 std::vector<shared_ptr<ValidationRequest> > &nextSteps)
51 {
Yingdi Yu40587c02014-02-21 16:40:48 -080052 onValidationFailed(data.shared_from_this(), "No policy for data checking");
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080053 }
54
55 virtual void
56 checkPolicy (const Interest& interest,
57 int stepCount,
58 const OnInterestValidated &onValidated,
59 const OnInterestValidationFailed &onValidationFailed,
60 std::vector<shared_ptr<ValidationRequest> > &nextSteps);
61private:
62 int64_t m_graceInterval; //ms
63 std::map<Name, PublicKey> m_trustAnchorsForInterest;
64 std::list<SecRuleSpecific> m_trustScopeForInterest;
65 std::map<Name, uint64_t> m_lastTimestamp;
66};
67
68inline void
69CommandInterestValidator::addInterestRule(const std::string& regex, const IdentityCertificate& certificate)
70{
71 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificate.getName());
72 addInterestRule(regex, keyName, certificate.getPublicKeyInfo());
73}
74
75inline void
76CommandInterestValidator::addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey)
77{
78 m_trustAnchorsForInterest[keyName] = publicKey;
79 shared_ptr<Regex> interestRegex = make_shared<Regex>(regex);
80 shared_ptr<Regex> signerRegex = Regex::fromName(keyName, true);
81 m_trustScopeForInterest.push_back(SecRuleSpecific(interestRegex, signerRegex));
82}
83
84inline void
85CommandInterestValidator::checkPolicy (const Interest& interest,
86 int stepCount,
87 const OnInterestValidated &onValidated,
88 const OnInterestValidationFailed &onValidationFailed,
89 std::vector<shared_ptr<ValidationRequest> > &nextSteps)
90{
Yingdi Yu40587c02014-02-21 16:40:48 -080091 const Name& interestName = interest.getName();
92
93 //Prepare
94 if (interestName.size() < 4)
95 return onValidationFailed(interest.shared_from_this(),
96 "Interest is not signed: " + interest.getName().toUri());
97
98 Signature signature(interestName[POS_SIG_INFO].blockFromValue(),
99 interestName[POS_SIG_VALUE].blockFromValue());
100
101 SignatureSha256WithRsa sig(signature);
102 const Name& keyLocatorName = sig.getKeyLocator().getName();
103 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
104
105 //Check if command is in the trusted scope
106 bool inScope = false;
107 for(std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
108 scopeIt != m_trustScopeForInterest.end();
109 ++scopeIt)
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800110 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800111 if(scopeIt->satisfy(interestName, keyName))
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800112 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800113 inScope = true;
114 break;
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800115 }
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800116 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800117 if(inScope == false)
118 return onValidationFailed(interest.shared_from_this(),
119 "Signer cannot be authorized for the command: " + interest.getName().toUri());
120
121 //Check if timestamp is valid
122 uint64_t timestamp = interestName.get(POS_TIMESTAMP).toNumber();
123 uint64_t current = static_cast<uint64_t>(time::now()/1000000);
124 std::map<Name, uint64_t>::const_iterator timestampIt = m_lastTimestamp.find(keyName);
125 if(timestampIt == m_lastTimestamp.end())
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800126 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800127 if(timestamp > (current + m_graceInterval) || (timestamp + m_graceInterval) < current)
128 return onValidationFailed(interest.shared_from_this(),
129 "The command is not in grace interval: " + interest.getName().toUri());
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800130 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800131 else
132 {
133 if(m_lastTimestamp[keyName] >= timestamp)
134 return onValidationFailed(interest.shared_from_this(),
135 "The command is outdated: " + interest.getName().toUri());
136 }
137
138 //Check signature
139 if(!Validator::verifySignature(interestName.wireEncode().value(),
140 interestName.wireEncode().value_size() - interestName[-1].size(),
141 sig, m_trustAnchorsForInterest[keyName]))
142 return onValidationFailed(interest.shared_from_this(),
143 "Signature cannot be validated: " + interest.getName().toUri());
144
145 //Update timestamp
146 m_lastTimestamp[keyName] = timestamp;
147
148 return onValidated(interest.shared_from_this());
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800149}
150
151
152} // namespace ndn
153
154#endif // NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP