blob: 4b50ef49f1953d158ad14b8d96ee052fb67e00dc [file] [log] [blame]
Yingdi Yu9236c432013-10-18 11:29:25 -07001/* -*- 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
Yingdi Yuf8f572d2014-01-13 11:19:47 -080011#if __clang__
Yingdi Yuf8f572d2014-01-13 11:19:47 -080012#pragma clang diagnostic ignored "-Wtautological-compare"
Yingdi Yuf8f572d2014-01-13 11:19:47 -080013#endif
14
Yingdi Yu9236c432013-10-18 11:29:25 -070015#include "contact-manager.h"
Yingdi Yu348f5ea2014-03-01 14:47:25 -080016#include <QStringList>
Yingdi Yu06f572b2014-03-11 15:46:10 -070017#include <QFile>
Yingdi Yu9236c432013-10-18 11:29:25 -070018
Yingdi Yu4685b1b2013-10-18 17:05:02 -070019#ifndef Q_MOC_RUN
Yingdi Yu348f5ea2014-03-01 14:47:25 -080020#include <ndn-cpp-dev/util/crypto.hpp>
21#include <ndn-cpp-dev/util/io.hpp>
22#include <ndn-cpp-dev/security/sec-rule-relative.hpp>
Yingdi Yufa4ce792014-02-06 18:09:22 -080023#include <ndn-cpp-dev/security/validator-regex.hpp>
Yingdi Yu72781e52013-11-06 23:00:21 -080024#include <cryptopp/base64.h>
Yingdi Yu348f5ea2014-03-01 14:47:25 -080025#include <cryptopp/files.h>
26#include <cryptopp/sha.h>
Yingdi Yu06f572b2014-03-11 15:46:10 -070027#include <cryptopp/filters.h>
Yingdi Yu348f5ea2014-03-01 14:47:25 -080028#include <boost/asio.hpp>
29#include <boost/tokenizer.hpp>
30#include <boost/filesystem.hpp>
Yingdi Yuec3d9a32013-10-18 18:35:09 -070031#include "logging.h"
Yingdi Yu4685b1b2013-10-18 17:05:02 -070032#endif
Yingdi Yu9236c432013-10-18 11:29:25 -070033
34using namespace ndn;
Yingdi Yu76dd8002013-12-24 11:16:32 +080035using namespace std;
Yingdi Yu348f5ea2014-03-01 14:47:25 -080036namespace fs = boost::filesystem;
Yingdi Yu9236c432013-10-18 11:29:25 -070037
Yingdi Yu348f5ea2014-03-01 14:47:25 -080038INIT_LOGGER("chronos.ContactManager");
Yingdi Yuec3d9a32013-10-18 18:35:09 -070039
Yingdi Yufa4ce792014-02-06 18:09:22 -080040namespace chronos{
Yingdi Yu4685b1b2013-10-18 17:05:02 -070041
Yingdi Yu348f5ea2014-03-01 14:47:25 -080042static const uint8_t DNS_RP_SEPARATOR[2] = {0xF0, 0x2E}; // %F0.
43
Yingdi Yufa4ce792014-02-06 18:09:22 -080044ContactManager::ContactManager(shared_ptr<Face> face,
45 QObject* parent)
46 : QObject(parent)
Yingdi Yufa4ce792014-02-06 18:09:22 -080047 , m_face(face)
Yingdi Yu348f5ea2014-03-01 14:47:25 -080048 , m_dnsListenerId(0)
Yingdi Yufa4ce792014-02-06 18:09:22 -080049{
Yingdi Yu76dd8002013-12-24 11:16:32 +080050 initializeSecurity();
Yingdi Yu9236c432013-10-18 11:29:25 -070051}
52
53ContactManager::~ContactManager()
Yingdi Yu6eabbd72013-12-27 08:44:12 +080054{}
Yingdi Yu9236c432013-10-18 11:29:25 -070055
Yingdi Yu348f5ea2014-03-01 14:47:25 -080056// private methods
Yingdi Yu06f572b2014-03-11 15:46:10 -070057shared_ptr<IdentityCertificate>
58ContactManager::loadTrustAnchor()
59{
60 shared_ptr<IdentityCertificate> anchor;
61
62 QFile anchorFile(":/security/anchor.cert");
63
64 if (!anchorFile.open(QIODevice::ReadOnly))
65 {
66 emit warning(QString("Cannot load trust anchor!"));
67
68 return anchor;
69 }
70
71 qint64 fileSize = anchorFile.size();
72 char* buf = new char[fileSize];
73 anchorFile.read(buf, fileSize);
74
75 try
76 {
77 using namespace CryptoPP;
78
79 OBufferStream os;
80 StringSource(reinterpret_cast<const uint8_t*>(buf), fileSize, true, new Base64Decoder(new FileSink(os)));
81 anchor = make_shared<IdentityCertificate>();
82 anchor->wireDecode(Block(os.buf()));
83 }
84 catch(CryptoPP::Exception& e)
85 {
86 emit warning(QString("Cannot load trust anchor!"));
87 }
88 catch(IdentityCertificate::Error& e)
89 {
90 emit warning(QString("Cannot load trust anchor!"));
91 }
92 catch(Block::Error& e)
93 {
94 emit warning(QString("Cannot load trust anchor!"));
95 }
96
97 delete [] buf;
98
99 return anchor;
100}
101
Yingdi Yu76dd8002013-12-24 11:16:32 +0800102void
103ContactManager::initializeSecurity()
104{
Yingdi Yu06f572b2014-03-11 15:46:10 -0700105 shared_ptr<IdentityCertificate> anchor = loadTrustAnchor();
Yingdi Yufa4ce792014-02-06 18:09:22 -0800106
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800107 shared_ptr<ValidatorRegex> validator = make_shared<ValidatorRegex>(m_face);
108 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><ENDORSED>",
109 "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
110 "==", "\\1", "\\1\\2", true));
111 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><><ENDORSEE>",
112 "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
113 "==", "\\1", "\\1\\2", true));
114 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><PROFILE>",
115 "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
116 "==", "\\1", "\\1\\2", true));
117 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
118 "^([^<KEY>]*)<KEY>(<>*<ksk-.*>)<ID-CERT>$",
119 "==", "\\1", "\\1\\2", true));
120 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
121 "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>$",
122 ">", "\\1\\2", "\\1", true));
123 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
124 "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
125 "==", "\\1", "\\1\\2", true));
126 validator->addDataVerificationRule(make_shared<SecRuleRelative>("^(<>*)$",
127 "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
128 ">", "\\1", "\\1\\2", true));
129 validator->addTrustAnchor(anchor);
130 m_validator = validator;
Yingdi Yu76dd8002013-12-24 11:16:32 +0800131}
132
133void
Yingdi Yufa4ce792014-02-06 18:09:22 -0800134ContactManager::fetchCollectEndorse(const Name& identity)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800135{
136 Name interestName = identity;
137 interestName.append("DNS").append("ENDORSED");
138
Yingdi Yu76dd8002013-12-24 11:16:32 +0800139 Interest interest(interestName);
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800140 interest.setInterestLifetime(1000);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800141 interest.setMustBeFresh(true);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800142
Yingdi Yufa4ce792014-02-06 18:09:22 -0800143 OnDataValidated onValidated = bind(&ContactManager::onDnsCollectEndorseValidated, this, _1, identity);
144 OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsCollectEndorseValidationFailed, this, _1, identity);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800145 TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsCollectEndorseTimeoutNotify, this, _1, identity);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800146
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800147 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800148}
149
150void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800151ContactManager::fetchEndorseCertificateInternal(const Name& identity, int certIndex)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800152{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800153 shared_ptr<EndorseCollection> endorseCollection = m_bufferedContacts[identity].m_endorseCollection;
154
155 if(certIndex >= endorseCollection->endorsement_size())
156 prepareEndorseInfo(identity);
157
158 Name interestName(endorseCollection->endorsement(certIndex).certname());
159
Yingdi Yu76dd8002013-12-24 11:16:32 +0800160 Interest interest(interestName);
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800161 interest.setInterestLifetime(1000);
Yingdi Yufa4ce792014-02-06 18:09:22 -0800162 interest.setMustBeFresh(true);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800163
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800164 m_face->expressInterest(interest,
165 bind(&ContactManager::onEndorseCertificateInternal,
166 this, _1, _2, identity, certIndex,
167 endorseCollection->endorsement(certIndex).hash()),
168 bind(&ContactManager::onEndorseCertificateInternalTimeout,
169 this, _1, identity, certIndex));
Yingdi Yu76dd8002013-12-24 11:16:32 +0800170}
171
Yingdi Yu76dd8002013-12-24 11:16:32 +0800172void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800173ContactManager::prepareEndorseInfo(const Name& identity)
Yingdi Yu76dd8002013-12-24 11:16:32 +0800174{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800175 // _LOG_DEBUG("prepareEndorseInfo");
176 const Profile& profile = m_bufferedContacts[identity].m_selfEndorseCert->getProfile();
Yingdi Yu76dd8002013-12-24 11:16:32 +0800177
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800178 shared_ptr<EndorseInfo> endorseInfo = make_shared<EndorseInfo>();
179 m_bufferedContacts[identity].m_endorseInfo = endorseInfo;
180
181 Profile::const_iterator pIt = profile.begin();
182 Profile::const_iterator pEnd = profile.end();
183
184 map<string, int> endorseCount;
185 for(; pIt != pEnd; pIt++)
186 {
187 // _LOG_DEBUG("prepareEndorseInfo: profile[" << pIt->first << "]: " << pIt->second);
188 endorseCount[pIt->first] = 0;
189 }
190
191 int endorseCertCount = 0;
192
193 vector<shared_ptr<EndorseCertificate> >::const_iterator cIt = m_bufferedContacts[identity].m_endorseCertList.begin();
194 vector<shared_ptr<EndorseCertificate> >::const_iterator cEnd = m_bufferedContacts[identity].m_endorseCertList.end();
195
196 for(; cIt != cEnd; cIt++, endorseCertCount++)
197 {
198 shared_ptr<Contact> contact = getContact((*cIt)->getSigner().getPrefix(-1));
199 if(!static_cast<bool>(contact))
200 continue;
201
202 if(!contact->isIntroducer()
203 || !contact->canBeTrustedFor(profile.getIdentityName()))
204 continue;
205
206 if(!Validator::verifySignature(**cIt, contact->getPublicKey()))
207 continue;
208
209 const Profile& tmpProfile = (*cIt)->getProfile();
210 if(tmpProfile != profile)
211 continue;
212
213 const vector<string>& endorseList = (*cIt)->getEndorseList();
214 vector<string>::const_iterator eIt = endorseList.begin();
215 for(; eIt != endorseList.end(); eIt++)
216 endorseCount[*eIt] += 1;
217 }
218
219 pIt = profile.begin();
220 pEnd = profile.end();
221 for(; pIt != pEnd; pIt++)
222 {
223 EndorseInfo::Endorsement* endorsement = endorseInfo->add_endorsement();
224 endorsement->set_type(pIt->first);
225 endorsement->set_value(pIt->second);
226 stringstream ss;
227 ss << endorseCount[pIt->first] << "/" << endorseCertCount;
228 endorsement->set_endorse(ss.str());
229 }
230
231 emit contactEndorseInfoReady (*endorseInfo);
232}
233
234void
235ContactManager::onDnsSelfEndorseCertValidated(const shared_ptr<const Data>& data,
236 const Name& identity)
237{
238 try
239 {
240 Data plainData;
241 plainData.wireDecode(data->getContent().blockFromValue());
242 shared_ptr<EndorseCertificate> selfEndorseCertificate = make_shared<EndorseCertificate>(boost::cref(plainData));
243 if(Validator::verifySignature(plainData, selfEndorseCertificate->getPublicKeyInfo()))
244 {
245 m_bufferedContacts[identity].m_selfEndorseCert = selfEndorseCertificate;
246 fetchCollectEndorse(identity);
247 }
248 else
249 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
250 }
251 catch(Block::Error& e)
252 {
253 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
254 }
255 catch(Data::Error& e)
256 {
257 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
258 }
259 catch(EndorseCertificate::Error& e)
260 {
261 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
262 }
263}
264
265void
266ContactManager::onDnsSelfEndorseCertValidationFailed(const shared_ptr<const Data>& data,
267 const Name& identity)
268{
269 // If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
270 // but let's stay with failure for now.
271 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
272}
273
274void
275ContactManager::onDnsSelfEndorseCertTimeoutNotify(const Interest& interest,
276 const Name& identity)
277{
278 // If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
279 // but let's stay with failure for now.
280 emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
281}
282
283void
284ContactManager::onDnsCollectEndorseValidated(const shared_ptr<const Data>& data,
285 const Name& identity)
286{
287 shared_ptr<EndorseCollection> endorseCollection = make_shared<EndorseCollection>();
288 if(!endorseCollection->ParseFromArray(data->getContent().value(), data->getContent().value_size()))
289 {
290 m_bufferedContacts[identity].m_endorseCollection = endorseCollection;
291 fetchEndorseCertificateInternal(identity, 0);
292 }
293 else
294 prepareEndorseInfo(identity);
295}
296
297void
298ContactManager::onDnsCollectEndorseValidationFailed(const shared_ptr<const Data>& data,
299 const Name& identity)
300{
301 prepareEndorseInfo(identity);
302}
303
304void
305ContactManager::onDnsCollectEndorseTimeoutNotify(const Interest& interest,
306 const Name& identity)
307{
308 // _LOG_DEBUG("onDnsCollectEndorseTimeoutNotify: " << interest.getName());
309 prepareEndorseInfo(identity);
310}
311
312void
313ContactManager::onEndorseCertificateInternal(const Interest& interest,
314 Data& data,
315 const Name& identity,
316 int certIndex,
317 string hash)
318{
319 stringstream ss;
320 {
321 using namespace CryptoPP;
322
323 SHA256 hash;
324 StringSource(data.wireEncode().wire(), data.wireEncode().size(), true,
325 new HashFilter(hash, new FileSink(ss)));
326 }
327
328 if(ss.str() == hash)
329 {
330 shared_ptr<EndorseCertificate> endorseCertificate = make_shared<EndorseCertificate>(boost::cref(data));
331 m_bufferedContacts[identity].m_endorseCertList.push_back(endorseCertificate);
332 }
333
334 fetchEndorseCertificateInternal(identity, certIndex+1);
335}
336
337void
338ContactManager::onEndorseCertificateInternalTimeout(const Interest& interest,
339 const Name& identity,
340 int certIndex)
341{
342 fetchEndorseCertificateInternal(identity, certIndex+1);
343}
344
345void
346ContactManager::collectEndorsement()
347{
348 {
349 boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
350 m_collectCount = m_contactList.size();
351
352 ContactList::iterator it = m_contactList.begin();
353 ContactList::iterator end = m_contactList.end();
354
355 for(; it != end ; it++)
356 {
357 Name interestName = (*it)->getNameSpace();
358 interestName.append("DNS").append(m_identity.wireEncode()).append("ENDORSEE");
359
360 Interest interest(interestName);
361 interest.setInterestLifetime(1000);
362
363 OnDataValidated onValidated = bind(&ContactManager::onDnsEndorseeValidated, this, _1);
364 OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsEndorseeValidationFailed, this, _1);
365 TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsEndorseeTimeoutNotify, this, _1);
366
367 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
368 }
Yingdi Yu76dd8002013-12-24 11:16:32 +0800369 }
370}
371
372void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800373ContactManager::onDnsEndorseeValidated(const shared_ptr<const Data>& data)
Yingdi Yuae8217c2013-11-09 00:03:26 -0800374{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800375 Data endorseData;
376 endorseData.wireDecode(data->getContent().blockFromValue());
Yingdi Yu76dd8002013-12-24 11:16:32 +0800377
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800378 EndorseCertificate endorseCertificate(endorseData);
379 m_contactStorage->updateCollectEndorse(endorseCertificate);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800380
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800381 decreaseCollectStatus();
Yingdi Yu76dd8002013-12-24 11:16:32 +0800382}
Yingdi Yuae8217c2013-11-09 00:03:26 -0800383
384void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800385ContactManager::onDnsEndorseeValidationFailed(const shared_ptr<const Data>& data)
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700386{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800387 decreaseCollectStatus();
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700388}
389
Yingdi Yub2e747d2013-11-05 23:06:43 -0800390void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800391ContactManager::onDnsEndorseeTimeoutNotify(const Interest& interest)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800392{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800393 decreaseCollectStatus();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800394}
395
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800396void
397ContactManager::decreaseCollectStatus()
Yingdi Yub2e747d2013-11-05 23:06:43 -0800398{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800399 int count;
400 {
401 boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
402 m_collectCount--;
403 count = m_collectCount;
404 }
Yingdi Yub2e747d2013-11-05 23:06:43 -0800405
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800406 if(count == 0)
407 publishCollectEndorsedDataInDNS();
408}
Yingdi Yub2e747d2013-11-05 23:06:43 -0800409
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800410void
411ContactManager::publishCollectEndorsedDataInDNS()
412{
413 Name dnsName = m_identity;
414 dnsName.append("DNS").append("ENDORSED").appendVersion();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800415
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800416 Data data;
417 data.setName(dnsName);
418
419 EndorseCollection endorseCollection;
420 m_contactStorage->getCollectEndorse(endorseCollection);
421
422 OBufferStream os;
423 endorseCollection.SerializeToOstream(&os);
424
425 data.setContent(os.buf());
426 m_keyChain.signByIdentity(data, m_identity);
427
428 m_contactStorage->updateDnsOthersEndorse(data);
429 m_face->put(data);
430}
431
432void
433ContactManager::onIdentityCertValidated(const shared_ptr<const Data>& data)
434{
435 shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(boost::cref(*data));
436 m_bufferedIdCerts[cert->getName()] = cert;
437 decreaseIdCertCount();
438}
439
440void
441ContactManager::onIdentityCertValidationFailed(const shared_ptr<const Data>& data)
442{
443 _LOG_DEBUG("ContactManager::onIdentityCertValidationFailed " << data->getName());
444 decreaseIdCertCount();
445}
446
447void
448ContactManager::onIdentityCertTimeoutNotify(const Interest& interest)
449{
450 _LOG_DEBUG("ContactManager::onIdentityCertTimeoutNotify: " << interest.getName());
451 decreaseIdCertCount();
452}
453
454void
455ContactManager::decreaseIdCertCount()
456{
457 int count;
458 {
459 boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
460 m_idCertCount--;
461 count = m_idCertCount;
462 }
463
464 if(count == 0)
465 {
466 QStringList certNameList;
467 QStringList nameList;
468
469 BufferedIdCerts::const_iterator it = m_bufferedIdCerts.begin();
470 BufferedIdCerts::const_iterator end = m_bufferedIdCerts.end();
471 for(; it != end; it++)
472 {
473 certNameList << QString::fromStdString(it->second->getName().toUri());
474 Profile profile(*(it->second));
475 nameList << QString::fromStdString(profile.get("name"));
476 }
477
478 emit idCertNameListReady(certNameList);
479 emit nameListReady(nameList);
480 }
Yingdi Yub2e747d2013-11-05 23:06:43 -0800481}
482
Yingdi Yu76dd8002013-12-24 11:16:32 +0800483shared_ptr<EndorseCertificate>
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800484ContactManager::getSignedSelfEndorseCertificate(const Profile& profile)
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700485{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800486 Name certificateName = m_keyChain.getDefaultCertificateNameForIdentity(m_identity);
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700487
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800488 shared_ptr<IdentityCertificate> signingCert = m_keyChain.getCertificate(certificateName);
Yingdi Yu72781e52013-11-06 23:00:21 -0800489
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700490 vector<string> endorseList;
491 Profile::const_iterator it = profile.begin();
492 for(; it != profile.end(); it++)
493 endorseList.push_back(it->first);
494
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800495 shared_ptr<EndorseCertificate> selfEndorseCertificate =
496 shared_ptr<EndorseCertificate>(new EndorseCertificate(*signingCert, profile, endorseList));
497
498 m_keyChain.sign(*selfEndorseCertificate, certificateName);
499
500 return selfEndorseCertificate;
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700501}
502
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700503void
Yingdi Yu76dd8002013-12-24 11:16:32 +0800504ContactManager::publishSelfEndorseCertificateInDNS(const EndorseCertificate& selfEndorseCertificate)
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700505{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800506 Name dnsName = m_identity;
Yingdi Yufa4ce792014-02-06 18:09:22 -0800507 dnsName.append("DNS").append("PROFILE").appendVersion();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800508
509 Data data;
Yingdi Yu76dd8002013-12-24 11:16:32 +0800510 data.setName(dnsName);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800511 data.setContent(selfEndorseCertificate.wireEncode());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800512 data.setFreshnessPeriod(1000);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800513
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800514 m_keyChain.signByIdentity(data, m_identity);
515
516 m_contactStorage->updateDnsSelfProfileData(data);
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800517 m_face->put(data);
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700518}
519
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800520shared_ptr<EndorseCertificate>
521ContactManager::generateEndorseCertificate(const Name& identity)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800522{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800523 shared_ptr<Contact> contact = getContact(identity);
524 if(!static_cast<bool>(contact))
525 return shared_ptr<EndorseCertificate>();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800526
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800527 Name signerKeyName = m_keyChain.getDefaultKeyNameForIdentity(m_identity);
528
529 vector<string> endorseList;
530 m_contactStorage->getEndorseList(identity, endorseList);
531
532 shared_ptr<EndorseCertificate> cert =
533 shared_ptr<EndorseCertificate>(new EndorseCertificate(contact->getPublicKeyName(),
534 contact->getPublicKey(),
535 contact->getNotBefore(),
536 contact->getNotAfter(),
537 signerKeyName,
538 contact->getProfile(),
539 endorseList));
540 m_keyChain.signByIdentity(*cert, m_identity);
541 return cert;
542
543}
544
545void
546ContactManager::publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate)
547{
Yingdi Yufa4ce792014-02-06 18:09:22 -0800548 Name endorsee = endorseCertificate.getPublicKeyName().getPrefix(-1);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800549 Name dnsName = m_identity;
550 dnsName.append("DNS")
551 .append(endorsee.wireEncode())
552 .append("ENDORSEE")
553 .appendVersion();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800554
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800555 Data data;
Yingdi Yu76dd8002013-12-24 11:16:32 +0800556 data.setName(dnsName);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800557 data.setContent(endorseCertificate.wireEncode());
Yingdi Yub2e747d2013-11-05 23:06:43 -0800558
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800559 m_keyChain.signByIdentity(data, m_identity);
560
561 m_contactStorage->updateDnsEndorseOthers(data, dnsName.get(-3).toEscapedString());
Yingdi Yuf8f572d2014-01-13 11:19:47 -0800562 m_face->put(data);
Yingdi Yub2e747d2013-11-05 23:06:43 -0800563}
564
565void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800566ContactManager::sendInterest(const Interest& interest,
567 const OnDataValidated& onValidated,
568 const OnDataValidationFailed& onValidationFailed,
569 const TimeoutNotify& timeoutNotify,
570 int retry /* = 1 */)
Yingdi Yub2e747d2013-11-05 23:06:43 -0800571{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800572 m_face->expressInterest(interest,
573 bind(&ContactManager::onTargetData,
574 this, _1, _2, onValidated, onValidationFailed),
575 bind(&ContactManager::onTargetTimeout,
576 this, _1, retry, onValidated, onValidationFailed, timeoutNotify));
577}
Yingdi Yu76dd8002013-12-24 11:16:32 +0800578
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800579void
580ContactManager::onTargetData(const Interest& interest,
581 const Data& data,
582 const OnDataValidated& onValidated,
583 const OnDataValidationFailed& onValidationFailed)
584{
585 // _LOG_DEBUG("On receiving data: " << data.getName());
586 m_validator->validate(data, onValidated, onValidationFailed);
587}
Yingdi Yub2e747d2013-11-05 23:06:43 -0800588
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800589void
590ContactManager::onTargetTimeout(const Interest& interest,
591 int retry,
592 const OnDataValidated& onValidated,
593 const OnDataValidationFailed& onValidationFailed,
594 const TimeoutNotify& timeoutNotify)
595{
596 // _LOG_DEBUG("On interest timeout: " << interest.getName());
597 if(retry > 0)
598 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, retry-1);
599 else
600 timeoutNotify(interest);
601}
602
603void
604ContactManager::onDnsInterest(const Name& prefix, const Interest& interest)
605{
606 const Name& interestName = interest.getName();
607 shared_ptr<Data> data;
608
609 if(interestName.size() <= prefix.size())
610 return;
611
612 if(interestName.size() == (prefix.size()+1))
Yingdi Yub2e747d2013-11-05 23:06:43 -0800613 {
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800614 data = m_contactStorage->getDnsData("N/A", interestName.get(prefix.size()).toEscapedString());
615 if(static_cast<bool>(data))
616 m_face->put(*data);
617 return;
Yingdi Yub2e747d2013-11-05 23:06:43 -0800618 }
Yingdi Yub2e747d2013-11-05 23:06:43 -0800619
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800620 if(interestName.size() == (prefix.size()+2))
621 {
622 data = m_contactStorage->getDnsData(interestName.get(prefix.size()).toEscapedString(),
623 interestName.get(prefix.size()+1).toEscapedString());
624 if(static_cast<bool>(data))
625 m_face->put(*data);
626 return;
627 }
628}
Yingdi Yub2e747d2013-11-05 23:06:43 -0800629
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800630void
631ContactManager::onDnsRegisterFailed(const Name& prefix, const string& failInfo)
632{
633 emit warning(QString(failInfo.c_str()));
634}
635
636
637// public slots
638void
639ContactManager::onIdentityUpdated(const QString& identity)
640{
641 m_identity = Name(identity.toStdString());
642
643 m_contactStorage = make_shared<ContactStorage>(m_identity);
644
645 if(m_dnsListenerId)
646 m_face->unsetInterestFilter(m_dnsListenerId);
647
648 Name dnsPrefix;
649 dnsPrefix.append(m_identity).append("DNS");
650 m_dnsListenerId = m_face->setInterestFilter(dnsPrefix,
651 bind(&ContactManager::onDnsInterest, this, _1, _2),
652 bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));
653
654 m_contactList.clear();
655 m_contactStorage->getAllContacts(m_contactList);
656
657 m_bufferedContacts.clear();
658
659 collectEndorsement();
Yingdi Yub2e747d2013-11-05 23:06:43 -0800660}
661
Yingdi Yuae8217c2013-11-09 00:03:26 -0800662void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800663ContactManager::onFetchContactInfo(const QString& identity)
Yingdi Yuae8217c2013-11-09 00:03:26 -0800664{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800665 // try to fetch self-endorse-certificate via DNS PROFILE first.
666 Name identityName(identity.toStdString());
667 Name interestName;
668 interestName.append(identityName).append("DNS").append("PROFILE");
Yingdi Yu76dd8002013-12-24 11:16:32 +0800669
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800670 // _LOG_DEBUG("onFetchContactInfo " << identity.toStdString() << " profile: " << interestName);
671
672 Interest interest(interestName);
673 interest.setInterestLifetime(1000);
674 interest.setMustBeFresh(true);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800675
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800676 OnDataValidated onValidated = bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identityName);
677 OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsSelfEndorseCertValidationFailed, this, _1, identityName);
678 TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsSelfEndorseCertTimeoutNotify, this, _1, identityName);
Yingdi Yu76dd8002013-12-24 11:16:32 +0800679
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800680 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
681}
Yingdi Yu76dd8002013-12-24 11:16:32 +0800682
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800683void
684ContactManager::onAddFetchedContact(const QString& identity)
685{
686 // _LOG_DEBUG("onAddFetchedContact");
687
688 Name identityName(identity.toStdString());
689
690 BufferedContacts::const_iterator it = m_bufferedContacts.find(identityName);
691 if(it != m_bufferedContacts.end())
692 {
693 Contact contact(*(it->second.m_selfEndorseCert));
694 // _LOG_DEBUG("onAddFetchedContact: contact ready");
695 try
696 {
697 m_contactStorage->addContact(contact);
698 m_bufferedContacts.erase(identityName);
699
700 m_contactList.clear();
701 m_contactStorage->getAllContacts(m_contactList);
702
703 onWaitForContactList();
704 }
705 catch(ContactStorage::Error& e)
706 {
707 emit warning(QString::fromStdString(e.what()));
708 }
709 }
710 else
711 {
712 emit warning(QString("Failure: no information of %1").arg(identity));
713 }
714}
715
716void
717ContactManager::onUpdateProfile()
718{
719 // Get current profile;
720 shared_ptr<Profile> newProfile = m_contactStorage->getSelfProfile();
721 if(!static_cast<bool>(newProfile))
Yingdi Yuae8217c2013-11-09 00:03:26 -0800722 return;
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800723
724 _LOG_DEBUG("ContactManager::onUpdateProfile: getProfile");
725
726 shared_ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(*newProfile);
727
728 m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate);
729
730 publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
731}
732
733void
734ContactManager::onRefreshBrowseContact()
735{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800736 std::vector<std::string> bufferedIdCertNames;
737 try
738 {
739 using namespace boost::asio::ip;
740 tcp::iostream request_stream;
741 request_stream.expires_from_now(boost::posix_time::milliseconds(5000));
742 request_stream.connect("ndncert.named-data.net","80");
743 if(!request_stream)
744 {
745 emit warning(QString::fromStdString("Fail to fetch certificate directory! #1"));
746 return;
747 }
748
749 request_stream << "GET /cert/list/ HTTP/1.0\r\n";
750 request_stream << "Host: ndncert.named-data.net\r\n\r\n";
751 request_stream.flush();
752
753 string line1;
754 std::getline(request_stream,line1);
755 if (!request_stream)
756 {
757 emit warning(QString::fromStdString("Fail to fetch certificate directory! #2"));
758 return;
759 }
760
761 std::stringstream response_stream(line1);
762 std::string http_version;
763 response_stream >> http_version;
764 unsigned int status_code;
765 response_stream >> status_code;
766 std::string status_message;
767 std::getline(response_stream,status_message);
768
769 if (!response_stream||http_version.substr(0,5)!="HTTP/")
770 {
771 emit warning(QString::fromStdString("Fail to fetch certificate directory! #3"));
772 return;
773 }
774 if (status_code!=200)
775 {
776 emit warning(QString::fromStdString("Fail to fetch certificate directory! #4"));
777 return;
778 }
779 vector<string> headers;
780 std::string header;
781 while (std::getline(request_stream, header) && header != "\r")
782 headers.push_back(header);
783
784 std::istreambuf_iterator<char> stream_iter (request_stream);
785 std::istreambuf_iterator<char> end_of_stream;
786
787 typedef boost::tokenizer< boost::escaped_list_separator<char>, std::istreambuf_iterator<char> > tokenizer_t;
788 tokenizer_t certItems (stream_iter, end_of_stream,boost::escaped_list_separator<char>('\\', '\n', '"'));
789
790 for (tokenizer_t::iterator it = certItems.begin(); it != certItems.end (); it++)
791 if (!it->empty())
792 bufferedIdCertNames.push_back(*it);
793 }
794 catch(std::exception &e)
795 {
796 emit warning(QString::fromStdString("Fail to fetch certificate directory! #N"));
797 }
798
799 {
800 boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
801 m_idCertCount = bufferedIdCertNames.size();
Yingdi Yuae8217c2013-11-09 00:03:26 -0800802 }
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800803 m_bufferedIdCerts.clear();
804
805 std::vector<std::string>::const_iterator it = bufferedIdCertNames.begin();
806 std::vector<std::string>::const_iterator end = bufferedIdCertNames.end();
807 for(; it != end; it++)
808 {
809 Name certName(*it);
810
811 Interest interest(certName);
812 interest.setInterestLifetime(1000);
813 interest.setMustBeFresh(true);
814
815 OnDataValidated onValidated = bind(&ContactManager::onIdentityCertValidated, this, _1);
816 OnDataValidationFailed onValidationFailed = bind(&ContactManager::onIdentityCertValidationFailed, this, _1);
817 TimeoutNotify timeoutNotify = bind(&ContactManager::onIdentityCertTimeoutNotify, this, _1);
818
819 sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
820 }
821
Yingdi Yuae8217c2013-11-09 00:03:26 -0800822}
823
Yingdi Yu72232692013-11-12 17:50:21 -0800824void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800825ContactManager::onFetchIdCert(const QString& qCertName)
Yingdi Yu72232692013-11-12 17:50:21 -0800826{
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800827 Name certName(qCertName.toStdString());
828 if(m_bufferedIdCerts.find(certName) != m_bufferedIdCerts.end())
829 {
830 emit idCertReady(*m_bufferedIdCerts[certName]);
831 }
Yingdi Yu72232692013-11-12 17:50:21 -0800832}
Yingdi Yuae8217c2013-11-09 00:03:26 -0800833
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800834void
835ContactManager::onAddFetchedContactIdCert(const QString& qCertName)
836{
837 Name certName(qCertName.toStdString());
838 Name identity = IdentityCertificate::certificateNameToPublicKeyName(certName).getPrefix(-1);
839
840 BufferedIdCerts::const_iterator it = m_bufferedIdCerts.find(certName);
841 if(it != m_bufferedIdCerts.end())
842 {
843 Contact contact(*it->second);
844 try
845 {
846 m_contactStorage->addContact(contact);
847 m_bufferedIdCerts.erase(certName);
848
849 m_contactList.clear();
850 m_contactStorage->getAllContacts(m_contactList);
851
852 onWaitForContactList();
853 }
854 catch(ContactStorage::Error& e)
855 {
856 emit warning(QString::fromStdString(e.what()));
857 }
858 }
859 else
860 emit warning(QString("Failure: no information of %1").arg(QString::fromStdString(identity.toUri())));
861}
862
863void
864ContactManager::onWaitForContactList()
865{
866 ContactList::const_iterator it = m_contactList.begin();
867 ContactList::const_iterator end = m_contactList.end();
868
869 QStringList aliasList;
870 QStringList idList;
871 for(; it != end; it++)
872 {
873 aliasList << QString((*it)->getAlias().c_str());
874 idList << QString((*it)->getNameSpace().toUri().c_str());
875 }
876
877 emit contactAliasListReady(aliasList);
878 emit contactIdListReady(idList);
879}
880
881void
882ContactManager::onWaitForContactInfo(const QString& identity)
883{
884 ContactList::const_iterator it = m_contactList.begin();
885 ContactList::const_iterator end = m_contactList.end();
886
887 for(; it != end; it++)
888 if((*it)->getNameSpace().toUri() == identity.toStdString())
889 emit contactInfoReady(QString((*it)->getNameSpace().toUri().c_str()),
890 QString((*it)->getName().c_str()),
891 QString((*it)->getInstitution().c_str()),
892 (*it)->isIntroducer());
893}
894
895void
896ContactManager::onRemoveContact(const QString& identity)
897{
898 m_contactStorage->removeContact(Name(identity.toStdString()));
899 m_contactList.clear();
900 m_contactStorage->getAllContacts(m_contactList);
901
902 onWaitForContactList();
903}
904
905void
906ContactManager::onUpdateAlias(const QString& identity, const QString& alias)
907{
908 m_contactStorage->updateAlias(Name(identity.toStdString()), alias.toStdString());
909 m_contactList.clear();
910 m_contactStorage->getAllContacts(m_contactList);
911
912 onWaitForContactList();
913}
914
915void
916ContactManager::onUpdateIsIntroducer(const QString& identity, bool isIntroducer)
917{
918 m_contactStorage->updateIsIntroducer(Name(identity.toStdString()), isIntroducer);
919}
920
921void
922ContactManager::onUpdateEndorseCertificate(const QString& identity)
923{
924 Name identityName(identity.toStdString());
925 shared_ptr<EndorseCertificate> newEndorseCertificate = generateEndorseCertificate(identityName);
926
927 if(!static_cast<bool>(newEndorseCertificate))
928 return;
929
930 m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identityName);
931
932 publishEndorseCertificateInDNS(*newEndorseCertificate);
933}
934
935} // namespace chronos
Yingdi Yufa4ce792014-02-06 18:09:22 -0800936
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700937
938#if WAF
939#include "contact-manager.moc"
940#include "contact-manager.cpp.moc"
941#endif