blob: 257f476ace9d632586bd233fd3a479003001e44c [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 };
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070027
28 CommandInterestValidator(const time::milliseconds& graceInterval = time::milliseconds(static_cast<int>(GRACE_INTERVAL)))
29 : m_graceInterval(graceInterval < time::milliseconds::zero() ?
30 time::milliseconds(static_cast<int>(GRACE_INTERVAL)) : graceInterval)
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080031 {
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080032 }
33
34 virtual
35 ~CommandInterestValidator()
36 {
37 }
38
39 void
40 addInterestRule(const std::string& regex, const IdentityCertificate& certificate);
41
42 void
43 addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey);
44
45protected:
46 virtual void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070047 checkPolicy (const Data& data,
48 int stepCount,
49 const OnDataValidated &onValidated,
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080050 const OnDataValidationFailed &onValidationFailed,
51 std::vector<shared_ptr<ValidationRequest> > &nextSteps)
52 {
Yingdi Yu40587c02014-02-21 16:40:48 -080053 onValidationFailed(data.shared_from_this(), "No policy for data checking");
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080054 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070055
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080056 virtual void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070057 checkPolicy (const Interest& interest,
58 int stepCount,
59 const OnInterestValidated &onValidated,
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080060 const OnInterestValidationFailed &onValidationFailed,
61 std::vector<shared_ptr<ValidationRequest> > &nextSteps);
62private:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070063 time::milliseconds m_graceInterval; //ms
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080064 std::map<Name, PublicKey> m_trustAnchorsForInterest;
65 std::list<SecRuleSpecific> m_trustScopeForInterest;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070066
67 typedef std::map<Name, time::system_clock::TimePoint> LastTimestampMap;
68 LastTimestampMap m_lastTimestamp;
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080069};
70
71inline void
72CommandInterestValidator::addInterestRule(const std::string& regex, const IdentityCertificate& certificate)
73{
74 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificate.getName());
75 addInterestRule(regex, keyName, certificate.getPublicKeyInfo());
76}
77
78inline void
79CommandInterestValidator::addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey)
80{
81 m_trustAnchorsForInterest[keyName] = publicKey;
82 shared_ptr<Regex> interestRegex = make_shared<Regex>(regex);
83 shared_ptr<Regex> signerRegex = Regex::fromName(keyName, true);
84 m_trustScopeForInterest.push_back(SecRuleSpecific(interestRegex, signerRegex));
85}
86
87inline void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070088CommandInterestValidator::checkPolicy (const Interest& interest,
89 int stepCount,
90 const OnInterestValidated &onValidated,
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080091 const OnInterestValidationFailed &onValidationFailed,
92 std::vector<shared_ptr<ValidationRequest> > &nextSteps)
93{
Yingdi Yu40587c02014-02-21 16:40:48 -080094 const Name& interestName = interest.getName();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070095
96 //Prepare
Yingdi Yu40587c02014-02-21 16:40:48 -080097 if (interestName.size() < 4)
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070098 return onValidationFailed(interest.shared_from_this(),
Yingdi Yu40587c02014-02-21 16:40:48 -080099 "Interest is not signed: " + interest.getName().toUri());
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700100
101 Signature signature(interestName[POS_SIG_INFO].blockFromValue(),
Yingdi Yu40587c02014-02-21 16:40:48 -0800102 interestName[POS_SIG_VALUE].blockFromValue());
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700103
Yingdi Yu40587c02014-02-21 16:40:48 -0800104 SignatureSha256WithRsa sig(signature);
105 const Name& keyLocatorName = sig.getKeyLocator().getName();
106 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700107
Yingdi Yu40587c02014-02-21 16:40:48 -0800108 //Check if command is in the trusted scope
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700109 bool inScope = false;
Yingdi Yu40587c02014-02-21 16:40:48 -0800110 for(std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
111 scopeIt != m_trustScopeForInterest.end();
112 ++scopeIt)
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800113 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800114 if(scopeIt->satisfy(interestName, keyName))
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800115 {
Yingdi Yu40587c02014-02-21 16:40:48 -0800116 inScope = true;
117 break;
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800118 }
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800119 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800120 if(inScope == false)
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700121 return onValidationFailed(interest.shared_from_this(),
Yingdi Yu21157162014-02-28 13:02:34 -0800122 "Signer cannot be authorized for the command: " + keyName.toUri());
Yingdi Yu40587c02014-02-21 16:40:48 -0800123
124 //Check if timestamp is valid
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700125 time::system_clock::TimePoint interestTime = time::fromUnixTimestamp(
126 time::milliseconds(interestName.get(POS_TIMESTAMP).toNumber()));
127 time::system_clock::TimePoint currentTime = time::system_clock::now();
128
129 LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
130 if (timestampIt == m_lastTimestamp.end())
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800131 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700132 if (!(currentTime - m_graceInterval <= interestTime &&
133 interestTime <= currentTime + m_graceInterval))
134 {
135 return onValidationFailed(interest.shared_from_this(),
136 "The command is not in grace interval: " + interest.getName().toUri());
137 }
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800138 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700139 else
Yingdi Yu40587c02014-02-21 16:40:48 -0800140 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700141 if(interestTime <= timestampIt->second)
142 return onValidationFailed(interest.shared_from_this(),
Yingdi Yu40587c02014-02-21 16:40:48 -0800143 "The command is outdated: " + interest.getName().toUri());
144 }
145
146 //Check signature
147 if(!Validator::verifySignature(interestName.wireEncode().value(),
148 interestName.wireEncode().value_size() - interestName[-1].size(),
149 sig, m_trustAnchorsForInterest[keyName]))
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700150 return onValidationFailed(interest.shared_from_this(),
Yingdi Yu40587c02014-02-21 16:40:48 -0800151 "Signature cannot be validated: " + interest.getName().toUri());
152
153 //Update timestamp
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700154 if (timestampIt == m_lastTimestamp.end())
155 {
156 m_lastTimestamp[keyName] = interestTime;
157 }
158 else
159 {
160 timestampIt->second = interestTime;
161 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800162
163 return onValidated(interest.shared_from_this());
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800164}
165
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800166} // namespace ndn
167
168#endif // NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP