blob: 69e9232b21fdbc4189ce72d4f816bc16e91aff5b [file] [log] [blame]
Yingdi Yu0eee6002014-02-11 15:54:17 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 * Yingdi Yu
5 *
6 * BSD license, See the LICENSE file for more information
7 *
8 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
9 */
10
11#include "sync-validator.h"
12#include "sync-logging.h"
13#include <ndn-cpp-dev/security/certificate-cache-ttl.hpp>
14#include <queue>
15
16using namespace ndn;
Yingdi Yu0eee6002014-02-11 15:54:17 -080017
18INIT_LOGGER ("SyncValidator");
19
20namespace Sync {
21
Yingdi Yu68bc51a2014-03-25 16:02:12 -070022using ndn::shared_ptr;
23
Yingdi Yu0eee6002014-02-11 15:54:17 -080024const shared_ptr<CertificateCache> SyncValidator::DefaultCertificateCache = shared_ptr<CertificateCache>();
25const shared_ptr<SecRuleRelative> SyncValidator::DefaultDataRule = shared_ptr<SecRuleRelative>();
26
27SyncValidator::SyncValidator(const Name& prefix,
28 const IdentityCertificate& anchor,
Yingdi Yua873d642014-04-15 21:31:33 -070029 Face& face,
Yingdi Yu3da10fe2014-02-27 16:37:34 -080030 const PublishCertCallback& publishCertCallback,
Yingdi Yu0eee6002014-02-11 15:54:17 -080031 shared_ptr<SecRuleRelative> rule,
Yingdi Yua873d642014-04-15 21:31:33 -070032 shared_ptr<CertificateCache> certificateCache,
Yingdi Yu0eee6002014-02-11 15:54:17 -080033 const int stepLimit)
34 : Validator(face)
35 , m_prefix(prefix)
36 , m_anchor(anchor)
37 , m_stepLimit(stepLimit)
38 , m_certificateCache(certificateCache)
Yingdi Yu3da10fe2014-02-27 16:37:34 -080039 , m_publishCertCallback(publishCertCallback)
Yingdi Yu0eee6002014-02-11 15:54:17 -080040 , m_dataRule(rule)
41{
Yingdi Yu0eee6002014-02-11 15:54:17 -080042 if(!static_cast<bool>(m_certificateCache))
Yingdi Yua873d642014-04-15 21:31:33 -070043 m_certificateCache = make_shared<CertificateCacheTtl>(m_face.ioService());
Yingdi Yu0eee6002014-02-11 15:54:17 -080044
45 Name certPrefix = prefix;
Yingdi Yu3da10fe2014-02-27 16:37:34 -080046 certPrefix.append("CHRONOS-INTRO-CERT");
Yingdi Yua873d642014-04-15 21:31:33 -070047 m_prefixId = m_face.setInterestFilter(certPrefix,
48 bind(&SyncValidator::onCertInterest, this, _1, _2),
Yingdi Yu3da10fe2014-02-27 16:37:34 -080049 bind(&SyncValidator::onCertRegisterFailed, this, _1, _2));
Yingdi Yu0eee6002014-02-11 15:54:17 -080050
51 setAnchor(m_anchor);
52}
53
54void
55SyncValidator::deriveTrustNodes()
56{
Yingdi Yu68bc51a2014-03-25 16:02:12 -070057 std::queue<Name> nodeQueue;
Yingdi Yu0eee6002014-02-11 15:54:17 -080058
59 // Clear existing trust nodes.
60 m_trustedNodes.clear();
61
62 // Add the trust anchor.
63 IntroNode origin(m_anchor);
64 m_trustedNodes[origin.name()] = m_anchor.getPublicKeyInfo();
65 nodeQueue.push(origin.name());
66
67 // BFS trusted nodes.
68 while(!nodeQueue.empty())
69 {
70 // Get next trusted node to process.
71 Nodes::const_iterator it = m_introNodes.find(nodeQueue.front());
72 const PublicKey& publicKey = m_trustedNodes[nodeQueue.front()];
73
74 if(it != m_introNodes.end())
75 {
76 // If the trusted node exists in the graph.
77 IntroNode::const_iterator eeIt = it->second.introduceeBegin();
78 IntroNode::const_iterator eeEnd = it->second.introduceeEnd();
79 for(; eeIt != eeEnd; eeIt++)
80 {
81 // Check the nodes introduced by the trusted node.
82 Edges::const_iterator edgeIt = m_introCerts.find(*eeIt);
Yingdi Yua873d642014-04-15 21:31:33 -070083 if(edgeIt != m_introCerts.end()
Yingdi Yu3da10fe2014-02-27 16:37:34 -080084 && m_trustedNodes.find(edgeIt->second.getIntroduceeCertName()) == m_trustedNodes.end()
Yingdi Yu0eee6002014-02-11 15:54:17 -080085 && verifySignature(edgeIt->second, publicKey))
86 {
87 // If the introduced node can be validated, add it into trusted node set and the node queue.
Yingdi Yu3da10fe2014-02-27 16:37:34 -080088 m_trustedNodes[edgeIt->second.getIntroduceeCertName()] = edgeIt->second.getIntroduceeCert().getPublicKeyInfo();
89 nodeQueue.push(edgeIt->second.getIntroduceeCertName());
Yingdi Yu0eee6002014-02-11 15:54:17 -080090 }
91 }
92 }
93 nodeQueue.pop();
94 }
95}
96
97void
Yingdi Yua873d642014-04-15 21:31:33 -070098SyncValidator::checkPolicy (const Data& data,
99 int stepCount,
100 const OnDataValidated& onValidated,
Yingdi Yu0eee6002014-02-11 15:54:17 -0800101 const OnDataValidationFailed& onValidationFailed,
102 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
103{
104 if(m_stepLimit == stepCount)
Yingdi Yua873d642014-04-15 21:31:33 -0700105 return onValidationFailed(data.shared_from_this(),
Yingdi Yu0eee6002014-02-11 15:54:17 -0800106 "Maximum steps of validation reached: " + data.getName().toUri());
107
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800108 if(m_prefix.isPrefixOf(data.getName()) || (static_cast<bool>(m_dataRule) && m_dataRule->satisfy(data)))
Yingdi Yu0eee6002014-02-11 15:54:17 -0800109 {
110 try
111 {
112 SignatureSha256WithRsa sig(data.getSignature());
113 Name keyLocatorName = sig.getKeyLocator().getName();
114
115 TrustNodes::const_iterator it = m_trustedNodes.find(keyLocatorName);
116 if(m_trustedNodes.end() != it)
117 {
118 if(verifySignature(data, sig, it->second))
119 return onValidated(data.shared_from_this());
120 else
Yingdi Yua873d642014-04-15 21:31:33 -0700121 return onValidationFailed(data.shared_from_this(),
Yingdi Yu0eee6002014-02-11 15:54:17 -0800122 "Cannot verify signature: " + data.getName().toUri());
123 }
124 else
125 {
Yingdi Yua873d642014-04-15 21:31:33 -0700126 _LOG_DEBUG("I am: " << m_anchor.getName().get(0).toEscapedString() << " for " << data.getName());
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800127
Yingdi Yu0eee6002014-02-11 15:54:17 -0800128 Name interestName = m_prefix;
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800129 interestName.append("CHRONOS-INTRO-CERT").append(keyLocatorName.wireEncode());
Yingdi Yu0eee6002014-02-11 15:54:17 -0800130 Interest interest(interestName);
Yingdi Yu6e1c9cd2014-03-25 10:26:54 -0700131 interest.setInterestLifetime(time::milliseconds(500));
Yingdi Yu0eee6002014-02-11 15:54:17 -0800132
Yingdi Yua873d642014-04-15 21:31:33 -0700133 OnDataValidated onKeyValidated = bind(&SyncValidator::onCertificateValidated, this,
Yingdi Yu0eee6002014-02-11 15:54:17 -0800134 _1, data.shared_from_this(), onValidated, onValidationFailed);
Yingdi Yu0eee6002014-02-11 15:54:17 -0800135
Yingdi Yua873d642014-04-15 21:31:33 -0700136 OnDataValidationFailed onKeyValidationFailed = bind(&SyncValidator::onCertificateValidationFailed, this,
137 _1, _2, data.shared_from_this(), onValidationFailed);
138
139 shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(interest,
Yingdi Yu0eee6002014-02-11 15:54:17 -0800140 onKeyValidated,
141 onKeyValidationFailed,
142 1,
143 stepCount + 1);
144 nextSteps.push_back(nextStep);
145
146 return;
147 }
148 }
149 catch(SignatureSha256WithRsa::Error& e)
150 {
Yingdi Yua873d642014-04-15 21:31:33 -0700151 return onValidationFailed(data.shared_from_this(),
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700152 "Not SignatureSha256WithRsa signature: " + std::string(e.what()));
Yingdi Yu0eee6002014-02-11 15:54:17 -0800153 }
154 catch(KeyLocator::Error& e)
155 {
156 return onValidationFailed(data.shared_from_this(),
157 "Key Locator is not a name: " + data.getName().toUri());
158 }
159 }
Yingdi Yu0eee6002014-02-11 15:54:17 -0800160 else
161 return onValidationFailed(data.shared_from_this(),
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800162 "No rule or rule is not satisfied: " + data.getName().toUri());
Yingdi Yu0eee6002014-02-11 15:54:17 -0800163}
164
165void
Yingdi Yua873d642014-04-15 21:31:33 -0700166SyncValidator::checkPolicy (const Interest& interest,
167 int stepCount,
168 const OnInterestValidated& onValidated,
Yingdi Yu0eee6002014-02-11 15:54:17 -0800169 const OnInterestValidationFailed& onValidationFailed,
170 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
171{
172 onValidationFailed(interest.shared_from_this(), "No policy for signed interest checking");
173}
174
175void
Yingdi Yua873d642014-04-15 21:31:33 -0700176SyncValidator::onCertificateValidated(const shared_ptr<const Data>& signCertificate,
177 const shared_ptr<const Data>& data,
178 const OnDataValidated& onValidated,
Yingdi Yu0eee6002014-02-11 15:54:17 -0800179 const OnDataValidationFailed& onValidationFailed)
180{
181 try
182 {
183 IntroCertificate introCert(*signCertificate);
184 addParticipant(introCert);
Yingdi Yua873d642014-04-15 21:31:33 -0700185
Yingdi Yu0eee6002014-02-11 15:54:17 -0800186 if(verifySignature(*data, introCert.getIntroduceeCert().getPublicKeyInfo()))
187 return onValidated(data);
188 else
Yingdi Yua873d642014-04-15 21:31:33 -0700189 return onValidationFailed(data,
Yingdi Yu0eee6002014-02-11 15:54:17 -0800190 "Cannot verify signature: " + data->getName().toUri());
191 }
192 catch(IntroCertificate::Error& e)
193 {
Yingdi Yua873d642014-04-15 21:31:33 -0700194 return onValidationFailed(data,
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700195 "Intro cert decoding error: " + std::string(e.what()));
Yingdi Yu0eee6002014-02-11 15:54:17 -0800196 }
197}
198
199void
Yingdi Yua873d642014-04-15 21:31:33 -0700200SyncValidator::onCertificateValidationFailed(const shared_ptr<const Data>& signCertificate,
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700201 const std::string& failureInfo,
Yingdi Yua873d642014-04-15 21:31:33 -0700202 const shared_ptr<const Data>& data,
Yingdi Yu0eee6002014-02-11 15:54:17 -0800203 const OnDataValidationFailed& onValidationFailed)
204{
205 onValidationFailed(data, failureInfo);
206}
207
208void
209SyncValidator::onCertInterest(const Name& prefix, const Interest& interest)
210{
Yingdi Yua873d642014-04-15 21:31:33 -0700211 Name name = interest.getName();
Yingdi Yu0eee6002014-02-11 15:54:17 -0800212 Edges::const_iterator it = m_introCerts.begin();
213 for(; it != m_introCerts.end(); it++)
214 {
215 if(name.isPrefixOf(it->first))
216 {
Yingdi Yua873d642014-04-15 21:31:33 -0700217 m_face.put(it->second);
Yingdi Yu0eee6002014-02-11 15:54:17 -0800218 return;
219 }
220 }
221}
222
223void
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700224SyncValidator::onCertRegisterFailed(const Name& prefix, const std::string& msg)
Yingdi Yu0eee6002014-02-11 15:54:17 -0800225{
226 _LOG_DEBUG("SyncValidator::onCertRegisterFailed: " << msg);
227}
228
229} // namespace Sync