blob: b3cff00bd943fed14be807e6765a69b32b899401 [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:
26 struct Error : public ndn::Validator::Error { Error(const std::string &what) : ndn::Validator::Error(what) {} };
27
28 static const ndn::shared_ptr<ndn::CertificateCache> DefaultCertificateCache;
29 static const ndn::shared_ptr<ndn::SecRuleRelative> DefaultDataRule;
30
31 SyncValidator(const ndn::Name& prefix,
32 const ndn::IdentityCertificate& anchor,
33 ndn::shared_ptr<ndn::Face> face,
34 ndn::shared_ptr<ndn::SecRuleRelative> rule = DefaultDataRule,
35 ndn::shared_ptr<ndn::CertificateCache> certificateCache = DefaultCertificateCache,
36 const int stepLimit = 10);
37
38 virtual
39 ~SyncValidator()
40 {
41 m_face->unsetInterestFilter(m_prefixId);
42 }
43
44 /**
45 * @brief Set the trust anchor
46 *
47 * The anchor should be the participant's own certificate.
48 * This anchor node is the origin of the derived trust graph.
49 * Once the new anchor is set, derive the TrustNode set.
50 *
51 * @param anchor.
52 */
53 inline void
54 setAnchor(const ndn::IdentityCertificate& anchor);
55
56 /**
57 * @brief Add a node into the trust graph.
58 *
59 * The method also create an edge from trust anchor to the node.
60 *
61 * @param introducee.
62 * @return IntroCertificate for the introducee.
63 */
64 inline ndn::shared_ptr<const IntroCertificate>
65 addParticipant(const ndn::IdentityCertificate& introducee);
66
67 /**
68 * @brief Add an edge into the trust graph.
69 *
70 * Create nodes if it is one of the edge's ends and does not exist in the graph.
71 *
72 * @param introCert.
73 */
74 inline void
75 addParticipant(const IntroCertificate& introCert);
76
77#ifdef _TEST
78 bool
79 canTrust(const ndn::Name& certName)
80 {
81 return (m_trustedNodes.find(certName.getPrefix(-1)) != m_trustedNodes.end());
82 }
83#endif //_DEBUG
84
85protected:
86 /***********************
87 * From ndn::Validator *
88 ***********************/
89 virtual void
90 checkPolicy (const ndn::Data& data,
91 int stepCount,
92 const ndn::OnDataValidated& onValidated,
93 const ndn::OnDataValidationFailed& onValidationFailed,
94 std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
95
96 virtual void
97 checkPolicy (const ndn::Interest& interest,
98 int stepCount,
99 const ndn::OnInterestValidated& onValidated,
100 const ndn::OnInterestValidationFailed& onValidationFailed,
101 std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
102private:
103 void
104 deriveTrustNodes();
105
106
107 void
108 onCertificateValidated(const ndn::shared_ptr<const ndn::Data>& signCertificate,
109 const ndn::shared_ptr<const ndn::Data>& data,
110 const ndn::OnDataValidated& onValidated,
111 const ndn::OnDataValidationFailed& onValidationFailed);
112
113 void
114 onCertificateValidationFailed(const ndn::shared_ptr<const ndn::Data>& signCertificate,
115 const std::string& failureInfo,
116 const ndn::shared_ptr<const ndn::Data>& data,
117 const ndn::OnDataValidationFailed& onValidationFailed);
118
119 void
120 onCertInterest (const ndn::Name& prefix, const ndn::Interest& interest);
121
122 void
123 onCertRegisterFailed(const ndn::Name& prefix, const std::string& msg);
124
125private:
126 class IntroNode;
127
128 // Syncprefix
129 ndn::Name m_prefix;
130
131 // The map
132 typedef std::map<const ndn::Name, IntroNode> Nodes;
133 typedef std::map<const ndn::Name, IntroCertificate> Edges;
134 Nodes m_introNodes;
135 Edges m_introCerts;
136
137 // The derived trust info
138 typedef std::map<const ndn::Name, ndn::PublicKey> TrustNodes;
139 ndn::IdentityCertificate m_anchor;
140 TrustNodes m_trustedNodes;
141
142 // others
143 int m_stepLimit;
144 ndn::shared_ptr<ndn::CertificateCache> m_certificateCache;
145 ndn::KeyChain m_keychain;
146 const ndn::RegisteredPrefixId* m_prefixId;
147 ndn::shared_ptr<ndn::SecRuleRelative> m_dataRule;
148
149 class IntroNode
150 {
151 public:
152 typedef std::vector<ndn::Name>::const_iterator const_iterator;
153
154 IntroNode()
155 {}
156
157 IntroNode(const ndn::IdentityCertificate& idCert)
158 : m_nodeName(idCert.getName().getPrefix(-1))
159 {}
160
161 IntroNode(const IntroCertificate& introCert, bool isIntroducer)
162 {
163 if(isIntroducer)
164 {
165 m_nodeName = introCert.getIntroducerName();
166 m_introduceeCerts.push_back(introCert.getName());
167 }
168 else
169 {
170 m_nodeName = introCert.getIntroduceeName();
171 m_introducerCerts.push_back(introCert.getName());
172 }
173 }
174
175 ~IntroNode()
176 {}
177
178 const ndn::Name&
179 name() const
180 {
181 return m_nodeName;
182 }
183
184 const_iterator
185 introducerBegin() const
186 {
187 return m_introducerCerts.begin();
188 }
189
190 const_iterator
191 introducerEnd() const
192 {
193 return m_introducerCerts.end();
194 }
195
196 const_iterator
197 introduceeBegin() const
198 {
199 return m_introduceeCerts.begin();
200 }
201
202 const_iterator
203 introduceeEnd() const
204 {
205 return m_introduceeCerts.end();
206 }
207
208 void
209 addIntroCertAsIntroducer(const ndn::Name& introCertName)
210 {
211 if(std::find(m_introduceeCerts.begin(), m_introduceeCerts.end(), introCertName) == m_introduceeCerts.end())
212 m_introduceeCerts.push_back(introCertName);
213 }
214
215 void
216 addIntroCertAsIntroducee(const ndn::Name& introCertName)
217 {
218 if(std::find(m_introducerCerts.begin(), m_introducerCerts.end(), introCertName) == m_introducerCerts.end())
219 m_introducerCerts.push_back(introCertName);
220 }
221
222 private:
223 ndn::Name m_nodeName;
224 std::vector<ndn::Name> m_introducerCerts;
225 std::vector<ndn::Name> m_introduceeCerts;
226 };
227
228};
229
230inline void
231SyncValidator::setAnchor(const ndn::IdentityCertificate& anchor)
232{
233 m_anchor = anchor;
234
235 // Add anchor into trust graph if it does not exist.
236 IntroNode origin(m_anchor);
237 Nodes::const_iterator nodeIt = m_introNodes.find(origin.name());
238 if(nodeIt == m_introNodes.end())
239 m_introNodes[origin.name()] = origin;
240
241 deriveTrustNodes();
242}
243
244inline void
245SyncValidator::addParticipant(const IntroCertificate& introCert)
246{
247 // Check if the edge has been added before.
248 ndn::Name certName = introCert.getName();
249 Edges::const_iterator edgeIt = m_introCerts.find(certName);
250 if(edgeIt != m_introCerts.end())
251 return; // the edge has been added before.
252
253 m_introCerts[certName] = introCert;
254
255 // Check if the introducer has been added.
256 Nodes::iterator nodeIt = m_introNodes.find(introCert.getIntroducerName());
257 if(nodeIt == m_introNodes.end())
258 {
259 IntroNode node(introCert, true);
260 m_introNodes[node.name()] = node;
261 }
262 else
263 nodeIt->second.addIntroCertAsIntroducer(certName);
264
265 // Check if the introducee has been added.
266 nodeIt = m_introNodes.find(introCert.getIntroduceeName());
267 if(nodeIt == m_introNodes.end())
268 {
269 IntroNode node(introCert, false);
270 m_introNodes[node.name()] = node;
271 }
272 else
273 nodeIt->second.addIntroCertAsIntroducee(certName);
274
275 // Check if the introducer is one of the trusted nodes.
276 TrustNodes::const_iterator trustNodeIt = m_trustedNodes.find(introCert.getIntroducerName());
277 if(trustNodeIt != m_trustedNodes.end() && verifySignature(introCert, trustNodeIt->second))
278 // If the introducee, add it into trusted node set.
279 m_trustedNodes[introCert.getIntroduceeName()] = introCert.getIntroduceeCert().getPublicKeyInfo();
280}
281
282inline ndn::shared_ptr<const IntroCertificate>
283SyncValidator::addParticipant(const ndn::IdentityCertificate& introducee)
284{
285 ndn::shared_ptr<IntroCertificate> introCert = ndn::make_shared<IntroCertificate>(m_prefix, introducee, m_anchor.getName().getPrefix(-1));
286
287 m_keychain.sign(*introCert, m_anchor.getName());
288
289 addParticipant(*introCert);
290
291 return introCert;
292}
293
294} // namespace Sync
295
296#endif //SYNC_VALIDATOR_H