blob: 00c92c83ccecd395618edf9d404241c0418d67dd [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#ifndef SYNC_VALIDATOR_H
12#define SYNC_VALIDATOR_H
13
14#include "sync-intro-certificate.h"
15#include <ndn-cpp-dev/security/validator.hpp>
16#include <ndn-cpp-dev/security/key-chain.hpp>
17#include <ndn-cpp-dev/security/sec-rule-relative.hpp>
18#include <ndn-cpp-dev/security/certificate-cache.hpp>
19#include <map>
20
21namespace Sync {
22
23class SyncValidator : public ndn::Validator
24{
25public:
Yingdi Yu3da10fe2014-02-27 16:37:34 -080026 typedef ndn::function< void (const uint8_t*, size_t, int) > PublishCertCallback;
27
Yingdi Yu0eee6002014-02-11 15:54:17 -080028 struct Error : public ndn::Validator::Error { Error(const std::string &what) : ndn::Validator::Error(what) {} };
29
30 static const ndn::shared_ptr<ndn::CertificateCache> DefaultCertificateCache;
31 static const ndn::shared_ptr<ndn::SecRuleRelative> DefaultDataRule;
32
33 SyncValidator(const ndn::Name& prefix,
34 const ndn::IdentityCertificate& anchor,
35 ndn::shared_ptr<ndn::Face> face,
Yingdi Yu3da10fe2014-02-27 16:37:34 -080036 const PublishCertCallback& publishCertCallback,
Yingdi Yu0eee6002014-02-11 15:54:17 -080037 ndn::shared_ptr<ndn::SecRuleRelative> rule = DefaultDataRule,
38 ndn::shared_ptr<ndn::CertificateCache> certificateCache = DefaultCertificateCache,
39 const int stepLimit = 10);
40
41 virtual
42 ~SyncValidator()
43 {
44 m_face->unsetInterestFilter(m_prefixId);
45 }
46
47 /**
48 * @brief Set the trust anchor
49 *
50 * The anchor should be the participant's own certificate.
51 * This anchor node is the origin of the derived trust graph.
52 * Once the new anchor is set, derive the TrustNode set.
53 *
54 * @param anchor.
55 */
56 inline void
57 setAnchor(const ndn::IdentityCertificate& anchor);
58
59 /**
60 * @brief Add a node into the trust graph.
61 *
62 * The method also create an edge from trust anchor to the node.
63 *
64 * @param introducee.
65 * @return IntroCertificate for the introducee.
66 */
67 inline ndn::shared_ptr<const IntroCertificate>
68 addParticipant(const ndn::IdentityCertificate& introducee);
69
70 /**
71 * @brief Add an edge into the trust graph.
72 *
73 * Create nodes if it is one of the edge's ends and does not exist in the graph.
74 *
75 * @param introCert.
76 */
77 inline void
78 addParticipant(const IntroCertificate& introCert);
79
Yingdi Yu3da10fe2014-02-27 16:37:34 -080080 inline void
81 getIntroCertNames(std::vector<ndn::Name>& list);
82
Yingdi Yuaed0f3e2014-02-28 14:54:16 -080083 inline const IntroCertificate&
84 getIntroCertificate(const ndn::Name& name);
85
Yingdi Yu0eee6002014-02-11 15:54:17 -080086#ifdef _TEST
87 bool
88 canTrust(const ndn::Name& certName)
89 {
90 return (m_trustedNodes.find(certName.getPrefix(-1)) != m_trustedNodes.end());
91 }
92#endif //_DEBUG
93
94protected:
95 /***********************
96 * From ndn::Validator *
97 ***********************/
98 virtual void
99 checkPolicy (const ndn::Data& data,
100 int stepCount,
101 const ndn::OnDataValidated& onValidated,
102 const ndn::OnDataValidationFailed& onValidationFailed,
103 std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
104
105 virtual void
106 checkPolicy (const ndn::Interest& interest,
107 int stepCount,
108 const ndn::OnInterestValidated& onValidated,
109 const ndn::OnInterestValidationFailed& onValidationFailed,
110 std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
111private:
112 void
113 deriveTrustNodes();
114
115
116 void
117 onCertificateValidated(const ndn::shared_ptr<const ndn::Data>& signCertificate,
118 const ndn::shared_ptr<const ndn::Data>& data,
119 const ndn::OnDataValidated& onValidated,
120 const ndn::OnDataValidationFailed& onValidationFailed);
121
122 void
123 onCertificateValidationFailed(const ndn::shared_ptr<const ndn::Data>& signCertificate,
124 const std::string& failureInfo,
125 const ndn::shared_ptr<const ndn::Data>& data,
126 const ndn::OnDataValidationFailed& onValidationFailed);
127
128 void
129 onCertInterest (const ndn::Name& prefix, const ndn::Interest& interest);
130
131 void
132 onCertRegisterFailed(const ndn::Name& prefix, const std::string& msg);
133
134private:
135 class IntroNode;
136
137 // Syncprefix
138 ndn::Name m_prefix;
139
140 // The map
141 typedef std::map<const ndn::Name, IntroNode> Nodes;
142 typedef std::map<const ndn::Name, IntroCertificate> Edges;
143 Nodes m_introNodes;
144 Edges m_introCerts;
145
146 // The derived trust info
147 typedef std::map<const ndn::Name, ndn::PublicKey> TrustNodes;
148 ndn::IdentityCertificate m_anchor;
149 TrustNodes m_trustedNodes;
150
151 // others
152 int m_stepLimit;
153 ndn::shared_ptr<ndn::CertificateCache> m_certificateCache;
154 ndn::KeyChain m_keychain;
155 const ndn::RegisteredPrefixId* m_prefixId;
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800156 PublishCertCallback m_publishCertCallback;
Yingdi Yu0eee6002014-02-11 15:54:17 -0800157 ndn::shared_ptr<ndn::SecRuleRelative> m_dataRule;
158
159 class IntroNode
160 {
161 public:
162 typedef std::vector<ndn::Name>::const_iterator const_iterator;
163
164 IntroNode()
165 {}
166
167 IntroNode(const ndn::IdentityCertificate& idCert)
168 : m_nodeName(idCert.getName().getPrefix(-1))
169 {}
170
171 IntroNode(const IntroCertificate& introCert, bool isIntroducer)
172 {
173 if(isIntroducer)
174 {
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800175 m_nodeName = introCert.getIntroducerCertName();
Yingdi Yu0eee6002014-02-11 15:54:17 -0800176 m_introduceeCerts.push_back(introCert.getName());
177 }
178 else
179 {
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800180 m_nodeName = introCert.getIntroduceeCertName();
Yingdi Yu0eee6002014-02-11 15:54:17 -0800181 m_introducerCerts.push_back(introCert.getName());
182 }
183 }
184
185 ~IntroNode()
186 {}
187
188 const ndn::Name&
189 name() const
190 {
191 return m_nodeName;
192 }
193
194 const_iterator
195 introducerBegin() const
196 {
197 return m_introducerCerts.begin();
198 }
199
200 const_iterator
201 introducerEnd() const
202 {
203 return m_introducerCerts.end();
204 }
205
206 const_iterator
207 introduceeBegin() const
208 {
209 return m_introduceeCerts.begin();
210 }
211
212 const_iterator
213 introduceeEnd() const
214 {
215 return m_introduceeCerts.end();
216 }
217
218 void
219 addIntroCertAsIntroducer(const ndn::Name& introCertName)
220 {
221 if(std::find(m_introduceeCerts.begin(), m_introduceeCerts.end(), introCertName) == m_introduceeCerts.end())
222 m_introduceeCerts.push_back(introCertName);
223 }
224
225 void
226 addIntroCertAsIntroducee(const ndn::Name& introCertName)
227 {
228 if(std::find(m_introducerCerts.begin(), m_introducerCerts.end(), introCertName) == m_introducerCerts.end())
229 m_introducerCerts.push_back(introCertName);
230 }
231
232 private:
233 ndn::Name m_nodeName;
234 std::vector<ndn::Name> m_introducerCerts;
235 std::vector<ndn::Name> m_introduceeCerts;
236 };
237
238};
239
240inline void
241SyncValidator::setAnchor(const ndn::IdentityCertificate& anchor)
242{
243 m_anchor = anchor;
244
245 // Add anchor into trust graph if it does not exist.
246 IntroNode origin(m_anchor);
247 Nodes::const_iterator nodeIt = m_introNodes.find(origin.name());
248 if(nodeIt == m_introNodes.end())
249 m_introNodes[origin.name()] = origin;
250
251 deriveTrustNodes();
252}
253
254inline void
255SyncValidator::addParticipant(const IntroCertificate& introCert)
256{
257 // Check if the edge has been added before.
258 ndn::Name certName = introCert.getName();
259 Edges::const_iterator edgeIt = m_introCerts.find(certName);
260 if(edgeIt != m_introCerts.end())
261 return; // the edge has been added before.
262
263 m_introCerts[certName] = introCert;
264
265 // Check if the introducer has been added.
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800266 Nodes::iterator nodeIt = m_introNodes.find(introCert.getIntroducerCertName());
Yingdi Yu0eee6002014-02-11 15:54:17 -0800267 if(nodeIt == m_introNodes.end())
268 {
269 IntroNode node(introCert, true);
270 m_introNodes[node.name()] = node;
271 }
272 else
273 nodeIt->second.addIntroCertAsIntroducer(certName);
274
275 // Check if the introducee has been added.
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800276 nodeIt = m_introNodes.find(introCert.getIntroduceeCertName());
Yingdi Yu0eee6002014-02-11 15:54:17 -0800277 if(nodeIt == m_introNodes.end())
278 {
279 IntroNode node(introCert, false);
280 m_introNodes[node.name()] = node;
281 }
282 else
283 nodeIt->second.addIntroCertAsIntroducee(certName);
284
285 // Check if the introducer is one of the trusted nodes.
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800286 TrustNodes::const_iterator trustNodeIt = m_trustedNodes.find(introCert.getIntroducerCertName());
Yingdi Yu0eee6002014-02-11 15:54:17 -0800287 if(trustNodeIt != m_trustedNodes.end() && verifySignature(introCert, trustNodeIt->second))
288 // If the introducee, add it into trusted node set.
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800289 m_trustedNodes[introCert.getIntroduceeCertName()] = introCert.getIntroduceeCert().getPublicKeyInfo();
Yingdi Yu0eee6002014-02-11 15:54:17 -0800290}
291
292inline ndn::shared_ptr<const IntroCertificate>
293SyncValidator::addParticipant(const ndn::IdentityCertificate& introducee)
294{
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800295 ndn::shared_ptr<IntroCertificate> introCert
296 = ndn::shared_ptr<IntroCertificate>(new IntroCertificate(m_prefix, introducee, m_anchor.getName().getPrefix(-1)));
Yingdi Yu0eee6002014-02-11 15:54:17 -0800297
298 m_keychain.sign(*introCert, m_anchor.getName());
299
300 addParticipant(*introCert);
301
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800302 // Publish certificate as normal data.
303 ndn::Block block = introCert->wireEncode();
304 m_publishCertCallback(block.wire(), block.size(), 1000);
305
Yingdi Yu0eee6002014-02-11 15:54:17 -0800306 return introCert;
307}
308
Yingdi Yu3da10fe2014-02-27 16:37:34 -0800309inline void
310SyncValidator::getIntroCertNames(std::vector<ndn::Name>& list)
311{
312 Edges::const_iterator it = m_introCerts.begin();
313 Edges::const_iterator end = m_introCerts.end();
314 for(; it != end; it++)
315 list.push_back(it->first);
316}
317
Yingdi Yuaed0f3e2014-02-28 14:54:16 -0800318inline const IntroCertificate&
319SyncValidator::getIntroCertificate(const ndn::Name& name)
320{
321 Edges::const_iterator it = m_introCerts.find(name);
322 if(it != m_introCerts.end())
323 return it->second;
324 else
325 throw Error("No cert");
326}
327
Yingdi Yu0eee6002014-02-11 15:54:17 -0800328} // namespace Sync
329
330#endif //SYNC_VALIDATOR_H