blob: ca65f27030162dd86b30367fc9dd937ea4a8677c [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
Yingdi Yu48e8c0c2014-03-19 12:01:55 -07007#ifndef NDN_UTIL_COMMAND_INTEREST_VALIDATOR_HPP
8#define NDN_UTIL_COMMAND_INTEREST_VALIDATOR_HPP
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -08009
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
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070028 CommandInterestValidator(const time::milliseconds& graceInterval =
29 time::milliseconds(static_cast<int>(GRACE_INTERVAL)))
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070030 : m_graceInterval(graceInterval < time::milliseconds::zero() ?
31 time::milliseconds(static_cast<int>(GRACE_INTERVAL)) : graceInterval)
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080032 {
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080033 }
34
35 virtual
36 ~CommandInterestValidator()
37 {
38 }
39
40 void
41 addInterestRule(const std::string& regex, const IdentityCertificate& certificate);
42
43 void
44 addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey);
45
46protected:
47 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070048 checkPolicy(const Data& data,
49 int stepCount,
50 const OnDataValidated& onValidated,
51 const OnDataValidationFailed& onValidationFailed,
52 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080053 {
Yingdi Yu40587c02014-02-21 16:40:48 -080054 onValidationFailed(data.shared_from_this(), "No policy for data checking");
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080055 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070056
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080057 virtual void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070058 checkPolicy(const Interest& interest,
59 int stepCount,
60 const OnInterestValidated& onValidated,
61 const OnInterestValidationFailed& onValidationFailed,
62 std::vector<shared_ptr<ValidationRequest> >& nextSteps);
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080063private:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070064 time::milliseconds m_graceInterval; //ms
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080065 std::map<Name, PublicKey> m_trustAnchorsForInterest;
66 std::list<SecRuleSpecific> m_trustScopeForInterest;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070067
68 typedef std::map<Name, time::system_clock::TimePoint> LastTimestampMap;
69 LastTimestampMap m_lastTimestamp;
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080070};
71
72inline void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070073CommandInterestValidator::addInterestRule(const std::string& regex,
74 const IdentityCertificate& certificate)
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080075{
76 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificate.getName());
77 addInterestRule(regex, keyName, certificate.getPublicKeyInfo());
78}
79
80inline void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070081CommandInterestValidator::addInterestRule(const std::string& regex,
82 const Name& keyName,
83 const PublicKey& publicKey)
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080084{
85 m_trustAnchorsForInterest[keyName] = publicKey;
86 shared_ptr<Regex> interestRegex = make_shared<Regex>(regex);
87 shared_ptr<Regex> signerRegex = Regex::fromName(keyName, true);
88 m_trustScopeForInterest.push_back(SecRuleSpecific(interestRegex, signerRegex));
89}
90
91inline void
Yingdi Yu48e8c0c2014-03-19 12:01:55 -070092CommandInterestValidator::checkPolicy(const Interest& interest,
93 int stepCount,
94 const OnInterestValidated& onValidated,
95 const OnInterestValidationFailed& onValidationFailed,
96 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -080097{
Yingdi Yu40587c02014-02-21 16:40:48 -080098 const Name& interestName = interest.getName();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070099
100 //Prepare
Yingdi Yu40587c02014-02-21 16:40:48 -0800101 if (interestName.size() < 4)
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700102 return onValidationFailed(interest.shared_from_this(),
Yingdi Yu40587c02014-02-21 16:40:48 -0800103 "Interest is not signed: " + interest.getName().toUri());
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700104
105 Signature signature(interestName[POS_SIG_INFO].blockFromValue(),
Yingdi Yu40587c02014-02-21 16:40:48 -0800106 interestName[POS_SIG_VALUE].blockFromValue());
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700107
Yingdi Yu40587c02014-02-21 16:40:48 -0800108 SignatureSha256WithRsa sig(signature);
109 const Name& keyLocatorName = sig.getKeyLocator().getName();
110 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700111
Yingdi Yu40587c02014-02-21 16:40:48 -0800112 //Check if command is in the trusted scope
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700113 bool isInScope = false;
114 for (std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
Yingdi Yu40587c02014-02-21 16:40:48 -0800115 scopeIt != m_trustScopeForInterest.end();
116 ++scopeIt)
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800117 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700118 if (scopeIt->satisfy(interestName, keyName))
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800119 {
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700120 isInScope = true;
Yingdi Yu40587c02014-02-21 16:40:48 -0800121 break;
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800122 }
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800123 }
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700124
125 if (isInScope == false)
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700126 return onValidationFailed(interest.shared_from_this(),
Yingdi Yu21157162014-02-28 13:02:34 -0800127 "Signer cannot be authorized for the command: " + keyName.toUri());
Yingdi Yu40587c02014-02-21 16:40:48 -0800128
129 //Check if timestamp is valid
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700130 time::system_clock::TimePoint interestTime =
131 time::fromUnixTimestamp(time::milliseconds(interestName.get(POS_TIMESTAMP).toNumber()));
132
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700133 time::system_clock::TimePoint currentTime = time::system_clock::now();
134
135 LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
136 if (timestampIt == m_lastTimestamp.end())
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800137 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700138 if (!(currentTime - m_graceInterval <= interestTime &&
139 interestTime <= currentTime + m_graceInterval))
140 {
141 return onValidationFailed(interest.shared_from_this(),
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700142 "The command is not in grace interval: " +
143 interest.getName().toUri());
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700144 }
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800145 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700146 else
Yingdi Yu40587c02014-02-21 16:40:48 -0800147 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700148 if(interestTime <= timestampIt->second)
149 return onValidationFailed(interest.shared_from_this(),
Yingdi Yu40587c02014-02-21 16:40:48 -0800150 "The command is outdated: " + interest.getName().toUri());
151 }
152
153 //Check signature
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700154 if (!Validator::verifySignature(interestName.wireEncode().value(),
155 interestName.wireEncode().value_size() -
156 interestName[-1].size(),
157 sig, m_trustAnchorsForInterest[keyName]))
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700158 return onValidationFailed(interest.shared_from_this(),
Yingdi Yu40587c02014-02-21 16:40:48 -0800159 "Signature cannot be validated: " + interest.getName().toUri());
160
161 //Update timestamp
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700162 if (timestampIt == m_lastTimestamp.end())
163 {
164 m_lastTimestamp[keyName] = interestTime;
165 }
166 else
167 {
168 timestampIt->second = interestTime;
169 }
Yingdi Yu40587c02014-02-21 16:40:48 -0800170
171 return onValidated(interest.shared_from_this());
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800172}
173
Alexander Afanasyev9cbf70a2014-02-17 18:07:51 -0800174} // namespace ndn
175
Yingdi Yu48e8c0c2014-03-19 12:01:55 -0700176#endif // NDN_UTIL_COMMAND_INTEREST_VALIDATOR_HPP