blob: 03c292b20aa5cf07d00fbee89ba8c25bce4541cd [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;
17using namespace std;
18
19INIT_LOGGER ("SyncValidator");
20
21namespace Sync {
22
23const shared_ptr<CertificateCache> SyncValidator::DefaultCertificateCache = shared_ptr<CertificateCache>();
24const shared_ptr<SecRuleRelative> SyncValidator::DefaultDataRule = shared_ptr<SecRuleRelative>();
25
26SyncValidator::SyncValidator(const Name& prefix,
27 const IdentityCertificate& anchor,
28 shared_ptr<Face> face,
29 shared_ptr<SecRuleRelative> rule,
30 shared_ptr<CertificateCache> certificateCache,
31 const int stepLimit)
32 : Validator(face)
33 , m_prefix(prefix)
34 , m_anchor(anchor)
35 , m_stepLimit(stepLimit)
36 , m_certificateCache(certificateCache)
37 , m_dataRule(rule)
38{
39 if(!static_cast<bool>(face))
40 throw Error("Face is not set!");
41
42 if(!static_cast<bool>(m_certificateCache))
43 m_certificateCache = make_shared<CertificateCacheTtl>(m_face->ioService());
44
45 Name certPrefix = prefix;
46 certPrefix.append("intro-cert");
47 m_prefixId = m_face->setInterestFilter (certPrefix,
48 bind(&SyncValidator::onCertInterest, this, _1, _2),
49 bind(&SyncValidator::onCertRegisterFailed, this, _1, _2));
50
51 setAnchor(m_anchor);
52}
53
54void
55SyncValidator::deriveTrustNodes()
56{
57 queue<Name> nodeQueue;
58
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);
83 if(edgeIt != m_introCerts.end()
84 && m_trustedNodes.find(edgeIt->second.getIntroduceeName()) == m_trustedNodes.end()
85 && verifySignature(edgeIt->second, publicKey))
86 {
87 // If the introduced node can be validated, add it into trusted node set and the node queue.
88 m_trustedNodes[edgeIt->second.getIntroduceeName()] = edgeIt->second.getIntroduceeCert().getPublicKeyInfo();
89 nodeQueue.push(edgeIt->second.getIntroduceeName());
90 }
91 }
92 }
93 nodeQueue.pop();
94 }
95}
96
97void
98SyncValidator::checkPolicy (const Data& data,
99 int stepCount,
100 const OnDataValidated& onValidated,
101 const OnDataValidationFailed& onValidationFailed,
102 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
103{
104 if(m_stepLimit == stepCount)
105 return onValidationFailed(data.shared_from_this(),
106 "Maximum steps of validation reached: " + data.getName().toUri());
107
108 if(m_prefix.isPrefixOf(data.getName()))
109 {
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
121 return onValidationFailed(data.shared_from_this(),
122 "Cannot verify signature: " + data.getName().toUri());
123 }
124 else
125 {
126 Name interestName = m_prefix;
127 interestName.append("intro-cert").append(keyLocatorName.wireEncode());
128 Interest interest(interestName);
129 interest.setInterestLifetime(500);
130
131 OnDataValidated onKeyValidated = bind(&SyncValidator::onCertificateValidated, this,
132 _1, data.shared_from_this(), onValidated, onValidationFailed);
133
134 OnDataValidationFailed onKeyValidationFailed = bind(&SyncValidator::onCertificateValidationFailed, this,
135 _1, _2, data.shared_from_this(), onValidationFailed);
136
137 shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(interest,
138 onKeyValidated,
139 onKeyValidationFailed,
140 1,
141 stepCount + 1);
142 nextSteps.push_back(nextStep);
143
144 return;
145 }
146 }
147 catch(SignatureSha256WithRsa::Error& e)
148 {
149 return onValidationFailed(data.shared_from_this(),
150 "Not SignatureSha256WithRsa signature: " + string(e.what()));
151 }
152 catch(KeyLocator::Error& e)
153 {
154 return onValidationFailed(data.shared_from_this(),
155 "Key Locator is not a name: " + data.getName().toUri());
156 }
157 }
158
159 if(static_cast<bool>(m_dataRule) && m_dataRule->satisfy(data))
160 {
161 try
162 {
163 SignatureSha256WithRsa sig(data.getSignature());
164 Name keyLocatorName = sig.getKeyLocator().getName();
165
166 TrustNodes::const_iterator it = m_trustedNodes.find(keyLocatorName);
167 if(m_trustedNodes.end() != it)
168 {
169 if(verifySignature(data, sig, it->second))
170 return onValidated(data.shared_from_this());
171 else
172 return onValidationFailed(data.shared_from_this(),
173 "Cannot verify signature: " + data.getName().toUri());
174 }
175 else
176 return onValidationFailed(data.shared_from_this(),
177 "Signer cannot be trusted: " + keyLocatorName.toUri());
178 }
179 catch(SignatureSha256WithRsa::Error& e)
180 {
181 return onValidationFailed(data.shared_from_this(),
182 "Not SignatureSha256WithRsa signature: " + string(e.what()));
183 }
184 catch(KeyLocator::Error& e)
185 {
186 return onValidationFailed(data.shared_from_this(),
187 "Key Locator is not a name: " + data.getName().toUri());
188 }
189 }
190 else
191 return onValidationFailed(data.shared_from_this(),
192 "No data rule or rule is not satisfied: " + data.getName().toUri());
193}
194
195void
196SyncValidator::checkPolicy (const Interest& interest,
197 int stepCount,
198 const OnInterestValidated& onValidated,
199 const OnInterestValidationFailed& onValidationFailed,
200 std::vector<shared_ptr<ValidationRequest> >& nextSteps)
201{
202 onValidationFailed(interest.shared_from_this(), "No policy for signed interest checking");
203}
204
205void
206SyncValidator::onCertificateValidated(const shared_ptr<const Data>& signCertificate,
207 const shared_ptr<const Data>& data,
208 const OnDataValidated& onValidated,
209 const OnDataValidationFailed& onValidationFailed)
210{
211 try
212 {
213 IntroCertificate introCert(*signCertificate);
214 addParticipant(introCert);
215
216 if(verifySignature(*data, introCert.getIntroduceeCert().getPublicKeyInfo()))
217 return onValidated(data);
218 else
219 return onValidationFailed(data,
220 "Cannot verify signature: " + data->getName().toUri());
221 }
222 catch(IntroCertificate::Error& e)
223 {
224 return onValidationFailed(data,
225 "Intro cert decoding error: " + string(e.what()));
226 }
227}
228
229void
230SyncValidator::onCertificateValidationFailed(const shared_ptr<const Data>& signCertificate,
231 const string& failureInfo,
232 const shared_ptr<const Data>& data,
233 const OnDataValidationFailed& onValidationFailed)
234{
235 onValidationFailed(data, failureInfo);
236}
237
238void
239SyncValidator::onCertInterest(const Name& prefix, const Interest& interest)
240{
241 Name name = interest.getName();
242 Edges::const_iterator it = m_introCerts.begin();
243 for(; it != m_introCerts.end(); it++)
244 {
245 if(name.isPrefixOf(it->first))
246 {
247 m_face->put(it->second);
248 return;
249 }
250 }
251}
252
253void
254SyncValidator::onCertRegisterFailed(const Name& prefix, const string& msg)
255{
256 _LOG_DEBUG("SyncValidator::onCertRegisterFailed: " << msg);
257}
258
259} // namespace Sync