blob: f2c05bb08ad5d52745d330c271f731f9ff456b74 [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,
29 shared_ptr<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,
32 shared_ptr<CertificateCache> certificateCache,
33 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{
42 if(!static_cast<bool>(face))
43 throw Error("Face is not set!");
44
45 if(!static_cast<bool>(m_certificateCache))
46 m_certificateCache = make_shared<CertificateCacheTtl>(m_face->ioService());
47
48 Name certPrefix = prefix;
Yingdi Yu3da10fe2014-02-27 16:37:34 -080049 certPrefix.append("CHRONOS-INTRO-CERT");
50 m_prefixId = m_face->setInterestFilter(certPrefix,
51 bind(&SyncValidator::onCertInterest, this, _1, _2),
52 bind(&SyncValidator::onCertRegisterFailed, this, _1, _2));
Yingdi Yu0eee6002014-02-11 15:54:17 -080053
54 setAnchor(m_anchor);
55}
56
57void
58SyncValidator::deriveTrustNodes()
59{
Yingdi Yu68bc51a2014-03-25 16:02:12 -070060 std::queue<Name> nodeQueue;
Yingdi Yu0eee6002014-02-11 15:54:17 -080061
62 // Clear existing trust nodes.
63 m_trustedNodes.clear();
64
65 // Add the trust anchor.
66 IntroNode origin(m_anchor);
67 m_trustedNodes[origin.name()] = m_anchor.getPublicKeyInfo();
68 nodeQueue.push(origin.name());
69
70 // BFS trusted nodes.
71 while(!nodeQueue.empty())
72 {
73 // Get next trusted node to process.
74 Nodes::const_iterator it = m_introNodes.find(nodeQueue.front());
75 const PublicKey& publicKey = m_trustedNodes[nodeQueue.front()];
76
77 if(it != m_introNodes.end())
78 {
79 // If the trusted node exists in the graph.
80 IntroNode::const_iterator eeIt = it->second.introduceeBegin();
81 IntroNode::const_iterator eeEnd = it->second.introduceeEnd();
82 for(; eeIt != eeEnd; eeIt++)
83 {
84 // Check the nodes introduced by the trusted node.
85 Edges::const_iterator edgeIt = m_introCerts.find(*eeIt);
86 if(edgeIt != m_introCerts.end()
Yingdi Yu3da10fe2014-02-27 16:37:34 -080087 && m_trustedNodes.find(edgeIt->second.getIntroduceeCertName()) == m_trustedNodes.end()
Yingdi Yu0eee6002014-02-11 15:54:17 -080088 && verifySignature(edgeIt->second, publicKey))
89 {
90 // If the introduced node can be validated, add it into trusted node set and the node queue.
Yingdi Yu3da10fe2014-02-27 16:37:34 -080091 m_trustedNodes[edgeIt->second.getIntroduceeCertName()] = edgeIt->second.getIntroduceeCert().getPublicKeyInfo();
92 nodeQueue.push(edgeIt->second.getIntroduceeCertName());
Yingdi Yu0eee6002014-02-11 15:54:17 -080093 }
94 }
95 }
96 nodeQueue.pop();
97 }
98}
99
100void
101SyncValidator::checkPolicy (const Data& data,
102 int stepCount,
103 const OnDataValidated& onValidated,
104 const OnDataValidationFailed& onValidationFailed,
105 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
106{
107 if(m_stepLimit == stepCount)
108 return onValidationFailed(data.shared_from_this(),
109 "Maximum steps of validation reached: " + data.getName().toUri());
110
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800111 if(m_prefix.isPrefixOf(data.getName()) || (static_cast<bool>(m_dataRule) && m_dataRule->satisfy(data)))
Yingdi Yu0eee6002014-02-11 15:54:17 -0800112 {
113 try
114 {
115 SignatureSha256WithRsa sig(data.getSignature());
116 Name keyLocatorName = sig.getKeyLocator().getName();
117
118 TrustNodes::const_iterator it = m_trustedNodes.find(keyLocatorName);
119 if(m_trustedNodes.end() != it)
120 {
121 if(verifySignature(data, sig, it->second))
122 return onValidated(data.shared_from_this());
123 else
124 return onValidationFailed(data.shared_from_this(),
125 "Cannot verify signature: " + data.getName().toUri());
126 }
127 else
128 {
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800129 _LOG_DEBUG("I am: " << m_anchor.getName().get(0).toEscapedString() << " for " << data.getName());
130
Yingdi Yu0eee6002014-02-11 15:54:17 -0800131 Name interestName = m_prefix;
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800132 interestName.append("CHRONOS-INTRO-CERT").append(keyLocatorName.wireEncode());
Yingdi Yu0eee6002014-02-11 15:54:17 -0800133 Interest interest(interestName);
Yingdi Yu6e1c9cd2014-03-25 10:26:54 -0700134 interest.setInterestLifetime(time::milliseconds(500));
Yingdi Yu0eee6002014-02-11 15:54:17 -0800135
136 OnDataValidated onKeyValidated = bind(&SyncValidator::onCertificateValidated, this,
137 _1, data.shared_from_this(), onValidated, onValidationFailed);
138
139 OnDataValidationFailed onKeyValidationFailed = bind(&SyncValidator::onCertificateValidationFailed, this,
140 _1, _2, data.shared_from_this(), onValidationFailed);
141
142 shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(interest,
143 onKeyValidated,
144 onKeyValidationFailed,
145 1,
146 stepCount + 1);
147 nextSteps.push_back(nextStep);
148
149 return;
150 }
151 }
152 catch(SignatureSha256WithRsa::Error& e)
153 {
154 return onValidationFailed(data.shared_from_this(),
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700155 "Not SignatureSha256WithRsa signature: " + std::string(e.what()));
Yingdi Yu0eee6002014-02-11 15:54:17 -0800156 }
157 catch(KeyLocator::Error& e)
158 {
159 return onValidationFailed(data.shared_from_this(),
160 "Key Locator is not a name: " + data.getName().toUri());
161 }
162 }
Yingdi Yu0eee6002014-02-11 15:54:17 -0800163 else
164 return onValidationFailed(data.shared_from_this(),
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800165 "No rule or rule is not satisfied: " + data.getName().toUri());
Yingdi Yu0eee6002014-02-11 15:54:17 -0800166}
167
168void
169SyncValidator::checkPolicy (const Interest& interest,
170 int stepCount,
171 const OnInterestValidated& onValidated,
172 const OnInterestValidationFailed& onValidationFailed,
173 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
174{
175 onValidationFailed(interest.shared_from_this(), "No policy for signed interest checking");
176}
177
178void
179SyncValidator::onCertificateValidated(const shared_ptr<const Data>& signCertificate,
180 const shared_ptr<const Data>& data,
181 const OnDataValidated& onValidated,
182 const OnDataValidationFailed& onValidationFailed)
183{
184 try
185 {
186 IntroCertificate introCert(*signCertificate);
187 addParticipant(introCert);
188
189 if(verifySignature(*data, introCert.getIntroduceeCert().getPublicKeyInfo()))
190 return onValidated(data);
191 else
192 return onValidationFailed(data,
193 "Cannot verify signature: " + data->getName().toUri());
194 }
195 catch(IntroCertificate::Error& e)
196 {
197 return onValidationFailed(data,
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700198 "Intro cert decoding error: " + std::string(e.what()));
Yingdi Yu0eee6002014-02-11 15:54:17 -0800199 }
200}
201
202void
203SyncValidator::onCertificateValidationFailed(const shared_ptr<const Data>& signCertificate,
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700204 const std::string& failureInfo,
Yingdi Yu0eee6002014-02-11 15:54:17 -0800205 const shared_ptr<const Data>& data,
206 const OnDataValidationFailed& onValidationFailed)
207{
208 onValidationFailed(data, failureInfo);
209}
210
211void
212SyncValidator::onCertInterest(const Name& prefix, const Interest& interest)
213{
214 Name name = interest.getName();
215 Edges::const_iterator it = m_introCerts.begin();
216 for(; it != m_introCerts.end(); it++)
217 {
218 if(name.isPrefixOf(it->first))
219 {
220 m_face->put(it->second);
221 return;
222 }
223 }
224}
225
226void
Yingdi Yu68bc51a2014-03-25 16:02:12 -0700227SyncValidator::onCertRegisterFailed(const Name& prefix, const std::string& msg)
Yingdi Yu0eee6002014-02-11 15:54:17 -0800228{
229 _LOG_DEBUG("SyncValidator::onCertRegisterFailed: " << msg);
230}
231
232} // namespace Sync